r13316: Let the carnage begin....
authorGerald Carter <jerry@samba.org>
Fri, 3 Feb 2006 22:19:41 +0000 (22:19 +0000)
committerGerald (Jerry) Carter <jerry@samba.org>
Wed, 10 Oct 2007 16:06:23 +0000 (11:06 -0500)
Sync with trunk as off r13315
(This used to be commit 17e63ac4ed8325c0d44fe62b2442449f3298559f)

185 files changed:
source3/Makefile.in
source3/auth/auth.c
source3/auth/auth_builtin.c
source3/auth/auth_compat.c
source3/auth/auth_domain.c
source3/auth/auth_ntlmssp.c
source3/auth/auth_rhosts.c
source3/auth/auth_sam.c
source3/auth/auth_script.c
source3/auth/auth_server.c
source3/auth/auth_unix.c
source3/auth/auth_util.c
source3/auth/auth_winbind.c
source3/configure.in
source3/groupdb/mapping.c
source3/include/ads.h
source3/include/auth.h
source3/include/doserr.h
source3/include/event.h [new file with mode: 0644]
source3/include/gpo.h [new file with mode: 0644]
source3/include/idmap.h
source3/include/includes.h
source3/include/local.h
source3/include/messages.h
source3/include/nt_status.h
source3/include/passdb.h
source3/include/rpc_dfs.h
source3/include/rpc_lsa.h
source3/include/rpc_netlogon.h
source3/include/rpc_samr.h
source3/include/secrets.h
source3/include/smb.h
source3/include/smbldap.h
source3/intl/lang_tdb.c
source3/lib/dummysmbd.c
source3/lib/events.c [new file with mode: 0644]
source3/lib/genrand.c
source3/lib/messages.c
source3/lib/pam_errors.c
source3/lib/pidfile.c
source3/lib/readline.c
source3/lib/secdesc.c
source3/lib/sharesec.c [new file with mode: 0644]
source3/lib/smbldap.c
source3/lib/smbldap_util.c
source3/lib/system_smbd.c
source3/lib/username.c
source3/lib/util.c
source3/lib/util_file.c
source3/lib/util_pw.c
source3/lib/util_sid.c
source3/lib/util_str.c
source3/lib/util_unistr.c
source3/libads/gpo.c [new file with mode: 0644]
source3/libads/gpo_util.c [new file with mode: 0644]
source3/libads/kerberos.c
source3/libads/krb5_errs.c [new file with mode: 0644]
source3/libads/krb5_setpw.c
source3/libads/ldap.c
source3/libads/sasl.c
source3/libmsrpc/cac_lsarpc.c
source3/libsmb/cliconnect.c
source3/libsmb/clidfs.c
source3/libsmb/clientgen.c
source3/libsmb/clikrb5.c
source3/libsmb/clilist.c
source3/libsmb/clispnego.c
source3/libsmb/conncache.c
source3/libsmb/errormap.c
source3/libsmb/gpo.c [new file with mode: 0644]
source3/libsmb/libsmbclient.c
source3/libsmb/passchange.c
source3/nsswitch/pam_winbind.c
source3/nsswitch/pam_winbind.h
source3/nsswitch/wb_client.c
source3/nsswitch/wbinfo.c
source3/nsswitch/winbindd.c
source3/nsswitch/winbindd.h
source3/nsswitch/winbindd_ads.c
source3/nsswitch/winbindd_cache.c
source3/nsswitch/winbindd_cm.c
source3/nsswitch/winbindd_cred_cache.c [new file with mode: 0644]
source3/nsswitch/winbindd_creds.c [new file with mode: 0644]
source3/nsswitch/winbindd_dual.c
source3/nsswitch/winbindd_group.c
source3/nsswitch/winbindd_misc.c
source3/nsswitch/winbindd_nss.h
source3/nsswitch/winbindd_pam.c
source3/nsswitch/winbindd_passdb.c
source3/nsswitch/winbindd_reconnect.c
source3/nsswitch/winbindd_rpc.c
source3/nsswitch/winbindd_sid.c
source3/nsswitch/winbindd_user.c
source3/nsswitch/winbindd_util.c
source3/pam_smbpass/pam_smb_auth.c
source3/pam_smbpass/pam_smb_passwd.c
source3/pam_smbpass/support.c
source3/param/loadparm.c
source3/param/params.c
source3/passdb/lookup_sid.c
source3/passdb/machine_sid.c
source3/passdb/passdb.c
source3/passdb/pdb_get_set.c
source3/passdb/pdb_interface.c
source3/passdb/pdb_ldap.c
source3/passdb/pdb_nds.c
source3/passdb/pdb_smbpasswd.c
source3/passdb/pdb_tdb.c
source3/passdb/secrets.c
source3/passdb/util_builtin.c
source3/passdb/util_unixsids.c [new file with mode: 0644]
source3/passdb/util_wellknown.c
source3/printing/nt_printing.c
source3/printing/print_generic.c
source3/python/py_lsa.c
source3/rpc_client/cli_dfs.c
source3/rpc_client/cli_lsarpc.c
source3/rpc_client/cli_netlogon.c
source3/rpc_client/cli_pipe.c
source3/rpc_client/cli_samr.c
source3/rpc_parse/parse_dfs.c
source3/rpc_parse/parse_lsa.c
source3/rpc_parse/parse_net.c
source3/rpc_parse/parse_prs.c
source3/rpc_parse/parse_rpc.c
source3/rpc_parse/parse_samr.c
source3/rpc_server/srv_dfs.c
source3/rpc_server/srv_dfs_nt.c
source3/rpc_server/srv_lsa_nt.c
source3/rpc_server/srv_netlog_nt.c
source3/rpc_server/srv_pipe.c
source3/rpc_server/srv_pipe_hnd.c
source3/rpc_server/srv_samr_nt.c
source3/rpc_server/srv_spoolss_nt.c
source3/rpc_server/srv_srvsvc_nt.c
source3/rpcclient/cmd_dfs.c
source3/rpcclient/cmd_lsarpc.c
source3/rpcclient/cmd_samr.c
source3/sam/idmap.c
source3/sam/idmap_ad.c
source3/sam/idmap_ldap.c
source3/sam/idmap_rid.c
source3/sam/idmap_smbldap.c
source3/sam/idmap_tdb.c
source3/sam/idmap_util.c
source3/script/installman.sh
source3/script/installswat.sh
source3/smbd/chgpasswd.c
source3/smbd/conn.c
source3/smbd/lanman.c
source3/smbd/msdfs.c
source3/smbd/ntquotas.c
source3/smbd/nttrans.c
source3/smbd/open.c
source3/smbd/password.c
source3/smbd/posix_acls.c
source3/smbd/process.c
source3/smbd/sec_ctx.c
source3/smbd/server.c
source3/smbd/service.c
source3/smbd/sesssetup.c
source3/smbd/share_access.c [new file with mode: 0644]
source3/smbd/uid.c
source3/utils/net.c
source3/utils/net.h
source3/utils/net_ads_gpo.c [new file with mode: 0644]
source3/utils/net_groupmap.c
source3/utils/net_help.c
source3/utils/net_lookup.c
source3/utils/net_rpc.c
source3/utils/net_rpc_rights.c
source3/utils/net_rpc_samsync.c
source3/utils/net_rpc_shell.c [new file with mode: 0644]
source3/utils/net_sam.c [new file with mode: 0644]
source3/utils/net_usershare.c [new file with mode: 0644]
source3/utils/net_util.c [new file with mode: 0644]
source3/utils/netlookup.c [new file with mode: 0644]
source3/utils/ntlm_auth.c
source3/utils/pdbedit.c
source3/utils/smbcacls.c
source3/utils/smbcontrol.c
source3/utils/smbcquotas.c
source3/utils/smbpasswd.c
source3/web/cgi.c
source3/web/swat.c

index 6c182a6e41ac502aa451880bad52f9f26744d6d2..281d58f23d087ddde96053221e58c22579706252 100644 (file)
@@ -134,7 +134,7 @@ BIN_PROGS2 = bin/smbcontrol@EXEEXT@ bin/smbtree@EXEEXT@ bin/tdbbackup@EXEEXT@ \
        bin/tdbtool@EXEEXT@
 BIN_PROGS3 = bin/smbpasswd@EXEEXT@ bin/rpcclient@EXEEXT@ bin/smbcacls@EXEEXT@ \
        bin/profiles@EXEEXT@ bin/ntlm_auth@EXEEXT@ \
-       bin/smbcquotas@EXEEXT@ bin/eventlogadm@EXEEXT@
+       bin/smbcquotas@EXEEXT@ bin/eventlogadm@EXEEXT@ 
 
 TORTURE_PROGS = bin/smbtorture@EXEEXT@ bin/msgtest@EXEEXT@ \
        bin/masktest@EXEEXT@ bin/locktest@EXEEXT@ \
@@ -207,8 +207,9 @@ LIB_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \
          nsswitch/wb_client.o $(WBCOMMON_OBJ) \
          lib/pam_errors.o intl/lang_tdb.o \
          lib/adt_tree.o lib/gencache.o $(TDB_OBJ) \
-         lib/module.o lib/ldap_escape.o @CHARSET_STATIC@ \
-         lib/secdesc.o lib/secace.o lib/secacl.o @SOCKWRAP@
+         lib/module.o lib/events.o lib/ldap_escape.o @CHARSET_STATIC@ \
+         lib/secdesc.o lib/util_seaccess.o lib/secace.o lib/secacl.o @SOCKWRAP@ \
+         libads/krb5_errs.o
 
 LIB_DUMMY_OBJ = lib/dummysmbd.o lib/dummyroot.o
 LIB_NONSMBD_OBJ = $(LIB_OBJ) $(LIB_DUMMY_OBJ)
@@ -219,7 +220,7 @@ READLINE_OBJ = lib/readline.o
 # Be sure to include them into your application
 POPT_LIB_OBJ = lib/popt_common.o 
 
-PARAM_OBJ = dynconfig.o param/loadparm.o param/params.o
+PARAM_OBJ = dynconfig.o param/loadparm.o param/params.o lib/sharesec.o
 
 KRBCLIENT_OBJ = libads/kerberos.o libads/ads_status.o 
 
@@ -244,12 +245,11 @@ LIBSMB_OBJ = libsmb/clientgen.o libsmb/cliconnect.o libsmb/clifile.o \
             libsmb/clirap.o libsmb/clierror.o libsmb/climessage.o \
             libsmb/clireadwrite.o libsmb/clilist.o libsmb/cliprint.o \
             libsmb/clitrans.o libsmb/clisecdesc.o libsmb/clidgram.o \
-            libsmb/clistr.o lib/util_seaccess.o \
-            libsmb/cliquota.o libsmb/clifsinfo.o libsmb/clidfs.o \
+            libsmb/clistr.o libsmb/cliquota.o libsmb/clifsinfo.o libsmb/clidfs.o \
              libsmb/smberr.o libsmb/credentials.o libsmb/pwd_cache.o \
             libsmb/clioplock.o $(ERRORMAP_OBJ) libsmb/clirap2.o \
             $(DOSERR_OBJ) \
-            $(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) $(LIBNMB_OBJ) 
+            $(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) $(LIBNMB_OBJ)
 
 LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \
               rpc_client/cli_netlogon.o rpc_client/cli_srvsvc.o \
@@ -324,7 +324,7 @@ PASSDB_GET_SET_OBJ = passdb/pdb_get_set.o
 
 PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \
                passdb/util_wellknown.o passdb/util_builtin.o passdb/pdb_compat.o \
-               passdb/lookup_sid.o \
+               passdb/util_unixsids.o passdb/lookup_sid.o \
                passdb/login_cache.o @PDB_STATIC@ passdb/pdb_sql.o \
                lib/system_smbd.o lib/account_pol.o lib/privileges.o
 
@@ -390,7 +390,8 @@ BUILDOPT_OBJ = smbd/build_options.o
 
 SMBD_OBJ_SRV = smbd/files.o smbd/chgpasswd.o smbd/connection.o \
               smbd/utmp.o smbd/session.o \
-               smbd/dfree.o smbd/dir.o smbd/password.o smbd/conn.o smbd/fileio.o \
+               smbd/dfree.o smbd/dir.o smbd/password.o smbd/conn.o \
+              smbd/share_access.o smbd/fileio.o \
                smbd/ipc.o smbd/lanman.o smbd/negprot.o \
                smbd/message.o smbd/nttrans.o smbd/pipes.o \
                smbd/reply.o smbd/sesssetup.o smbd/trans2.o smbd/uid.o \
@@ -462,12 +463,13 @@ SMBSH_OBJ = smbwrapper/smbsh.o smbwrapper/shared.o \
 
 STATUS_OBJ = utils/status.o $(LOCKING_OBJ) $(PARAM_OBJ) \
              $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \
-            $(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(ERRORMAP_OBJ) 
+            $(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(ERRORMAP_OBJ) $(RPC_PARSE_OBJ1) \
+             $(DOSERR_OBJ)
              
 
 SMBCONTROL_OBJ = utils/smbcontrol.o $(LOCKING_OBJ) $(PARAM_OBJ) \
        $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \
-       $(SECRETS_OBJ) $(LIBSAMBA_OBJ) \
+       $(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(RPC_PARSE_OBJ1) $(DOSERR_OBJ) \
        $(PRINTBASE_OBJ) $(ERRORMAP_OBJ)
 
 SMBTREE_OBJ = utils/smbtree.o $(PARAM_OBJ) \
@@ -476,16 +478,16 @@ SMBTREE_OBJ = utils/smbtree.o $(PARAM_OBJ) \
 
 TESTPARM_OBJ = utils/testparm.o \
                $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) \
-              $(SECRETS_OBJ) $(LIBSAMBA_OBJ)
+              $(SECRETS_OBJ) $(LIBSAMBA_OBJ) $(RPC_PARSE_OBJ1) $(DOSERR_OBJ)
 
 SMBPASSWD_OBJ = utils/smbpasswd.o $(PASSCHANGE_OBJ) $(PARAM_OBJ) $(SECRETS_OBJ) \
                $(LIBSMB_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ)\
-                $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) \
+                $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) \
                $(SMBLDAP_OBJ) $(RPC_PARSE_OBJ) $(LIBMSRPC_OBJ)
 
 PDBEDIT_OBJ = utils/pdbedit.o $(PARAM_OBJ) $(PASSDB_OBJ) $(LIBSAMBA_OBJ) \
                $(LIB_NONSMBD_OBJ) $(GROUPDB_OBJ) $(SECRETS_OBJ) \
-               $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) libsmb/asn1.o
+               $(POPT_LIB_OBJ) $(SMBLDAP_OBJ) libsmb/asn1.o $(RPC_PARSE_OBJ1) $(DOSERR_OBJ)
 
 SMBGET_OBJ = utils/smbget.o $(POPT_LIB_OBJ) $(LIBSMBCLIENT_OBJ)
 
@@ -504,9 +506,12 @@ RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \
             $(LIBADS_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) \
             $(SMBLDAP_OBJ) $(DCUTIL_OBJ)
 
-PAM_WINBIND_PICOBJ = nsswitch/pam_winbind.@PICSUFFIX@ \
-       nsswitch/wb_common.@PICSUFFIX@ lib/replace1.@PICSUFFIX@ \
-       lib/snprintf.@PICSUFFIX@
+PAM_WINBIND_OBJ = nsswitch/pam_winbind.o \
+                 $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(RPC_PARSE_OBJ1) \
+                 $(LIBSAMBA_OBJ) $(DOSERR_OBJ)
+
+PAM_WINBIND_PICOBJ = $(PAM_WINBIND_OBJ:.o=.@PICSUFFIX@)
+
 
 SMBW_OBJ1 = smbwrapper/smbw.o \
                smbwrapper/smbw_dir.o smbwrapper/smbw_stat.o \
@@ -561,7 +566,9 @@ NET_OBJ1 = utils/net.o utils/net_ads.o utils/net_ads_cldap.o utils/net_help.o \
           utils/net_rpc_join.o utils/net_time.o utils/net_lookup.o \
           utils/net_cache.o utils/net_groupmap.o utils/net_idmap.o \
           utils/net_status.o utils/net_rpc_printer.o utils/net_rpc_rights.o \
-          utils/net_rpc_service.o utils/net_rpc_registry.o 
+          utils/net_rpc_service.o utils/net_rpc_registry.o utils/net_usershare.o \
+          utils/netlookup.o utils/net_sam.o utils/net_rpc_shell.o \
+          utils/net_util.o
 
 NET_OBJ = $(NET_OBJ1) $(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) \
          $(RPC_PARSE_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
@@ -569,7 +576,7 @@ NET_OBJ = $(NET_OBJ1) $(PARAM_OBJ) $(SECRETS_OBJ) $(LIBSMB_OBJ) \
          $(LIBMSRPC_OBJ) $(IDMAP_OBJ) \
          $(LIBADS_OBJ) $(LIBADS_SERVER_OBJ) $(POPT_LIB_OBJ) \
          $(SMBLDAP_OBJ) $(DCUTIL_OBJ) $(SERVER_MUTEX_OBJ) \
-         $(AFS_OBJ) $(AFS_SETTOKEN_OBJ) $(REGFIO_OBJ)
+         $(AFS_OBJ) $(AFS_SETTOKEN_OBJ) $(REGFIO_OBJ) $(READLINE_OBJ)
 
 CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) \
          $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) $(SECRETS_OBJ)
@@ -581,8 +588,9 @@ MNT_OBJ = client/smbmnt.o lib/replace.o $(VERSION_OBJ) $(SNPRINTF_OBJ)
 
 UMOUNT_OBJ = client/smbumount.o
 
-NMBLOOKUP_OBJ = utils/nmblookup.o $(PARAM_OBJ) $(LIBNMB_OBJ) \
-               $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) $(LIBSAMBA_OBJ)
+NMBLOOKUP_OBJ = utils/nmblookup.o $(PARAM_OBJ) $(LIBNMB_OBJ) $(RPC_PARSE_OBJ1) $(DOSERR_OBJ) \
+               $(LIB_NONSMBD_OBJ) $(POPT_LIB_OBJ) $(SECRETS_OBJ) $(LIBSAMBA_OBJ) \
+               
 
 SMBTORTURE_OBJ1 = torture/torture.o torture/nbio.o torture/scanner.o torture/utable.o \
                torture/denytest.o torture/mangle_test.o 
@@ -625,11 +633,12 @@ SMBCQUOTAS_OBJ = utils/smbcquotas.o $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) \
 EVTLOGADM_OBJ0 = utils/eventlogadm.o 
 
 EVTLOGADM_OBJ  = $(EVTLOGADM_OBJ0) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(REGOBJS_OBJ) \
-               $(ERRORMAP_OBJ) $(RPC_PARSE_OBJ0) $(LIBSAMBA_OBJ) $(DOSERR_OBJ) \
+               $(ERRORMAP_OBJ) $(RPC_PARSE_OBJ1) $(LIBSAMBA_OBJ) $(DOSERR_OBJ) \
                registry/reg_eventlog.o rpc_server/srv_eventlog_lib.o registry/reg_util.o \
                registry/reg_db.o 
 
-TALLOCTORT_OBJ = lib/talloctort.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) libsmb/nterr.o
+TALLOCTORT_OBJ = lib/talloctort.o $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
+                 $(RPC_PARSE_OBJ1) $(DOSERR_OBJ) $(LIBSAMBA_OBJ)
 
 RPCTORTURE_OBJ = torture/rpctorture.o \
              rpcclient/display.o \
@@ -699,7 +708,9 @@ WINBINDD_OBJ1 = \
                nsswitch/winbindd_ads.o \
                nsswitch/winbindd_passdb.o \
                nsswitch/winbindd_dual.o \
-               nsswitch/winbindd_async.o
+               nsswitch/winbindd_async.o \
+               nsswitch/winbindd_creds.o \
+               nsswitch/winbindd_cred_cache.o 
 
 WINBINDD_OBJ = \
                $(WINBINDD_OBJ1) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
@@ -708,10 +719,11 @@ WINBINDD_OBJ = \
                $(PROFILE_OBJ) $(SLCACHE_OBJ) $(SMBLDAP_OBJ) \
                $(SECRETS_OBJ) $(LIBADS_OBJ) $(KRBCLIENT_OBJ) $(POPT_LIB_OBJ) \
                $(DCUTIL_OBJ) $(IDMAP_OBJ) \
-               $(AFS_OBJ) $(AFS_SETTOKEN_OBJ)
+               $(AFS_OBJ) $(AFS_SETTOKEN_OBJ) \
+               $(LIBADS_SERVER_OBJ) $(SERVER_MUTEX_OBJ)
 
 WBINFO_OBJ = nsswitch/wbinfo.o $(LIBSAMBA_OBJ) $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) \
-               $(SECRETS_OBJ) $(POPT_LIB_OBJ) $(AFS_SETTOKEN_OBJ)
+               $(SECRETS_OBJ) $(POPT_LIB_OBJ) $(AFS_SETTOKEN_OBJ) $(RPC_PARSE_OBJ1) $(DOSERR_OBJ)
 
 WINBIND_NSS_OBJ = $(WBCOMMON_OBJ) lib/replace1.o @WINBIND_NSS_EXTRA_OBJS@
 
@@ -731,7 +743,7 @@ NTLM_AUTH_OBJ1 = utils/ntlm_auth.o utils/ntlm_auth_diagnostics.o
 NTLM_AUTH_OBJ = ${NTLM_AUTH_OBJ1} $(LIBSAMBA_OBJ) $(POPT_LIB_OBJ) \
                libsmb/asn1.o libsmb/spnego.o libsmb/clikrb5.o libads/kerberos.o \
                libads/kerberos_verify.o $(SECRETS_OBJ) $(SERVER_MUTEX_OBJ) \
-               libads/authdata.o $(RPC_PARSE_OBJ0) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
+               libads/authdata.o $(RPC_PARSE_OBJ1) $(PASSDB_OBJ) $(GROUPDB_OBJ) \
                $(SMBLDAP_OBJ) $(DOSERR_OBJ) rpc_parse/parse_net.o
 
 ######################################################################
@@ -781,7 +793,7 @@ modules: SHOWFLAGS proto_exists $(MODULES)
 
 cac: SHOWFLAGS bin/libmsrpc.@SHLIBEXT@ bin/libmsrpc.a
 
-everything: all libsmbclient debug2html smbfilter talloctort modules torture eventlogadm \
+everything: all libsmbclient debug2html smbfilter talloctort modules torture \
        $(EVERYTHING_PROGS)
 
 .SUFFIXES:
@@ -908,7 +920,7 @@ bin/smbctool@EXEEXT@: $(TOOL_OBJ) @BUILD_POPT@ bin/.dummy
 
 bin/net@EXEEXT@: $(NET_OBJ) @BUILD_POPT@ bin/.dummy
        @echo Linking $@
-       @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(NET_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS)
+       @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(NET_OBJ) $(DYNEXP) $(LDFLAGS) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) $(PASSDB_LIBS) $(TERMLDFLAGS) $(TERMLIBS)
 
 bin/profiles@EXEEXT@: $(PROFILES_OBJ) @BUILD_POPT@ bin/.dummy
        @echo Linking $@
@@ -949,10 +961,10 @@ bin/smbtree@EXEEXT@: $(SMBTREE_OBJ) @BUILD_POPT@ bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBTREE_OBJ) $(LDFLAGS) $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) 
 
-bin/smbpasswd@EXEEXT@: $(SMBPASSWD_OBJ) bin/.dummy
+bin/smbpasswd@EXEEXT@: $(SMBPASSWD_OBJ) @BUILD_POPT@ bin/.dummy
        @echo Linking $@
        @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(SMBPASSWD_OBJ) $(LDFLAGS) $(PASSDB_LIBS) \
-               $(DYNEXP) $(LIBS) $(KRB5LIBS) $(LDAP_LIBS) 
+               $(DYNEXP) $(LIBS) @POPTLIBS@ $(KRB5LIBS) $(LDAP_LIBS) 
 
 bin/pdbedit@EXEEXT@: $(PDBEDIT_OBJ) @BUILD_POPT@ bin/.dummy
        @echo Linking $@
@@ -1180,7 +1192,7 @@ bin/winbindd@EXEEXT@: $(WINBINDD_OBJ) @BUILD_POPT@ bin/.dummy
 nsswitch/pam_winbind.@SHLIBEXT@: $(PAM_WINBIND_PICOBJ) bin/.dummy
        @echo "Linking $@"
        @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_WINBIND_PICOBJ) \
-               @SONAMEFLAG@`basename $@` -lpam
+               @SONAMEFLAG@`basename $@` $(LIBS) -lpam
 
 bin/rhosts.@SHLIBEXT@: $(AUTH_RHOSTS_OBJ:.o=.@PICSUFFIX@)
        @echo "Building plugin $@"
index df7d6fc9c60a638f15d3ad9e83a7b72165daba9f..6dc30383d5d121db0ac79449ab2d238cff33040a 100644 (file)
@@ -216,10 +216,10 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
                return NT_STATUS_LOGON_FAILURE;
 
        DEBUG(3, ("check_ntlm_password:  Checking password for unmapped user [%s]\\[%s]@[%s] with the new password interface\n", 
-                 user_info->client_domain.str, user_info->smb_name.str, user_info->wksta_name.str));
+                 user_info->client_domain, user_info->smb_name, user_info->wksta_name));
 
        DEBUG(3, ("check_ntlm_password:  mapped user is: [%s]\\[%s]@[%s]\n", 
-                 user_info->domain.str, user_info->internal_username.str, user_info->wksta_name.str));
+                 user_info->domain, user_info->internal_username, user_info->wksta_name));
 
        if (auth_context->challenge.length != 8) {
                DEBUG(0, ("check_ntlm_password:  Invalid challenge stored for this auth context - cannot continue\n"));
@@ -243,14 +243,14 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
 #endif
 
        /* This needs to be sorted:  If it doesn't match, what should we do? */
-       if (!check_domain_match(user_info->smb_name.str, user_info->domain.str))
+       if (!check_domain_match(user_info->smb_name, user_info->domain))
                return NT_STATUS_LOGON_FAILURE;
 
        for (auth_method = auth_context->auth_method_list;auth_method; auth_method = auth_method->next) {
                NTSTATUS result;
                
                mem_ctx = talloc_init("%s authentication for user %s\\%s", auth_method->name, 
-                                           user_info->domain.str, user_info->smb_name.str);
+                                           user_info->domain, user_info->smb_name);
 
                result = auth_method->auth(auth_context, auth_method->private_data, mem_ctx, user_info, server_info);
 
@@ -265,10 +265,10 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
 
                if (NT_STATUS_IS_OK(nt_status)) {
                        DEBUG(3, ("check_ntlm_password: %s authentication for user [%s] succeeded\n", 
-                                 auth_method->name, user_info->smb_name.str));
+                                 auth_method->name, user_info->smb_name));
                } else {
                        DEBUG(5, ("check_ntlm_password: %s authentication for user [%s] FAILED with error %s\n", 
-                                 auth_method->name, user_info->smb_name.str, nt_errstr(nt_status)));
+                                 auth_method->name, user_info->smb_name, nt_errstr(nt_status)));
                }
 
                talloc_destroy(mem_ctx);
@@ -302,8 +302,8 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
                        DEBUG((*server_info)->guest ? 5 : 2, 
                              ("check_ntlm_password:  %sauthentication for user [%s] -> [%s] -> [%s] succeeded\n", 
                               (*server_info)->guest ? "guest " : "", 
-                              user_info->smb_name.str
-                              user_info->internal_username.str
+                              user_info->smb_name, 
+                              user_info->internal_username, 
                               unix_username));
                }
                
@@ -313,8 +313,8 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context,
        /* failed authentication; check for guest lapping */
        
        DEBUG(2, ("check_ntlm_password:  Authentication for user [%s] -> [%s] FAILED with error %s\n", 
-       user_info->smb_name.str, user_info->internal_username.str
-       nt_errstr(nt_status)));
+                 user_info->smb_name, user_info->internal_username
+                 nt_errstr(nt_status)));
        ZERO_STRUCTP(server_info); 
        
        return nt_status;
index 96c2221652eef25d6dc7a44787eb84b376256ec7..d4d6d49e40c7d9c4ae290a4b7225f812740affeb 100644 (file)
@@ -41,8 +41,8 @@ static NTSTATUS check_guest_security(const struct auth_context *auth_context,
        /* mark this as 'not for me' */
        NTSTATUS nt_status = NT_STATUS_NOT_IMPLEMENTED;
 
-       if (!(user_info->internal_username.str 
-             && *user_info->internal_username.str)) {
+       if (!(user_info->internal_username 
+             && *user_info->internal_username)) {
                nt_status = make_server_info_guest(server_info);
        }
 
@@ -84,7 +84,7 @@ static NTSTATUS check_name_to_ntstatus_security(const struct auth_context *auth_
        NTSTATUS nt_status;
        fstring user;
        long error_num;
-       fstrcpy(user, user_info->smb_name.str);
+       fstrcpy(user, user_info->smb_name);
        
        if (strnequal("NT_STATUS", user, strlen("NT_STATUS"))) {
                strupper_m(user);
index 2ac70d7354663f32f4dab2bc9d989dabd60bcfce..28b9de8d4312060a3c844145c63a1088a8e9d429 100644 (file)
@@ -84,7 +84,7 @@ static NTSTATUS pass_check_smb(const char *smb_name,
        } else {
                nt_status = check_plaintext_password(smb_name, plaintext_password, &server_info);
        }               
-       free_server_info(&server_info);
+       talloc_free(server_info);
        return nt_status;
 }
 
index 266851b22923a235a0a66fbd7612383ceafce798..81ae7c134004f93964d1eacec83565e4550fbded 100644 (file)
@@ -221,9 +221,9 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
                                                      mem_ctx,
                                                      user_info->logon_parameters,/* flags such as 'allow workstation logon' */ 
                                                      dc_name,                    /* server name */
-                                                     user_info->smb_name.str,    /* user name logging on. */
-                                                     user_info->domain.str,      /* domain name */
-                                                     user_info->wksta_name.str,  /* workstation name */
+                                                     user_info->smb_name,        /* user name logging on. */
+                                                     user_info->domain,          /* domain name */
+                                                     user_info->wksta_name,      /* workstation name */
                                                      chal,                       /* 8 byte challenge. */
                                                      user_info->lm_resp,         /* lanman 24 byte response */
                                                      user_info->nt_resp,         /* nt 24 byte response */
@@ -237,8 +237,8 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
        if (!NT_STATUS_IS_OK(nt_status)) {
                DEBUG(0,("domain_client_validate: unable to validate password "
                          "for user %s in domain %s to Domain controller %s. "
-                         "Error was %s.\n", user_info->smb_name.str,
-                         user_info->domain.str, dc_name, 
+                         "Error was %s.\n", user_info->smb_name,
+                         user_info->domain, dc_name, 
                          nt_errstr(nt_status)));
 
                /* map to something more useful */
@@ -247,13 +247,13 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx,
                }
        } else {
                nt_status = make_server_info_info3(mem_ctx,
-                                               user_info->internal_username.str
-                                               user_info->smb_name.str,
+                                               user_info->internal_username, 
+                                               user_info->smb_name,
                                                domain,
                                                server_info,
                                                &info3);
 
-               netsamlogon_cache_store( user_info->smb_name.str, &info3 );
+               netsamlogon_cache_store( user_info->smb_name, &info3 );
        }
 
        /* Note - once the cli stream is shutdown the mem_ctx used
@@ -296,7 +296,7 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context,
         * password file.
         */
 
-       if(strequal(get_global_sam_name(), user_info->domain.str)) {
+       if(strequal(get_global_sam_name(), user_info->domain)) {
                DEBUG(3,("check_ntdomain_security: Requested domain was for this machine.\n"));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
@@ -305,7 +305,7 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context,
 
        if ( !get_dc_name(domain, NULL, dc_name, &dc_ip) ) {
                DEBUG(5,("check_ntdomain_security: unable to locate a DC for domain %s\n",
-                       user_info->domain.str));
+                       user_info->domain));
                return NT_STATUS_NO_LOGON_SERVERS;
        }
        
@@ -360,9 +360,9 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte
         * Check that the requested domain is not our own machine name or domain name.
         */
 
-       if( strequal(get_global_sam_name(), user_info->domain.str)) {
+       if( strequal(get_global_sam_name(), user_info->domain)) {
                DEBUG(3,("check_trustdomain_security: Requested domain [%s] was for this machine.\n",
-                       user_info->domain.str));
+                       user_info->domain));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
@@ -371,7 +371,7 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte
           The logic is that if we know nothing about the domain, that
           user is not known to us and does not exist */
        
-       if ( !is_trusted_domain( user_info->domain.str ) )
+       if ( !is_trusted_domain( user_info->domain ) )
                return NT_STATUS_NOT_IMPLEMENTED;
 
        /*
@@ -379,14 +379,17 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte
         * No need to become_root() as secrets_init() is done at startup.
         */
 
-       if (!secrets_fetch_trusted_domain_password(user_info->domain.str, &trust_password,
+       if (!secrets_fetch_trusted_domain_password(user_info->domain, &trust_password,
                                &sid, &last_change_time)) {
-               DEBUG(0, ("check_trustdomain_security: could not fetch trust account password for domain %s\n", user_info->domain.str));
+               DEBUG(0, ("check_trustdomain_security: could not fetch trust "
+                         "account password for domain %s\n",
+                         user_info->domain));
                return NT_STATUS_CANT_ACCESS_DOMAIN_INFO;
        }
 
 #ifdef DEBUG_PASSWORD
-       DEBUG(100, ("Trust password for domain %s is %s\n", user_info->domain.str, trust_password));
+       DEBUG(100, ("Trust password for domain %s is %s\n", user_info->domain,
+                   trust_password));
 #endif
        E_md4hash(trust_password, trust_md4_password);
        SAFE_FREE(trust_password);
@@ -402,15 +405,15 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte
        /* use get_dc_name() for consistency even through we know that it will be 
           a netbios name */
           
-       if ( !get_dc_name(user_info->domain.str, NULL, dc_name, &dc_ip) ) {
+       if ( !get_dc_name(user_info->domain, NULL, dc_name, &dc_ip) ) {
                DEBUG(5,("check_trustdomain_security: unable to locate a DC for domain %s\n",
-                       user_info->domain.str));
+                       user_info->domain));
                return NT_STATUS_NO_LOGON_SERVERS;
        }
        
        nt_status = domain_client_validate(mem_ctx,
                                        user_info,
-                                       user_info->domain.str,
+                                       user_info->domain,
                                        (uchar *)auth_context->challenge.data,
                                        server_info,
                                        dc_name,
index 2fef8f1e9b56ca686d7ddcc080ced0b387da8187..2bf86860cc1469bec7029c8740d9f208bda89623 100644 (file)
@@ -115,6 +115,14 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state,
        if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
        }
+
+       nt_status = create_local_token(auth_ntlmssp_state->server_info);
+
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               DEBUG(10, ("create_local_token failed\n"));
+               return nt_status;
+       }
+
        if (auth_ntlmssp_state->server_info->user_session_key.length) {
                DEBUG(10, ("Got NT session key of length %u\n",
                        (unsigned int)auth_ntlmssp_state->server_info->user_session_key.length));
@@ -179,7 +187,7 @@ void auth_ntlmssp_end(AUTH_NTLMSSP_STATE **auth_ntlmssp_state)
                ((*auth_ntlmssp_state)->auth_context->free)(&(*auth_ntlmssp_state)->auth_context);
        }
        if ((*auth_ntlmssp_state)->server_info) {
-               free_server_info(&(*auth_ntlmssp_state)->server_info);
+               talloc_free((*auth_ntlmssp_state)->server_info);
        }
        talloc_destroy(mem_ctx);
        *auth_ntlmssp_state = NULL;
index b561e3d42bee9c4d94b777cfdc34e510beda941d..e310fa80fd5de1f452f04f519b0b624592fe828d 100644 (file)
@@ -60,103 +60,101 @@ static NTSTATUS auth_get_sam_account(const char *user, SAM_ACCOUNT **account)
 
 static BOOL check_user_equiv(const char *user, const char *remote, const char *equiv_file)
 {
-  int plus_allowed = 1;
-  char *file_host;
-  char *file_user;
-  char **lines = file_lines_load(equiv_file, NULL);
-  int i;
-
-  DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file));
-  if (! lines) return False;
-  for (i=0; lines[i]; i++) {
-    char *buf = lines[i];
-    trim_char(buf,' ',' ');
-
-    if (buf[0] != '#' && buf[0] != '\n') 
-    {
-      BOOL is_group = False;
-      int plus = 1;
-      char *bp = buf;
-      if (strcmp(buf, "NO_PLUS\n") == 0)
-      {
-       DEBUG(6, ("check_user_equiv NO_PLUS\n"));
-       plus_allowed = 0;
-      }
-      else {
-       if (buf[0] == '+') 
-       {
-         bp++;
-         if (*bp == '\n' && plus_allowed) 
-         {
-           /* a bare plus means everbody allowed */
-           DEBUG(6, ("check_user_equiv everybody allowed\n"));
-           file_lines_free(lines);
-           return True;
-         }
-       }
-       else if (buf[0] == '-')
-       {
-         bp++;
-         plus = 0;
-       }
-       if (*bp == '@') 
-       {
-         is_group = True;
-         bp++;
+       int plus_allowed = 1;
+       char *file_host;
+       char *file_user;
+       char **lines = file_lines_load(equiv_file, NULL,0);
+       int i;
+
+       DEBUG(5, ("check_user_equiv %s %s %s\n", user, remote, equiv_file));
+       if (! lines) {
+               return False;
        }
-       file_host = strtok(bp, " \t\n");
-       file_user = strtok(NULL, " \t\n");
-       DEBUG(7, ("check_user_equiv %s %s\n", file_host ? file_host : "(null)", 
-                 file_user ? file_user : "(null)" ));
-       if (file_host && *file_host) 
-       {
-         BOOL host_ok = False;
+       for (i=0; lines[i]; i++) {
+               char *buf = lines[i];
+               trim_char(buf,' ',' ');
+
+               if (buf[0] != '#' && buf[0] != '\n') {
+                       BOOL is_group = False;
+                       int plus = 1;
+                       char *bp = buf;
+
+                       if (strcmp(buf, "NO_PLUS\n") == 0) {
+                               DEBUG(6, ("check_user_equiv NO_PLUS\n"));
+                               plus_allowed = 0;
+                       } else {
+                               if (buf[0] == '+') {
+                                       bp++;
+                                       if (*bp == '\n' && plus_allowed) {
+                                               /* a bare plus means everbody allowed */
+                                               DEBUG(6, ("check_user_equiv everybody allowed\n"));
+                                               file_lines_free(lines);
+                                               return True;
+                                       }
+                               } else if (buf[0] == '-') {
+                                       bp++;
+                                       plus = 0;
+                               }
+                               if (*bp == '@') {
+                                       is_group = True;
+                                       bp++;
+                               }
+                               file_host = strtok(bp, " \t\n");
+                               file_user = strtok(NULL, " \t\n");
+                               DEBUG(7, ("check_user_equiv %s %s\n", file_host ? file_host : "(null)", 
+                                       file_user ? file_user : "(null)" ));
+
+                               if (file_host && *file_host) {
+                                       BOOL host_ok = False;
 
 #if defined(HAVE_NETGROUP) && defined(HAVE_YP_GET_DEFAULT_DOMAIN)
-         if (is_group)
-           {
-             static char *mydomain = NULL;
-             if (!mydomain)
-               yp_get_default_domain(&mydomain);
-             if (mydomain && innetgr(file_host,remote,user,mydomain))
-               host_ok = True;
-           }
+                                       if (is_group) {
+                                               static char *mydomain = NULL;
+                                               if (!mydomain) {
+                                                       yp_get_default_domain(&mydomain);
+                                               }
+                                               if (mydomain && innetgr(file_host,remote,user,mydomain)) {
+                                                       host_ok = True;
+                                               }
+                                       }
 #else
-         if (is_group)
-           {
-             DEBUG(1,("Netgroups not configured\n"));
-             continue;
-           }
+                                       if (is_group) {
+                                               DEBUG(1,("Netgroups not configured\n"));
+                                               continue;
+                                       }
 #endif
 
-         /* is it this host */
-         /* the fact that remote has come from a call of gethostbyaddr
-          * means that it may have the fully qualified domain name
-          * so we could look up the file version to get it into
-          * a canonical form, but I would rather just type it
-          * in full in the equiv file
-          */
-         if (!host_ok && !is_group && strequal(remote, file_host))
-           host_ok = True;
-
-         if (!host_ok)
-           continue;
-
-         /* is it this user */
-         if (file_user == 0 || strequal(user, file_user)) 
-           {
-             DEBUG(5, ("check_user_equiv matched %s%s %s\n",
-                       (plus ? "+" : "-"), file_host,
-                       (file_user ? file_user : "")));
-             file_lines_free(lines);
-             return (plus ? True : False);
-           }
+                                       /* is it this host */
+                                       /* the fact that remote has come from a call of gethostbyaddr
+                                        * means that it may have the fully qualified domain name
+                                        * so we could look up the file version to get it into
+                                        * a canonical form, but I would rather just type it
+                                        * in full in the equiv file
+                                        */
+
+                                       if (!host_ok && !is_group && strequal(remote, file_host)) {
+                                               host_ok = True;
+                                       }
+
+                                       if (!host_ok) {
+                                               continue;
+                                       }
+
+                                       /* is it this user */
+                                       if (file_user == 0 || strequal(user, file_user)) {
+                                               DEBUG(5, ("check_user_equiv matched %s%s %s\n",
+                                                       (plus ? "+" : "-"), file_host,
+                                                       (file_user ? file_user : "")));
+                                               file_lines_free(lines);
+                                               return (plus ? True : False);
+                                       }
+                               }
+                       }
+               }
        }
-      }
-    }
-  }
-  file_lines_free(lines);
-  return False;
+
+       file_lines_free(lines);
+       return False;
 }
 
 /****************************************************************************
@@ -169,7 +167,7 @@ static BOOL check_hosts_equiv(SAM_ACCOUNT *account)
        char *fname = NULL;
 
        fname = lp_hosts_equiv();
-       if (!NT_STATUS_IS_OK(sid_to_uid(pdb_get_user_sid(account), &uid)))
+       if (!sid_to_uid(pdb_get_user_sid(account), &uid))
                return False;
 
        /* note: don't allow hosts.equiv on root */
@@ -195,7 +193,7 @@ static NTSTATUS check_hostsequiv_security(const struct auth_context *auth_contex
        NTSTATUS nt_status;
        SAM_ACCOUNT *account = NULL;
        if (!NT_STATUS_IS_OK(nt_status = 
-                            auth_get_sam_account(user_info->internal_username.str, 
+                            auth_get_sam_account(user_info->internal_username,
                                                  &account))) {
                if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) 
                        nt_status = NT_STATUS_NOT_IMPLEMENTED;
@@ -204,6 +202,9 @@ static NTSTATUS check_hostsequiv_security(const struct auth_context *auth_contex
 
        if (check_hosts_equiv(account)) {
                nt_status = make_server_info_sam(server_info, account);
+               if (!NT_STATUS_IS_OK(nt_status)) {
+                       pdb_free_sam(&account);
+               }
        } else {
                pdb_free_sam(&account);
                nt_status = NT_STATUS_NOT_IMPLEMENTED;
@@ -241,7 +242,7 @@ static NTSTATUS check_rhosts_security(const struct auth_context *auth_context,
        const char *home;
        
        if (!NT_STATUS_IS_OK(nt_status = 
-                            auth_get_sam_account(user_info->internal_username.str, 
+                            auth_get_sam_account(user_info->internal_username,
                                                  &account))) {
                if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) 
                        nt_status = NT_STATUS_NOT_IMPLEMENTED;
@@ -255,6 +256,9 @@ static NTSTATUS check_rhosts_security(const struct auth_context *auth_context,
                become_root();
                if (check_user_equiv(pdb_get_username(account),client_name(),rhostsfile)) {
                        nt_status = make_server_info_sam(server_info, account);
+                       if (!NT_STATUS_IS_OK(nt_status)) {
+                               pdb_free_sam(&account);
+                       }
                } else {
                        pdb_free_sam(&account);
                }
index 558c181f704452731324e98515f00a3fee6b9293..fb53941b79fc3146b4a98dc4e03f49b5089c2587 100644 (file)
@@ -62,8 +62,8 @@ static NTSTATUS sam_password_ok(const struct auth_context *auth_context,
                                   &user_info->lm_resp, &user_info->nt_resp, 
                                   &user_info->lm_interactive_pwd, &user_info->nt_interactive_pwd,
                                   username, 
-                                  user_info->smb_name.str, 
-                                  user_info->client_domain.str, 
+                                  user_info->smb_name,
+                                  user_info->client_domain,
                                   lm_pw, nt_pw, user_sess_key, lm_sess_key);
 }
 
@@ -177,22 +177,22 @@ static NTSTATUS sam_account_ok(TALLOC_CTX *mem_ctx,
                fstring tok;
                const char *s = workstation_list;
 
-               const char *machine_name = talloc_asprintf(mem_ctx, "%s$", user_info->wksta_name.str);
+               const char *machine_name = talloc_asprintf(mem_ctx, "%s$", user_info->wksta_name);
                if (machine_name == NULL)
                        return NT_STATUS_NO_MEMORY;
                        
                        
                while (next_token(&s, tok, ",", sizeof(tok))) {
-                       DEBUG(10,("sam_account_ok: checking for workstation match %s and %s (len=%d)\n",
-                                 tok, user_info->wksta_name.str, user_info->wksta_name.len));
-                       if(strequal(tok, user_info->wksta_name.str)) {
+                       DEBUG(10,("sam_account_ok: checking for workstation match %s and %s\n",
+                                 tok, user_info->wksta_name));
+                       if(strequal(tok, user_info->wksta_name)) {
                                invalid_ws = False;
                                break;
                        }
                        if (tok[0] == '+') {
                                DEBUG(10,("sam_account_ok: checking for workstation %s in group: %s\n", 
                                        machine_name, tok + 1));
-                               if (user_in_group_list(machine_name, tok + 1, NULL, 0)) {
+                               if (user_in_group(machine_name, tok + 1)) {
                                        invalid_ws = False;
                                        break;
                                }
@@ -257,11 +257,12 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
        /* get the account information */
 
        become_root();
-       ret = pdb_getsampwnam(sampass, user_info->internal_username.str);
+       ret = pdb_getsampwnam(sampass, user_info->internal_username);
        unbecome_root();
 
        if (ret == False) {
-               DEBUG(3,("check_sam_security: Couldn't find user '%s' in passdb.\n", user_info->internal_username.str));
+               DEBUG(3,("check_sam_security: Couldn't find user '%s' in "
+                        "passdb.\n", user_info->internal_username));
                pdb_free_sam(&sampass);
                return NT_STATUS_NO_SUCH_USER;
        }
@@ -294,7 +295,7 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
                }
                if (updated_autolock || updated_badpw){
                        become_root();
-                       if(!pdb_update_sam_account(sampass))
+                       if(!NT_STATUS_IS_OK(pdb_update_sam_account(sampass)))
                                DEBUG(1, ("Failed to modify entry.\n"));
                        unbecome_root();
                }
@@ -313,7 +314,7 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
 
        if (updated_autolock || updated_badpw){
                become_root();
-               if(!pdb_update_sam_account(sampass))
+               if(!NT_STATUS_IS_OK(pdb_update_sam_account(sampass)))
                        DEBUG(1, ("Failed to modify entry.\n"));
                unbecome_root();
        }
@@ -329,13 +330,21 @@ static NTSTATUS check_sam_security(const struct auth_context *auth_context,
 
        if (!NT_STATUS_IS_OK(nt_status = make_server_info_sam(server_info, sampass))) {         
                DEBUG(0,("check_sam_security: make_server_info_sam() failed with '%s'\n", nt_errstr(nt_status)));
+               pdb_free_sam(&sampass);
                data_blob_free(&user_sess_key);
                data_blob_free(&lm_sess_key);
                return nt_status;
        }
 
-       (*server_info)->user_session_key = user_sess_key;
-       (*server_info)->lm_session_key = lm_sess_key;
+       (*server_info)->user_session_key =
+               data_blob_talloc(*server_info, user_sess_key.data,
+                                user_sess_key.length);
+       data_blob_free(&user_sess_key);
+
+       (*server_info)->lm_session_key =
+               data_blob_talloc(*server_info, lm_sess_key.data,
+                                lm_sess_key.length);
+       data_blob_free(&lm_sess_key);
 
        return nt_status;
 }
@@ -369,8 +378,8 @@ static NTSTATUS check_samstrict_security(const struct auth_context *auth_context
                return NT_STATUS_LOGON_FAILURE;
        }
 
-       is_local_name = is_myname(user_info->domain.str);
-       is_my_domain  = strequal(user_info->domain.str, lp_workgroup());
+       is_local_name = is_myname(user_info->domain);
+       is_my_domain  = strequal(user_info->domain, lp_workgroup());
 
        /* check whether or not we service this domain/workgroup name */
        
@@ -379,7 +388,7 @@ static NTSTATUS check_samstrict_security(const struct auth_context *auth_context
                case ROLE_DOMAIN_MEMBER:
                        if ( !is_local_name ) {
                                DEBUG(6,("check_samstrict_security: %s is not one of my local names (%s)\n",
-                                       user_info->domain.str, (lp_server_role() == ROLE_DOMAIN_MEMBER 
+                                       user_info->domain, (lp_server_role() == ROLE_DOMAIN_MEMBER 
                                        ? "ROLE_DOMAIN_MEMBER" : "ROLE_STANDALONE") ));
                                return NT_STATUS_NOT_IMPLEMENTED;
                        }
@@ -387,7 +396,7 @@ static NTSTATUS check_samstrict_security(const struct auth_context *auth_context
                case ROLE_DOMAIN_BDC:
                        if ( !is_local_name && !is_my_domain ) {
                                DEBUG(6,("check_samstrict_security: %s is not one of my local names or domain name (DC)\n",
-                                       user_info->domain.str));
+                                       user_info->domain));
                                return NT_STATUS_NOT_IMPLEMENTED;
                        }
                default: /* name is ok */
index 1a715fca319e3fc8a8fa3766772e9818b4b30e7c..1bc33ec59e7915ae3c9c107101c211764d5c1a66 100644 (file)
@@ -63,8 +63,8 @@ static NTSTATUS script_check_user_credentials(const struct auth_context *auth_co
                return NT_STATUS_INVALID_PARAMETER;
        }               
 
-       secret_str_len = strlen(user_info->domain.str) + 1 +
-                       strlen(user_info->smb_name.str) + 1 +
+       secret_str_len = strlen(user_info->domain) + 1 +
+                       strlen(user_info->smb_name) + 1 +
                        16 + 1 + /* 8 bytes of challenge going to 16 */
                        48 + 1 + /* 24 bytes of challenge going to 48 */
                        48 + 1;
@@ -74,9 +74,9 @@ static NTSTATUS script_check_user_credentials(const struct auth_context *auth_co
                return NT_STATUS_NO_MEMORY;
        }
 
-       safe_strcpy( secret_str, user_info->domain.str, secret_str_len - 1);
+       safe_strcpy( secret_str, user_info->domain, secret_str_len - 1);
        safe_strcat( secret_str, "\n", secret_str_len - 1);
-       safe_strcat( secret_str, user_info->smb_name.str, secret_str_len - 1);
+       safe_strcat( secret_str, user_info->smb_name, secret_str_len - 1);
        safe_strcat( secret_str, "\n", secret_str_len - 1);
 
        for (i = 0; i < 8; i++) {
@@ -110,7 +110,7 @@ static NTSTATUS script_check_user_credentials(const struct auth_context *auth_co
 
        if (ret) {
                DEBUG(1,("script_check_user_credentials: failed to authenticate %s\\%s\n",
-                       user_info->domain.str, user_info->smb_name.str ));
+                       user_info->domain, user_info->smb_name ));
                /* auth failed. */
                return NT_STATUS_NO_SUCH_USER;
        }
index 7bce32ef2b221d3edd8bb49e7e0d59eca72a3dc7..8eed8bba6a40efd60e4286b0a74efd4f26cb8a7b 100644 (file)
@@ -235,7 +235,7 @@ static NTSTATUS check_smbserver_security(const struct auth_context *auth_context
         * password file.
         */
 
-       if(is_myname(user_info->domain.str)) {
+       if(is_myname(user_info->domain)) {
                DEBUG(3,("check_smbserver_security: Requested domain was for this machine.\n"));
                return nt_status;
        }
@@ -296,7 +296,7 @@ static NTSTATUS check_smbserver_security(const struct auth_context *auth_context
 
        if ((!tested_password_server) && (lp_paranoid_server_security())) {
                if (cli_session_setup(cli, baduser, (char *)badpass, sizeof(badpass), 
-                                       (char *)badpass, sizeof(badpass), user_info->domain.str)) {
+                                       (char *)badpass, sizeof(badpass), user_info->domain)) {
 
                        /*
                         * We connected to the password server so we
@@ -342,11 +342,11 @@ use this machine as the password server.\n"));
 
        if (!user_info->encrypted) {
                /* Plaintext available */
-               if (!cli_session_setup(cli, user_info->smb_name.str
+               if (!cli_session_setup(cli, user_info->smb_name, 
                                       (char *)user_info->plaintext_password.data, 
                                       user_info->plaintext_password.length, 
                                       NULL, 0,
-                                      user_info->domain.str)) {
+                                      user_info->domain)) {
                        DEBUG(1,("password server %s rejected the password\n", cli->desthost));
                        /* Make this cli_nt_error() when the conversion is in */
                        nt_status = cli_nt_error(cli);
@@ -354,12 +354,12 @@ use this machine as the password server.\n"));
                        nt_status = NT_STATUS_OK;
                }
        } else {
-               if (!cli_session_setup(cli, user_info->smb_name.str
+               if (!cli_session_setup(cli, user_info->smb_name, 
                                       (char *)user_info->lm_resp.data, 
                                       user_info->lm_resp.length, 
                                       (char *)user_info->nt_resp.data, 
                                       user_info->nt_resp.length, 
-                                      user_info->domain.str)) {
+                                      user_info->domain)) {
                        DEBUG(1,("password server %s rejected the password\n", cli->desthost));
                        /* Make this cli_nt_error() when the conversion is in */
                        nt_status = cli_nt_error(cli);
@@ -380,11 +380,11 @@ use this machine as the password server.\n"));
                fstring real_username;
                struct passwd *pass;
 
-               if ( (pass = smb_getpwnam( user_info->internal_username.str
+               if ( (pass = smb_getpwnam( NULL, user_info->internal_username
                        real_username, True )) != NULL ) 
                {
                        nt_status = make_server_info_pw(server_info, pass->pw_name, pass);
-                       passwd_free(&pass);
+                       talloc_free(pass);
                }
                else
                {
index f744cba0c434e53c754eee80a8bfcf304590f8d8..df0703d348b10af25a99a794b35b9a575875d5eb 100644 (file)
@@ -62,7 +62,7 @@ static BOOL update_smbpassword_file(const char *user, const char *password)
        /* Now write it into the file. */
        become_root();
 
-       ret = pdb_update_sam_account (sampass);
+       ret = NT_STATUS_IS_OK(pdb_update_sam_account (sampass));
 
        unbecome_root();
 
@@ -91,13 +91,13 @@ static NTSTATUS check_unix_security(const struct auth_context *auth_context,
        struct passwd *pass = NULL;
 
        become_root();
-       pass = Get_Pwnam(user_info->internal_username.str);
+       pass = Get_Pwnam(user_info->internal_username);
 
        
        /** @todo This call assumes a ASCII password, no charset transformation is 
            done.  We may need to revisit this **/
        nt_status = pass_check(pass,
-                               pass ? pass->pw_name : user_info->internal_username.str
+                               pass ? pass->pw_name : user_info->internal_username, 
                                (char *)user_info->plaintext_password.data,
                                user_info->plaintext_password.length-1,
                                lp_update_encrypted() ? 
index eb15fff7c8da5fc708ececbd8a7f7eb1a63b84c5..27dab9b9aa80f02398b46b76d62d5202328541d9 100644 (file)
@@ -5,6 +5,7 @@
    Copyright (C) Andrew Bartlett 2001
    Copyright (C) Jeremy Allison 2000-2001
    Copyright (C) Rafal Szczesniak 2002
+   Copyright (C) Volker Lendecke 2006
 
    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
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_AUTH
 
+static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
+                                                  const DOM_SID *user_sid,
+                                                  const DOM_SID *group_sid,
+                                                  BOOL is_guest,
+                                                  int num_groupsids,
+                                                  const DOM_SID *groupsids);
 
 /****************************************************************************
  Create a UNIX user on demand.
@@ -78,42 +85,32 @@ static NTSTATUS make_user_info(auth_usersupplied_info **user_info,
 
        DEBUG(5,("making strings for %s's user_info struct\n", internal_username));
 
-       (*user_info)->smb_name.str = SMB_STRDUP(smb_name);
-       if ((*user_info)->smb_name.str) { 
-               (*user_info)->smb_name.len = strlen(smb_name);
-       } else {
+       (*user_info)->smb_name = SMB_STRDUP(smb_name);
+       if ((*user_info)->smb_name == NULL) { 
                free_user_info(user_info);
                return NT_STATUS_NO_MEMORY;
        }
        
-       (*user_info)->internal_username.str = SMB_STRDUP(internal_username);
-       if ((*user_info)->internal_username.str) { 
-               (*user_info)->internal_username.len = strlen(internal_username);
-       } else {
+       (*user_info)->internal_username = SMB_STRDUP(internal_username);
+       if ((*user_info)->internal_username == NULL) { 
                free_user_info(user_info);
                return NT_STATUS_NO_MEMORY;
        }
 
-       (*user_info)->domain.str = SMB_STRDUP(domain);
-       if ((*user_info)->domain.str) { 
-               (*user_info)->domain.len = strlen(domain);
-       } else {
+       (*user_info)->domain = SMB_STRDUP(domain);
+       if ((*user_info)->domain == NULL) { 
                free_user_info(user_info);
                return NT_STATUS_NO_MEMORY;
        }
 
-       (*user_info)->client_domain.str = SMB_STRDUP(client_domain);
-       if ((*user_info)->client_domain.str) { 
-               (*user_info)->client_domain.len = strlen(client_domain);
-       } else {
+       (*user_info)->client_domain = SMB_STRDUP(client_domain);
+       if ((*user_info)->client_domain == NULL) { 
                free_user_info(user_info);
                return NT_STATUS_NO_MEMORY;
        }
 
-       (*user_info)->wksta_name.str = SMB_STRDUP(wksta_name);
-       if ((*user_info)->wksta_name.str) { 
-               (*user_info)->wksta_name.len = strlen(wksta_name);
-       } else {
+       (*user_info)->wksta_name = SMB_STRDUP(wksta_name);
+       if ((*user_info)->wksta_name == NULL) { 
                free_user_info(user_info);
                return NT_STATUS_NO_MEMORY;
        }
@@ -196,26 +193,28 @@ BOOL make_user_info_netlogon_network(auth_usersupplied_info **user_info,
                                     const char *client_domain, 
                                     const char *wksta_name, 
                                     uint32 logon_parameters,
-                                    const uchar *lm_network_pwd, int lm_pwd_len,
-                                    const uchar *nt_network_pwd, int nt_pwd_len)
+                                    const uchar *lm_network_pwd,
+                                    int lm_pwd_len,
+                                    const uchar *nt_network_pwd,
+                                    int nt_pwd_len)
 {
        BOOL ret;
-       NTSTATUS nt_status;
+       NTSTATUS status;
        DATA_BLOB lm_blob = data_blob(lm_network_pwd, lm_pwd_len);
        DATA_BLOB nt_blob = data_blob(nt_network_pwd, nt_pwd_len);
 
-       nt_status = make_user_info_map(user_info,
-                                      smb_name, client_domain, 
-                                      wksta_name, 
-                                      lm_pwd_len ? &lm_blob : NULL, 
-                                      nt_pwd_len ? &nt_blob : NULL,
-                                      NULL, NULL, NULL,
-                                      True);
+       status = make_user_info_map(user_info,
+                                   smb_name, client_domain, 
+                                   wksta_name, 
+                                   lm_pwd_len ? &lm_blob : NULL, 
+                                   nt_pwd_len ? &nt_blob : NULL,
+                                   NULL, NULL, NULL,
+                                   True);
 
-       if (NT_STATUS_IS_OK(nt_status)) {
+       if (NT_STATUS_IS_OK(status)) {
                (*user_info)->logon_parameters = logon_parameters;
        }
-       ret = NT_STATUS_IS_OK(nt_status) ? True : False;
+       ret = NT_STATUS_IS_OK(status) ? True : False;
 
        data_blob_free(&lm_blob);
        data_blob_free(&nt_blob);
@@ -246,8 +245,11 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
        ZERO_STRUCT(key);
        memcpy(key, dc_sess_key, 8);
        
-       if (lm_interactive_pwd) memcpy(lm_pwd, lm_interactive_pwd, sizeof(lm_pwd));
-       if (nt_interactive_pwd) memcpy(nt_pwd, nt_interactive_pwd, sizeof(nt_pwd));
+       if (lm_interactive_pwd)
+               memcpy(lm_pwd, lm_interactive_pwd, sizeof(lm_pwd));
+
+       if (nt_interactive_pwd)
+               memcpy(nt_pwd, nt_interactive_pwd, sizeof(nt_pwd));
        
 #ifdef DEBUG_PASSWORD
        DEBUG(100,("key:"));
@@ -275,10 +277,12 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
 #endif
        
        if (lm_interactive_pwd)
-               SMBOWFencrypt((const unsigned char *)lm_pwd, chal, local_lm_response);
+               SMBOWFencrypt((const unsigned char *)lm_pwd, chal,
+                             local_lm_response);
 
        if (nt_interactive_pwd)
-               SMBOWFencrypt((const unsigned char *)nt_pwd, chal, local_nt_response);
+               SMBOWFencrypt((const unsigned char *)nt_pwd, chal,
+                             local_nt_response);
        
        /* Password info paranoia */
        ZERO_STRUCT(key);
@@ -293,26 +297,29 @@ BOOL make_user_info_netlogon_interactive(auth_usersupplied_info **user_info,
                DATA_BLOB nt_interactive_blob;
                
                if (lm_interactive_pwd) {
-                       local_lm_blob = data_blob(local_lm_response, sizeof(local_lm_response));
-                       lm_interactive_blob = data_blob(lm_pwd, sizeof(lm_pwd));
+                       local_lm_blob = data_blob(local_lm_response,
+                                                 sizeof(local_lm_response));
+                       lm_interactive_blob = data_blob(lm_pwd,
+                                                       sizeof(lm_pwd));
                        ZERO_STRUCT(lm_pwd);
                }
                
                if (nt_interactive_pwd) {
-                       local_nt_blob = data_blob(local_nt_response, sizeof(local_nt_response));
-                       nt_interactive_blob = data_blob(nt_pwd, sizeof(nt_pwd));
+                       local_nt_blob = data_blob(local_nt_response,
+                                                 sizeof(local_nt_response));
+                       nt_interactive_blob = data_blob(nt_pwd,
+                                                       sizeof(nt_pwd));
                        ZERO_STRUCT(nt_pwd);
                }
 
-               nt_status = make_user_info_map(user_info, 
-                                              smb_name, client_domain, 
-                                              wksta_name, 
-                                              lm_interactive_pwd ? &local_lm_blob : NULL,
-                                              nt_interactive_pwd ? &local_nt_blob : NULL,
-                                              lm_interactive_pwd ? &lm_interactive_blob : NULL,
-                                              nt_interactive_pwd ? &nt_interactive_blob : NULL,
-                                              NULL,
-                                              True);
+               nt_status = make_user_info_map(
+                       user_info, 
+                       smb_name, client_domain, wksta_name, 
+                       lm_interactive_pwd ? &local_lm_blob : NULL,
+                       nt_interactive_pwd ? &local_nt_blob : NULL,
+                       lm_interactive_pwd ? &lm_interactive_blob : NULL,
+                       nt_interactive_pwd ? &nt_interactive_blob : NULL,
+                       NULL, True);
 
                if (NT_STATUS_IS_OK(nt_status)) {
                        (*user_info)->logon_parameters = logon_parameters;
@@ -347,17 +354,21 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
         * Not encrypted - do so.
         */
        
-       DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted format.\n"));
+       DEBUG(5,("make_user_info_for_reply: User passwords not in encrypted "
+                "format.\n"));
        
        if (plaintext_password.data) {
                unsigned char local_lm_response[24];
                
 #ifdef DEBUG_PASSWORD
-               DEBUG(10,("Unencrypted password (len %d):\n",(int)plaintext_password.length));
-               dump_data(100, (const char *)plaintext_password.data, plaintext_password.length);
+               DEBUG(10,("Unencrypted password (len %d):\n",
+                         (int)plaintext_password.length));
+               dump_data(100, (const char *)plaintext_password.data,
+                         plaintext_password.length);
 #endif
 
-               SMBencrypt( (const char *)plaintext_password.data, (const uchar*)chal, local_lm_response);
+               SMBencrypt( (const char *)plaintext_password.data,
+                           (const uchar*)chal, local_lm_response);
                local_lm_blob = data_blob(local_lm_response, 24);
                
                /* We can't do an NT hash here, as the password needs to be
@@ -369,14 +380,14 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info,
                local_nt_blob = data_blob(NULL, 0); 
        }
        
-       ret = make_user_info_map(user_info, smb_name,
-                                client_domain, 
-                                get_remote_machine_name(),
-                                local_lm_blob.data ? &local_lm_blob : NULL,
-                                local_nt_blob.data ? &local_nt_blob : NULL,
-                                NULL, NULL,
-                                plaintext_password.data ? &plaintext_password : NULL, 
-                                False);
+       ret = make_user_info_map(
+               user_info, smb_name, client_domain, 
+               get_remote_machine_name(),
+               local_lm_blob.data ? &local_lm_blob : NULL,
+               local_nt_blob.data ? &local_nt_blob : NULL,
+               NULL, NULL,
+               plaintext_password.data ? &plaintext_password : NULL, 
+               False);
        
        data_blob_free(&local_lm_blob);
        return NT_STATUS_IS_OK(ret) ? True : False;
@@ -426,7 +437,6 @@ BOOL make_user_info_guest(auth_usersupplied_info **user_info)
 
 void debug_nt_user_token(int dbg_class, int dbg_lev, NT_USER_TOKEN *token)
 {
-       fstring sid_str;
        size_t     i;
        
        if (!token) {
@@ -434,12 +444,15 @@ void debug_nt_user_token(int dbg_class, int dbg_lev, NT_USER_TOKEN *token)
                return;
        }
        
-       DEBUGC(dbg_class, dbg_lev, ("NT user token of user %s\n",
-                                   sid_to_string(sid_str, &token->user_sids[0]) ));
-       DEBUGADDC(dbg_class, dbg_lev, ("contains %lu SIDs\n", (unsigned long)token->num_sids));
+       DEBUGC(dbg_class, dbg_lev,
+              ("NT user token of user %s\n",
+               sid_string_static(&token->user_sids[0]) ));
+       DEBUGADDC(dbg_class, dbg_lev,
+                 ("contains %lu SIDs\n", (unsigned long)token->num_sids));
        for (i = 0; i < token->num_sids; i++)
-               DEBUGADDC(dbg_class, dbg_lev, ("SID[%3lu]: %s\n", (unsigned long)i, 
-                                              sid_to_string(sid_str, &token->user_sids[i])));
+               DEBUGADDC(dbg_class, dbg_lev,
+                         ("SID[%3lu]: %s\n", (unsigned long)i, 
+                          sid_string_static(&token->user_sids[i])));
 
        dump_se_priv( dbg_class, dbg_lev, &token->privileges );
 }
@@ -448,464 +461,568 @@ void debug_nt_user_token(int dbg_class, int dbg_lev, NT_USER_TOKEN *token)
  prints a UNIX 'token' to debug output.
 ****************************************************************************/
 
-void debug_unix_user_token(int dbg_class, int dbg_lev, uid_t uid, gid_t gid, int n_groups, gid_t *groups)
+void debug_unix_user_token(int dbg_class, int dbg_lev, uid_t uid, gid_t gid,
+                          int n_groups, gid_t *groups)
 {
        int     i;
-       DEBUGC(dbg_class, dbg_lev, ("UNIX token of user %ld\n", (long int)uid));
+       DEBUGC(dbg_class, dbg_lev,
+              ("UNIX token of user %ld\n", (long int)uid));
 
-       DEBUGADDC(dbg_class, dbg_lev, ("Primary group is %ld and contains %i supplementary groups\n", (long int)gid, n_groups));
+       DEBUGADDC(dbg_class, dbg_lev,
+                 ("Primary group is %ld and contains %i supplementary "
+                  "groups\n", (long int)gid, n_groups));
        for (i = 0; i < n_groups; i++)
                DEBUGADDC(dbg_class, dbg_lev, ("Group[%3i]: %ld\n", i, 
                        (long int)groups[i]));
 }
 
-/****************************************************************************
- Create the SID list for this user.
-****************************************************************************/
+/******************************************************************************
+ Create a token for the root user to be used internally by smbd.
+ This is similar to running under the context of the LOCAL_SYSTEM account
+ in Windows.  This is a read-only token.  Do not modify it or free() it.
+ Create a copy if your need to change it.
+******************************************************************************/
 
-static NTSTATUS create_nt_user_token(const DOM_SID *user_sid, const DOM_SID *group_sid, 
-                                    int n_groupSIDs, DOM_SID *groupSIDs, 
-                                    BOOL is_guest, NT_USER_TOKEN **token)
+NT_USER_TOKEN *get_root_nt_token( void )
 {
-       NTSTATUS       nt_status = NT_STATUS_OK;
-       NT_USER_TOKEN *ptoken;
-       int i;
-       int sid_ndx;
-       DOM_SID domadm;
-       BOOL is_domain_admin = False;
-       BOOL domain_mode = False;
+       static NT_USER_TOKEN *token = NULL;
+       DOM_SID u_sid, g_sid;
+       struct passwd *pw;
        
-       if ((ptoken = SMB_MALLOC_P(NT_USER_TOKEN)) == NULL) {
-               DEBUG(0, ("create_nt_user_token: Out of memory allocating token\n"));
-               nt_status = NT_STATUS_NO_MEMORY;
-               return nt_status;
+       if ( token )
+               return token;
+               
+       if ( !(pw = getpwnam( "root" )) ) {
+               DEBUG(0,("get_root_nt_token: getpwnam\"root\") failed!\n"));
+               return NULL;
        }
+       
+       /* get the user and primary group SIDs; although the 
+          BUILTIN\Administrators SId is really the one that matters here */
+          
+       uid_to_sid(&u_sid, pw->pw_uid);
+       gid_to_sid(&g_sid, pw->pw_gid);
 
-       ZERO_STRUCTP(ptoken);
+       token = create_local_nt_token(NULL, &u_sid, &g_sid, False,
+                                     1, &global_sid_Builtin_Administrators);
+       return token;
+}
 
-       ptoken->num_sids = n_groupSIDs + 5;
+static int server_info_dtor(void *p)
+{
+       auth_serversupplied_info *server_info =
+               talloc_get_type_abort(p, auth_serversupplied_info);
 
-       if ((ptoken->user_sids = SMB_MALLOC_ARRAY( DOM_SID, ptoken->num_sids )) == NULL) {
-               DEBUG(0, ("create_nt_user_token: Out of memory allocating SIDs\n"));
-               nt_status = NT_STATUS_NO_MEMORY;
-               return nt_status;
+       if (server_info->sam_account != NULL) {
+               pdb_free_sam(&server_info->sam_account);
        }
-       
-       memset((char*)ptoken->user_sids,0,sizeof(DOM_SID) * ptoken->num_sids);
-       
-       /*
-        * Note - user SID *MUST* be first in token !
-        * se_access_check depends on this.
-        *
-        * Primary group SID is second in token. Convention.
-        */
 
-       sid_copy(&ptoken->user_sids[PRIMARY_USER_SID_INDEX], user_sid);
-       if (group_sid)
-               sid_copy(&ptoken->user_sids[PRIMARY_GROUP_SID_INDEX], group_sid);
+       ZERO_STRUCTP(server_info);
+       return 0;
+}
 
-       /*
-        * Finally add the "standard" SIDs.
-        * The only difference between guest and "anonymous" (which we
-        * don't really support) is the addition of Authenticated_Users.
-        */
+/***************************************************************************
+ Make a server_info struct. Free with talloc_free().
+***************************************************************************/
+
+static auth_serversupplied_info *make_server_info(TALLOC_CTX *mem_ctx)
+{
+       struct auth_serversupplied_info *result;
 
-       sid_copy(&ptoken->user_sids[2], &global_sid_World);
-       sid_copy(&ptoken->user_sids[3], &global_sid_Network);
+       result = TALLOC_ZERO_P(mem_ctx, auth_serversupplied_info);
+       if (result == NULL) {
+               DEBUG(0, ("talloc failed\n"));
+               return NULL;
+       }
 
-       if (is_guest)
-               sid_copy(&ptoken->user_sids[4], &global_sid_Builtin_Guests);
-       else
-               sid_copy(&ptoken->user_sids[4], &global_sid_Authenticated_Users);
-       
-       sid_ndx = 5; /* next available spot */
-
-       /* this is where we construct the domain admins SID if we can
-          so that we can add the BUILTIN\Administrators SID to the token */
-
-       ZERO_STRUCT( domadm );
-       if ( IS_DC || lp_server_role()==ROLE_DOMAIN_MEMBER ) {
-               domain_mode = True;
-
-               if ( IS_DC ) 
-                       sid_copy( &domadm, get_global_sam_sid() );
-               else {
-                       /* if we a re a member server and cannot find
-                          out domain SID then reset the domain_mode flag */
-                       if ( !secrets_fetch_domain_sid( lp_workgroup(), &domadm ) )
-                               domain_mode = False;
-               }
+       talloc_set_destructor(result, server_info_dtor);
+
+       /* Initialise the uid and gid values to something non-zero
+          which may save us from giving away root access if there
+          is a bug in allocating these fields. */
+
+       result->uid = -1;
+       result->gid = -1;
+       return result;
+}
 
-               sid_append_rid( &domadm, DOMAIN_GROUP_RID_ADMINS );
+/***************************************************************************
+ Make (and fill) a user_info struct from a SAM_ACCOUNT
+***************************************************************************/
+
+NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info, 
+                             SAM_ACCOUNT *sampass)
+{
+       NTSTATUS status;
+       struct passwd *pwd;
+       gid_t *gids;
+       auth_serversupplied_info *result;
+
+       pwd = getpwnam_alloc(NULL, pdb_get_username(sampass));
+       if ( pwd == NULL )  {
+               DEBUG(1, ("User %s in passdb, but getpwnam() fails!\n",
+                         pdb_get_username(sampass)));
+               return NT_STATUS_NO_SUCH_USER;
        }
-       
-       /* add the group SIDs to teh token */
-       
-       for (i = 0; i < n_groupSIDs; i++) {
-               size_t check_sid_idx;
-               for (check_sid_idx = 1; check_sid_idx < ptoken->num_sids; check_sid_idx++) {
-                       if (sid_equal(&ptoken->user_sids[check_sid_idx], 
-                                     &groupSIDs[i])) {
-                               break;
-                       }
-               }
-               
-               if (check_sid_idx >= ptoken->num_sids) /* Not found already */ {
-                       sid_copy(&ptoken->user_sids[sid_ndx++], &groupSIDs[i]);
-               } else {
-                       ptoken->num_sids--;
-               }
-               
-               /* here we check if the user is a domain admin and add the
-                  BUILTIN\Administrators SID to the token the group membership
-                  check succeeds. */
 
-               if ( domain_mode ) {
-                       if ( sid_equal( &domadm, &groupSIDs[i] ) )
-                               is_domain_admin = True;
-               }
-               
+       result = make_server_info(NULL);
+       if (result == NULL) {
+               talloc_free(pwd);
+               return NT_STATUS_NO_MEMORY;
        }
 
-       /* finally realloc the SID array and add the BUILTIN\Administrators 
-          SID if necessary */
+       result->sam_account = sampass;
+       result->unix_name = talloc_strdup(result, pwd->pw_name);
+       result->gid = pwd->pw_gid;
+       result->uid = pwd->pw_uid;
+       
+       talloc_free(pwd);
 
-       if ( is_domain_admin ) {
-               DOM_SID *sids;
+       status = pdb_enum_group_memberships(result, sampass,
+                                           &result->sids, &gids,
+                                           &result->num_sids);
 
-               if ( !(sids = SMB_REALLOC_ARRAY( ptoken->user_sids, DOM_SID, ptoken->num_sids+1 )) ) 
-                       DEBUG(0,("create_nt_user_token: Failed to realloc SID arry of size %d\n", ptoken->num_sids+1));
-               else  {
-                       ptoken->user_sids = sids;
-                       sid_copy( &(ptoken->user_sids)[ptoken->num_sids++], &global_sid_Builtin_Administrators );
-               }
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10, ("pdb_enum_group_memberships failed: %s\n",
+                          nt_errstr(status)));
+               result->sam_account = NULL; /* Don't free on error exit. */
+               talloc_free(result);
+               return status;
        }
 
-       /* add privileges assigned to this user */
+       /* For now we throw away the gids and convert via sid_to_gid
+        * later. This needs fixing, but I'd like to get the code straight and
+        * simple first. */
+       talloc_free(gids);
 
-       get_privileges_for_sids( &ptoken->privileges, ptoken->user_sids, ptoken->num_sids );
-       
-       debug_nt_user_token(DBGC_AUTH, 10, ptoken);
-       
-       if ((lp_log_nt_token_command() != NULL) &&
-           (strlen(lp_log_nt_token_command()) > 0)) {
-               TALLOC_CTX *mem_ctx;
-               char *command;
-               char *group_sidstr;
-
-               mem_ctx = talloc_init("setnttoken");
-               if (mem_ctx == NULL)
-                       return NT_STATUS_NO_MEMORY;
+       DEBUG(5,("make_server_info_sam: made server info for user %s -> %s\n",
+                pdb_get_username(sampass), result->unix_name));
 
-               group_sidstr = talloc_strdup(mem_ctx, "");
-               for (i=1; i<ptoken->num_sids; i++) {
-                       group_sidstr = talloc_asprintf(
-                               mem_ctx, "%s %s", group_sidstr,
-                               sid_string_static(&ptoken->user_sids[i]));
-               }
+       *server_info = result;
 
-               command = talloc_string_sub(
-                       mem_ctx, lp_log_nt_token_command(),
-                       "%s", sid_string_static(&ptoken->user_sids[0]));
-               command = talloc_string_sub(
-                       mem_ctx, command, "%t", group_sidstr);
+       return NT_STATUS_OK;
+}
+
+/*
+ * Add alias SIDs from memberships within the partially created token SID list
+ */
 
-               if (command == NULL) {
-                       talloc_destroy(mem_ctx);
+static NTSTATUS add_aliases(TALLOC_CTX *tmp_ctx, const DOM_SID *domain_sid,
+                           struct nt_user_token *token)
+{
+       uint32 *aliases;
+       size_t i, num_aliases;
+       NTSTATUS status;
+
+       aliases = NULL;
+       num_aliases = 0;
+
+       status = pdb_enum_alias_memberships(tmp_ctx, domain_sid,
+                                           token->user_sids,
+                                           token->num_sids,
+                                           &aliases, &num_aliases);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10, ("pdb_enum_alias_memberships failed: %s\n",
+                          nt_errstr(status)));
+               return status;
+       }
+
+       for (i=0; i<num_aliases; i++) {
+               DOM_SID alias_sid;
+               sid_compose(&alias_sid, domain_sid, aliases[i]);
+               add_sid_to_array_unique(token, &alias_sid,
+                                       &token->user_sids,
+                                       &token->num_sids);
+               if (token->user_sids == NULL) {
+                       DEBUG(0, ("add_sid_to_array failed\n"));
                        return NT_STATUS_NO_MEMORY;
                }
+       }
 
-               DEBUG(8, ("running command: [%s]\n", command));
-               if (smbrun(command, NULL) != 0) {
-                       DEBUG(0, ("Could not log NT token\n"));
-                       nt_status = NT_STATUS_ACCESS_DENIED;
-               }
-               talloc_destroy(mem_ctx);
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS log_nt_token(TALLOC_CTX *tmp_ctx, NT_USER_TOKEN *token)
+{
+       char *command;
+       char *group_sidstr;
+       size_t i;
+
+       if ((lp_log_nt_token_command() == NULL) ||
+           (strlen(lp_log_nt_token_command()) == 0)) {
+               return NT_STATUS_OK;
        }
 
-       *token = ptoken;
+       group_sidstr = talloc_strdup(tmp_ctx, "");
+       for (i=1; i<token->num_sids; i++) {
+               group_sidstr = talloc_asprintf(
+                       tmp_ctx, "%s %s", group_sidstr,
+                       sid_string_static(&token->user_sids[i]));
+       }
 
-       return nt_status;
-}
+       command = talloc_string_sub(
+               tmp_ctx, lp_log_nt_token_command(),
+               "%s", sid_string_static(&token->user_sids[0]));
+       command = talloc_string_sub(tmp_ctx, command, "%t", group_sidstr);
 
-/****************************************************************************
- Create the SID list for this user.
-****************************************************************************/
+       if (command == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       DEBUG(8, ("running command: [%s]\n", command));
+       if (smbrun(command, NULL) != 0) {
+               DEBUG(0, ("Could not log NT token\n"));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       return NT_STATUS_OK;
+}
 
-NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, BOOL is_guest)
+/*
+ * Create a NT token for the user, expanding local aliases
+ */
+
+static struct nt_user_token *create_local_nt_token(TALLOC_CTX *mem_ctx,
+                                                  const DOM_SID *user_sid,
+                                                  const DOM_SID *group_sid,
+                                                  BOOL is_guest,
+                                                  int num_groupsids,
+                                                  const DOM_SID *groupsids)
 {
-       DOM_SID user_sid;
-       DOM_SID group_sid;
-       DOM_SID *group_sids;
-       NT_USER_TOKEN *token;
+       TALLOC_CTX *tmp_ctx;
+       struct nt_user_token *result = NULL;
        int i;
+       NTSTATUS status;
 
-       if (!NT_STATUS_IS_OK(uid_to_sid(&user_sid, uid))) {
+       tmp_ctx = talloc_new(mem_ctx);
+       if (tmp_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
                return NULL;
        }
-       if (!NT_STATUS_IS_OK(gid_to_sid(&group_sid, gid))) {
-               return NULL;
+
+       result = TALLOC_ZERO_P(tmp_ctx, NT_USER_TOKEN);
+       if (result == NULL) {
+               DEBUG(0, ("talloc failed\n"));
+               goto done;
        }
 
-       group_sids = SMB_MALLOC_ARRAY(DOM_SID, ngroups);
-       if (!group_sids) {
-               DEBUG(0, ("create_nt_token: malloc() failed for DOM_SID list!\n"));
-               return NULL;
+       /* First create the default SIDs */
+
+       add_sid_to_array(result, user_sid,
+                        &result->user_sids, &result->num_sids);
+       add_sid_to_array(result, group_sid,
+                        &result->user_sids, &result->num_sids);
+       add_sid_to_array(result, &global_sid_World,
+                        &result->user_sids, &result->num_sids);
+       add_sid_to_array(result, &global_sid_Network,
+                        &result->user_sids, &result->num_sids);
+
+       if (is_guest) {
+               add_sid_to_array(result, &global_sid_Builtin_Guests,
+                                &result->user_sids, &result->num_sids);
+       } else {
+               add_sid_to_array(result, &global_sid_Authenticated_Users,
+                                &result->user_sids, &result->num_sids);
        }
 
-       /* convert the Unix group ids to SIDS */
+       /* Now the SIDs we got from authentication. These are the ones from
+        * the info3 struct or from the pdb_enum_group_memberships, depending
+        * on who authenticated the user. */
 
-       for (i = 0; i < ngroups; i++) {
-               if (!NT_STATUS_IS_OK(gid_to_sid(&(group_sids)[i], (groups)[i]))) {
-                       DEBUG(1, ("create_nt_token: failed to convert gid %ld to a sid!\n", (long int)groups[i]));
-                       SAFE_FREE(group_sids);
-                       return NULL;
-               }
+       for (i=0; i<num_groupsids; i++) {
+               add_sid_to_array_unique(result, &groupsids[i],
+                                       &result->user_sids, &result->num_sids);
        }
 
-       if (!NT_STATUS_IS_OK(create_nt_user_token(&user_sid, &group_sid, 
-                                                 ngroups, group_sids, is_guest, &token))) {
-               SAFE_FREE(group_sids);
-               return NULL;
+       if (lp_winbind_nested_groups()) {
+
+               /* Now add the aliases. First the one from our local SAM */
+
+               status = add_aliases(tmp_ctx, get_global_sam_sid(), result);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       result = NULL;
+                       goto done;
+               }
+
+               /* Finally the builtin ones */
+
+               status = add_aliases(tmp_ctx, &global_sid_Builtin, result);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       result = NULL;
+                       goto done;
+               }
+       } else {
+
+               /* Play jerry's trick to auto-add local admins if we're a
+                * domain admin. */
+
+               DOM_SID dom_admins;
+               BOOL domain_mode = False;
+
+               if (IS_DC) {
+                       sid_compose(&dom_admins, get_global_sam_sid(),
+                                   DOMAIN_GROUP_RID_ADMINS);
+                       domain_mode = True;
+               }
+               if ((lp_server_role() == ROLE_DOMAIN_MEMBER) &&
+                   (secrets_fetch_domain_sid(lp_workgroup(), &dom_admins))) {
+                       sid_append_rid(&dom_admins, DOMAIN_GROUP_RID_ADMINS);
+                       domain_mode = True;
+               }
+
+               if (domain_mode) {
+                       for (i=0; i<result->num_sids; i++) {
+                               if (sid_equal(&dom_admins,
+                                             &result->user_sids[i])) {
+                                       add_sid_to_array_unique(
+                                               result,
+                                               &global_sid_Builtin_Administrators,
+                                               &result->user_sids,
+                                               &result->num_sids);
+                                       break;
+                               }
+                       }
+                       
+               }
        }
 
-       SAFE_FREE(group_sids);
+       get_privileges_for_sids(&result->privileges, result->user_sids,
+                               result->num_sids);
 
-       return token;
+       talloc_steal(mem_ctx, result);
+
+ done:
+       talloc_free(tmp_ctx);
+       return result;
 }
 
-/******************************************************************************
- Create a token for the root user to be used internally by smbd.
- This is similar to running under the context of the LOCAL_SYSTEM account
- in Windows.  This is a read-only token.  Do not modify it or free() it.
- Create a copy if your need to change it.
-******************************************************************************/
+/*
+ * Create the token to use from server_info->sam_account and
+ * server_info->sids (the info3/sam groups). Find the unix gids.
+ */
 
-NT_USER_TOKEN *get_root_nt_token( void )
+NTSTATUS create_local_token(auth_serversupplied_info *server_info)
 {
-       static NT_USER_TOKEN *token = NULL;
-       DOM_SID u_sid, g_sid;
-       DOM_SID g_sids[1];
-       struct passwd *pw;
-       NTSTATUS result;
+       TALLOC_CTX *mem_ctx;
+       NTSTATUS status;
+       size_t i;
        
-       if ( token )
-               return token;
-               
-       if ( !(pw = getpwnam( "root" )) ) {
-               DEBUG(0,("get_root_nt_token: getpwnam\"root\") failed!\n"));
-               return NULL;
+
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
+               return NT_STATUS_NO_MEMORY;
        }
+
+       server_info->ptok = create_local_nt_token(
+               server_info,
+               pdb_get_user_sid(server_info->sam_account),
+               pdb_get_group_sid(server_info->sam_account),
+               server_info->guest,
+               server_info->num_sids, server_info->sids);
        
-       /* get the user and primary group SIDs; although the 
-          BUILTIN\Administrators SId is really the one that matters here */
-          
-       if ( !NT_STATUS_IS_OK(uid_to_sid(&u_sid, pw->pw_uid)) )
-               return NULL;
-       if ( !NT_STATUS_IS_OK(gid_to_sid(&g_sid, pw->pw_gid)) )
-               return NULL;
-               
-       sid_copy( &g_sids[0], &global_sid_Builtin_Administrators );
-       
-       result = create_nt_user_token( &u_sid, &g_sid, 1, g_sids, False, &token);
+       /* Convert the SIDs to gids. */
+
+       server_info->n_groups = 0;
+       server_info->groups = NULL;
+
+       /* Start at index 1, where the groups start. */
+
+       for (i=1; i<server_info->ptok->num_sids; i++) {
+               gid_t gid;
+               DOM_SID *sid = &server_info->ptok->user_sids[i];
+
+               if (!sid_to_gid(sid, &gid)) {
+                       DEBUG(10, ("Could not convert SID %s to gid, "
+                                  "ignoring it\n", sid_string_static(sid)));
+                       continue;
+               }
+               add_gid_to_array_unique(server_info, gid, &server_info->groups,
+                                       &server_info->n_groups);
+       }
        
-       return NT_STATUS_IS_OK(result) ? token : NULL;
+       debug_nt_user_token(DBGC_AUTH, 10, server_info->ptok);
+
+       status = log_nt_token(mem_ctx, server_info->ptok);
+
+       talloc_free(mem_ctx);
+       return status;
 }
 
-/******************************************************************************
- * this function returns the groups (SIDs) of the local SAM the user is in.
- * If this samba server is a DC of the domain the user belongs to, it returns 
- * both domain groups and local / builtin groups. If the user is in a trusted
- * domain, or samba is a member server of a domain, then this function returns
- * local and builtin groups the user is a member of.
+/*
+ * Create an artificial NT token given just a username. (Initially indended
+ * for force user)
  *
- * currently this is a hack, as there is no sam implementation that is capable
- * of groups.
+ * We go through lookup_name() to avoid problems we had with 'winbind use
+ * default domain'.
  *
- * NOTE!! This function will fail if you pass in a winbind user without 
- * the domain   --jerry
- ******************************************************************************/
-
-static NTSTATUS get_user_groups(const char *username, uid_t uid, gid_t gid,
-                                size_t *n_groups, DOM_SID **groups, gid_t **unix_groups)
+ * We have 3 cases:
+ *
+ * unmapped unix users: Go directly to nss to find the user's group.
+ *
+ * A passdb user: The list of groups is provided by pdb_enum_group_memberships.
+ *
+ * If the user is provided by winbind, the primary gid is set to "domain
+ * users" of the user's domain. For an explanation why this is necessary, see
+ * the thread starting at
+ * http://lists.samba.org/archive/samba-technical/2006-January/044803.html.
+ */
+
+NTSTATUS create_token_from_username(TALLOC_CTX *mem_ctx, const char *username,
+                                   BOOL is_guest,
+                                   uid_t *uid, gid_t *gid,
+                                   char **found_username,
+                                   struct nt_user_token **token)
 {
-       int             n_unix_groups;
-       int             i;
+       NTSTATUS result = NT_STATUS_NO_SUCH_USER;
+       TALLOC_CTX *tmp_ctx;
+       DOM_SID user_sid;
+       enum SID_NAME_USE type;
+       gid_t *gids;
+       DOM_SID primary_group_sid;
+       DOM_SID *group_sids;
+       size_t num_group_sids;
 
-       *n_groups = 0;
-       *groups   = NULL;
+       tmp_ctx = talloc_new(NULL);
+       if (tmp_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       if (strchr(username, *lp_winbind_separator()) == NULL) {
-               NTSTATUS result;
+       if (!lookup_name(tmp_ctx, username, LOOKUP_NAME_ALL,
+                        NULL, NULL, &user_sid, &type)) {
+               DEBUG(1, ("lookup_name for %s failed\n", username));
+               goto done;
+       }
 
-               become_root();
-               result = pdb_enum_group_memberships(username, gid, groups,
-                                                   unix_groups, n_groups);
-               unbecome_root();
-               return result;
+       if (type != SID_NAME_USER) {
+               DEBUG(1, ("%s is a %s, not a user\n", username,
+                         sid_type_lookup(type)));
+               goto done;
        }
 
-       /* We have the separator, this must be winbind */
-       
-       n_unix_groups = winbind_getgroups( username, unix_groups );
+       if (!sid_to_uid(&user_sid, uid)) {
+               DEBUG(1, ("sid_to_uid for %s (%s) failed\n",
+                         username, sid_string_static(&user_sid)));
+               goto done;
+       }
 
-       DEBUG(10,("get_user_groups: winbind_getgroups(%s): result = %s\n",
-                 username,  n_unix_groups == -1 ? "FAIL" : "SUCCESS"));
-                         
-       if ( n_unix_groups == -1 )
-               return NT_STATUS_NO_SUCH_USER; /* what should this return
-                                               * value be? */  
+       if (sid_check_is_in_unix_users(&user_sid)) {
 
-       debug_unix_user_token(DBGC_CLASS, 5, uid, gid, n_unix_groups, *unix_groups);
-       
-       /* now setup the space for storing the SIDS */
-       
-       if (n_unix_groups > 0) {
-       
-               *groups   = SMB_MALLOC_ARRAY(DOM_SID, n_unix_groups);
-               
-               if (!*groups) {
-                       DEBUG(0, ("get_user_group: malloc() failed for DOM_SID list!\n"));
-                       SAFE_FREE(*unix_groups);
-                       return NT_STATUS_NO_MEMORY;
+               /* This is a unix user not in passdb. We need to ask nss
+                * directly, without consulting passdb */
+
+               struct passwd *pass;
+               size_t i;
+
+               pass = getpwuid_alloc(tmp_ctx, *uid);
+               if (pass == NULL) {
+                       DEBUG(1, ("getpwuid(%d) for user %s failed\n",
+                                 *uid, username));
+                       goto done;
                }
-       }
 
-       *n_groups = n_unix_groups;
+               *gid = pass->pw_gid;
+               gid_to_sid(&primary_group_sid, pass->pw_gid);
 
-       for (i = 0; i < *n_groups; i++) {
-               if (!NT_STATUS_IS_OK(gid_to_sid(&(*groups)[i], (*unix_groups)[i]))) {
-                       DEBUG(1, ("get_user_groups: failed to convert gid %ld to a sid!\n", 
-                               (long int)(*unix_groups)[i+1]));
-                       SAFE_FREE(*groups);
-                       SAFE_FREE(*unix_groups);
-                       return NT_STATUS_NO_SUCH_USER;
+               if (!getgroups_unix_user(tmp_ctx, username, pass->pw_gid,
+                                        &gids, &num_group_sids)) {
+                       DEBUG(1, ("getgroups_unix_user for user %s failed\n",
+                                 username));
+                       goto done;
                }
-       }
-                    
-       return NT_STATUS_OK;
-}
 
-/***************************************************************************
- Make a user_info struct
-***************************************************************************/
+               group_sids = talloc_array(tmp_ctx, DOM_SID, num_group_sids);
+               if (group_sids == NULL) {
+                       DEBUG(1, ("talloc_array failed\n"));
+                       result = NT_STATUS_NO_MEMORY;
+                       goto done;
+               }
 
-static NTSTATUS make_server_info(auth_serversupplied_info **server_info)
-{
-       *server_info = SMB_MALLOC_P(auth_serversupplied_info);
-       if (!*server_info) {
-               DEBUG(0,("make_server_info: malloc failed!\n"));
-               return NT_STATUS_NO_MEMORY;
-       }
-       ZERO_STRUCTP(*server_info);
+               for (i=0; i<num_group_sids; i++) {
+                       gid_to_sid(&group_sids[i], gids[i]);
+               }
+               *found_username = talloc_strdup(mem_ctx, pass->pw_name);
 
-       /* Initialise the uid and gid values to something non-zero
-          which may save us from giving away root access if there
-          is a bug in allocating these fields. */
+       } else if (sid_check_is_in_our_domain(&user_sid)) {
 
-       (*server_info)->uid = -1;
-       (*server_info)->gid = -1;
+               /* This is a passdb user, so ask passdb */
 
-       return NT_STATUS_OK;
-}
+               SAM_ACCOUNT *sam_acct = NULL;
 
-/***************************************************************************
-Fill a server_info struct from a SAM_ACCOUNT with their groups
-***************************************************************************/
+               result = pdb_init_sam_talloc(tmp_ctx, &sam_acct);
+               if (!NT_STATUS_IS_OK(result)) {
+                       goto done;
+               }
 
-static NTSTATUS add_user_groups(auth_serversupplied_info **server_info, 
-                               const char * unix_username,
-                               SAM_ACCOUNT *sampass,
-                               uid_t uid, gid_t gid)
-{
-       NTSTATUS nt_status;
-       const DOM_SID *user_sid = pdb_get_user_sid(sampass);
-       const DOM_SID *group_sid = pdb_get_group_sid(sampass);
-       size_t       n_groupSIDs = 0;
-       DOM_SID  *groupSIDs   = NULL;
-       gid_t    *unix_groups = NULL;
-       NT_USER_TOKEN *token;
-       BOOL is_guest;
-       uint32 rid;
+               if (!pdb_getsampwsid(sam_acct, &user_sid)) {
+                       DEBUG(1, ("pdb_getsampwsid(%s) for user %s failed\n",
+                                 sid_string_static(&user_sid), username));
+                       result = NT_STATUS_NO_SUCH_USER;
+                       goto done;
+               }
 
-       nt_status = get_user_groups(unix_username, uid, gid, 
-               &n_groupSIDs, &groupSIDs, &unix_groups);
-               
-       if (!NT_STATUS_IS_OK(nt_status)) {
-               DEBUG(4,("get_user_groups_from_local_sam failed\n"));
-               free_server_info(server_info);
-               return nt_status;
-       }
-       
-       is_guest = (sid_peek_rid(user_sid, &rid) && rid == DOMAIN_USER_RID_GUEST);
+               sid_copy(&primary_group_sid, pdb_get_group_sid(sam_acct));
 
-       if (!NT_STATUS_IS_OK(nt_status = create_nt_user_token(user_sid, group_sid,
-                                                             n_groupSIDs, groupSIDs, is_guest, 
-                                                             &token)))
-       {
-               DEBUG(4,("create_nt_user_token failed\n"));
-               SAFE_FREE(groupSIDs);
-               SAFE_FREE(unix_groups);
-               free_server_info(server_info);
-               return nt_status;
-       }
-       
-       SAFE_FREE(groupSIDs);
+               result = pdb_enum_group_memberships(tmp_ctx, sam_acct,
+                                                   &group_sids, &gids,
+                                                   &num_group_sids);
+               if (!NT_STATUS_IS_OK(result)) {
+                       DEBUG(10, ("enum_group_memberships failed for %s\n",
+                                  username));
+                       goto done;
+               }
 
-       (*server_info)->n_groups = n_groupSIDs;
-       (*server_info)->groups = unix_groups;
-       (*server_info)->ptok = token;
+               *found_username = talloc_strdup(mem_ctx,
+                                               pdb_get_username(sam_acct));
 
-       return nt_status;
-}
+       } else {
 
-/***************************************************************************
- Make (and fill) a user_info struct from a SAM_ACCOUNT
-***************************************************************************/
+               /* This user is from winbind, force the primary gid to the
+                * user's "domain users" group. Under certain circumstances
+                * (user comes from NT4), this might be a loss of
+                * information. But we can not rely on winbind getting the
+                * correct info. AD might prohibit winbind looking up that
+                * information. */
 
-NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info, 
-                             SAM_ACCOUNT *sampass)
-{
-       NTSTATUS nt_status;
-       struct passwd *pwd;
+               uint32 dummy;
 
-       if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info)))
-               return nt_status;
+               sid_copy(&primary_group_sid, &user_sid);
+               sid_split_rid(&primary_group_sid, &dummy);
+               sid_append_rid(&primary_group_sid, DOMAIN_GROUP_RID_USERS);
 
-       (*server_info)->sam_account    = sampass;
+               if (!sid_to_gid(&primary_group_sid, gid)) {
+                       DEBUG(1, ("sid_to_gid(%s) failed\n",
+                                 sid_string_static(&primary_group_sid)));
+                       goto done;
+               }
 
-       if ( !(pwd = getpwnam_alloc(pdb_get_username(sampass))) )  {
-               DEBUG(1, ("User %s in passdb, but getpwnam() fails!\n",
-                         pdb_get_username(sampass)));
-               free_server_info(server_info);
-               return NT_STATUS_NO_SUCH_USER;
-       }
-       (*server_info)->unix_name = smb_xstrdup(pwd->pw_name);
-       (*server_info)->gid = pwd->pw_gid;
-       (*server_info)->uid = pwd->pw_uid;
-       
-       passwd_free(&pwd);
+               num_group_sids = 0;
+               group_sids = NULL;
 
-       if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, pdb_get_username(sampass), 
-                                                        sampass,
-                                                        (*server_info)->uid, 
-                                                        (*server_info)->gid))) 
-       {
-               free_server_info(server_info);
-               return nt_status;
+               *found_username = talloc_strdup(mem_ctx, username);
        }
 
-       (*server_info)->sam_fill_level = SAM_FILL_ALL;
-       DEBUG(5,("make_server_info_sam: made server info for user %s -> %s\n",
-                pdb_get_username(sampass),
-                (*server_info)->unix_name));
+       *token = create_local_nt_token(mem_ctx, &user_sid, &primary_group_sid,
+                                      is_guest, num_group_sids, group_sids);
 
-       return nt_status;
+       if ((*token == NULL) || (*found_username == NULL)) {
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+
+       result = NT_STATUS_OK;
+ done:
+       talloc_free(tmp_ctx);
+       return result;
 }
 
 /***************************************************************************
- Make (and fill) a user_info struct from a Kerberos PAC logon_info by conversion 
- to a SAM_ACCOUNT
+ Make (and fill) a user_info struct from a Kerberos PAC logon_info by
conversion to a SAM_ACCOUNT
 ***************************************************************************/
 
 NTSTATUS make_server_info_pac(auth_serversupplied_info **server_info, 
@@ -913,16 +1030,22 @@ NTSTATUS make_server_info_pac(auth_serversupplied_info **server_info,
                              struct passwd *pwd,
                              PAC_LOGON_INFO *logon_info)
 {
-       NTSTATUS nt_status;
+       NTSTATUS status;
        SAM_ACCOUNT *sampass = NULL;
        DOM_SID user_sid, group_sid;
        fstring dom_name;
+       auth_serversupplied_info *result;
 
-       if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(&sampass, pwd))) {             
-               return nt_status;
+       status = pdb_init_sam_pw(&sampass, pwd);
+
+       if (!NT_STATUS_IS_OK(status)) {         
+               return status;
        }
-       if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info))) {
-               return nt_status;
+
+       result = make_server_info(NULL);
+       if (result == NULL) {
+               pdb_free_sam(&sampass);
+               return NT_STATUS_NO_MEMORY;
        }
 
        /* only copy user_sid, group_sid and domain name out of the PAC for
@@ -941,20 +1064,18 @@ NTSTATUS make_server_info_pac(auth_serversupplied_info **server_info,
 
        pdb_set_logon_count(sampass, logon_info->info3.logon_count, PDB_SET);
 
-       (*server_info)->sam_account    = sampass;
+       result->sam_account = sampass;
+       result->unix_name = talloc_strdup(result, unix_username);
+       result->uid = pwd->pw_uid;
+       result->gid = pwd->pw_gid;
 
-       if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, unix_username,
-               sampass, pwd->pw_uid, pwd->pw_gid))) 
-       {
-               return nt_status;
-       }
+       /* TODO: Add groups from pac */
+       result->sids = NULL;
+       result->num_sids = 0;
 
-       (*server_info)->unix_name = smb_xstrdup(unix_username);
+       *server_info = result;
 
-       (*server_info)->sam_fill_level = SAM_FILL_ALL;
-       (*server_info)->uid = pwd->pw_uid;
-       (*server_info)->gid = pwd->pw_gid;
-       return nt_status;
+       return NT_STATUS_OK;
 }
 
 
@@ -967,93 +1088,172 @@ NTSTATUS make_server_info_pw(auth_serversupplied_info **server_info,
                              char *unix_username,
                             struct passwd *pwd)
 {
-       NTSTATUS nt_status;
+       NTSTATUS status;
        SAM_ACCOUNT *sampass = NULL;
-       if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(&sampass, pwd))) {             
-               return nt_status;
+       gid_t *gids;
+       auth_serversupplied_info *result;
+       
+       status = pdb_init_sam_pw(&sampass, pwd);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
-       if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info))) {
-               return nt_status;
+
+       result = make_server_info(NULL);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               pdb_free_sam(&sampass);
+               return status;
        }
 
-       (*server_info)->sam_account    = sampass;
+       result->sam_account = sampass;
+       result->unix_name = talloc_strdup(result, unix_username);
+       result->uid = pwd->pw_uid;
+       result->gid = pwd->pw_gid;
 
-       if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, unix_username,
-               sampass, pwd->pw_uid, pwd->pw_gid))) 
-       {
-               return nt_status;
+       status = pdb_enum_group_memberships(result, sampass,
+                                           &result->sids, &gids,
+                                           &result->num_sids);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10, ("pdb_enum_group_memberships failed: %s\n",
+                          nt_errstr(status)));
+               talloc_free(result);
+               return status;
        }
 
-       (*server_info)->unix_name = smb_xstrdup(unix_username);
+       /* For now we throw away the gids and convert via sid_to_gid
+        * later. This needs fixing, but I'd like to get the code straight and
+        * simple first. */
+       talloc_free(gids);
 
-       (*server_info)->sam_fill_level = SAM_FILL_ALL;
-       (*server_info)->uid = pwd->pw_uid;
-       (*server_info)->gid = pwd->pw_gid;
-       return nt_status;
+       *server_info = result;
+
+       return NT_STATUS_OK;
 }
 
 /***************************************************************************
  Make (and fill) a user_info struct for a guest login.
+ This *must* succeed for smbd to start. If there is no mapping entry for
+ the guest gid, then create one.
 ***************************************************************************/
 
 static NTSTATUS make_new_server_info_guest(auth_serversupplied_info **server_info)
 {
-       NTSTATUS nt_status;
+       NTSTATUS status;
        SAM_ACCOUNT *sampass = NULL;
        DOM_SID guest_sid;
+       BOOL ret;
+       static const char zeros[16];
 
-       if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam(&sampass))) {
-               return nt_status;
+       status = pdb_init_sam(&sampass);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
        }
 
        sid_copy(&guest_sid, get_global_sam_sid());
        sid_append_rid(&guest_sid, DOMAIN_USER_RID_GUEST);
 
        become_root();
-       if (!pdb_getsampwsid(sampass, &guest_sid)) {
-               unbecome_root();
+       ret = pdb_getsampwsid(sampass, &guest_sid);
+       unbecome_root();
+
+       if (!ret) {
+               pdb_free_sam(&sampass);
                return NT_STATUS_NO_SUCH_USER;
        }
-       unbecome_root();
 
-       nt_status = make_server_info_sam(server_info, sampass);
+       status = make_server_info_sam(server_info, sampass);
 
-       if (NT_STATUS_IS_OK(nt_status)) {
-               static const char zeros[16];
-               (*server_info)->guest = True;
-               
-               /* annoying, but the Guest really does have a session key, 
-                  and it is all zeros! */
-               (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros));
-               (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
+       if (!NT_STATUS_IS_OK(status)) {
+
+               /* If there was no initial group mapping for the nobody user,
+                  create one*/
+
+               if (NT_STATUS_EQUAL(status, NT_STATUS_NO_SUCH_USER)) {
+                       GROUP_MAP map;
+                       struct passwd *pwd = getpwnam_alloc(NULL, pdb_get_username(sampass));
+
+                       if ( pwd == NULL )  {
+                               DEBUG(1, ("No guest user %s!\n",
+                                         pdb_get_username(sampass)));
+                               pdb_free_sam(&sampass);
+                               return NT_STATUS_NO_SUCH_USER;
+                       }
+
+                       map.gid = pwd->pw_gid;
+                       sid_copy(&map.sid, get_global_sam_sid());
+                       sid_append_rid(&map.sid, DOMAIN_GROUP_RID_GUESTS);
+                       map.sid_name_use = SID_NAME_DOM_GRP;
+                       fstrcpy(map.nt_name, "Domain Guests");
+                       map.comment[0] = '\0';
+
+                       if ( !NT_STATUS_IS_OK(pdb_update_group_mapping_entry(&map)) ) {
+                               DEBUG(1, ("Could not update group database for guest user %s\n",
+                                       pdb_get_username(sampass) ));
+                               talloc_free(pwd);
+                               pdb_free_sam(&sampass);
+                               return NT_STATUS_NO_SUCH_USER;
+                       }
+
+                       talloc_free(pwd);
+
+                       /* And try again. */
+                       status = make_server_info_sam(server_info, sampass);
+               }
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       pdb_free_sam(&sampass);
+                       return status;
+               }
        }
+       
+       (*server_info)->guest = True;
 
-       return nt_status;
+       status = create_local_token(*server_info);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(10, ("create_local_token failed: %s\n",
+                          nt_errstr(status)));
+               return status;
+       }
+
+       /* annoying, but the Guest really does have a session key, and it is
+          all zeros! */
+       (*server_info)->user_session_key = data_blob(zeros, sizeof(zeros));
+       (*server_info)->lm_session_key = data_blob(zeros, sizeof(zeros));
+
+       return NT_STATUS_OK;
 }
 
 static auth_serversupplied_info *copy_serverinfo(auth_serversupplied_info *src)
 {
        auth_serversupplied_info *dst;
 
-       if (!NT_STATUS_IS_OK(make_server_info(&dst)))
+       dst = make_server_info(NULL);
+       if (dst == NULL) {
                return NULL;
+       }
 
        dst->guest = src->guest;
        dst->uid = src->uid;
        dst->gid = src->gid;
        dst->n_groups = src->n_groups;
        if (src->n_groups != 0)
-               dst->groups = memdup(src->groups, sizeof(gid_t)*dst->n_groups);
+               dst->groups = talloc_memdup(dst, src->groups,
+                                           sizeof(gid_t)*dst->n_groups);
        else
                dst->groups = NULL;
-       dst->ptok = dup_nt_token(src->ptok);
-       dst->user_session_key = data_blob(src->user_session_key.data,
-                                         src->user_session_key.length);
-       dst->lm_session_key = data_blob(src->lm_session_key.data,
-                                         src->lm_session_key.length);
+       dst->ptok = dup_nt_token(dst, src->ptok);
+       dst->user_session_key = data_blob_talloc(
+               dst, src->user_session_key.data,
+               src->user_session_key.length);
+       dst->lm_session_key = data_blob_talloc(
+               dst, src->lm_session_key.data,
+               src->lm_session_key.length);
        pdb_copy_sam_account(src->sam_account, &dst->sam_account);
        dst->pam_handle = NULL;
-       dst->unix_name = smb_xstrdup(src->unix_name);
+       dst->unix_name = talloc_strdup(dst, src->unix_name);
 
        return dst;
 }
@@ -1103,7 +1303,7 @@ static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx,
 
        map_username( dom_user );
 
-       if ( !(passwd = smb_getpwnam( dom_user, real_username, True )) )
+       if ( !(passwd = smb_getpwnam( NULL, dom_user, real_username, True )) )
                return NT_STATUS_NO_SUCH_USER;
 
        *uid = passwd->pw_uid;
@@ -1121,7 +1321,7 @@ static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx,
                *found_username));
 
        nt_status = pdb_init_sam_pw(sam_account, passwd);
-       passwd_free(&passwd);
+       talloc_free(passwd);
        return nt_status;
 }
 
@@ -1131,7 +1331,8 @@ static NTSTATUS fill_sam_account(TALLOC_CTX *mem_ctx,
  the username if we fallback to the username only.
  ****************************************************************************/
  
-struct passwd *smb_getpwnam( char *domuser, fstring save_username, BOOL create )
+struct passwd *smb_getpwnam( TALLOC_CTX *mem_ctx, char *domuser,
+                            fstring save_username, BOOL create )
 {
        struct passwd *pw = NULL;
        char *p;
@@ -1154,7 +1355,7 @@ struct passwd *smb_getpwnam( char *domuser, fstring save_username, BOOL create )
        if ( p ) {
                fstring strip_username;
 
-               pw = Get_Pwnam_alloc( domuser );
+               pw = Get_Pwnam_alloc( mem_ctx, domuser );
                if ( pw ) {     
                        /* make sure we get the case of the username correct */
                        /* work around 'winbind use default domain = yes' */
@@ -1185,7 +1386,7 @@ struct passwd *smb_getpwnam( char *domuser, fstring save_username, BOOL create )
        
        /* just lookup a plain username */
        
-       pw = Get_Pwnam_alloc(username);
+       pw = Get_Pwnam_alloc(mem_ctx, username);
                
        /* Create local user if requested. */
        
@@ -1195,7 +1396,7 @@ struct passwd *smb_getpwnam( char *domuser, fstring save_username, BOOL create )
                        return NULL;
 
                smb_create_user(NULL, username, NULL);
-               pw = Get_Pwnam_alloc(username);
+               pw = Get_Pwnam_alloc(mem_ctx, username);
        }
        
        /* one last check for a valid passwd struct */
@@ -1231,15 +1432,10 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
        uid_t uid;
        gid_t gid;
 
-       size_t n_lgroupSIDs;
-       DOM_SID *lgroupSIDs   = NULL;
-
-       gid_t *unix_groups = NULL;
-       NT_USER_TOKEN *token;
-
-       DOM_SID *all_group_SIDs;
        size_t i;
 
+       auth_serversupplied_info *result;
+
        /* 
           Here is where we should check the list of
           trusted domains, and verify that the SID 
@@ -1257,12 +1453,14 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
        }
 
        if (!(nt_username = unistr2_tdup(mem_ctx, &(info3->uni_user_name)))) {
-               /* If the server didn't give us one, just use the one we sent them */
+               /* If the server didn't give us one, just use the one we sent
+                * them */
                nt_username = sent_nt_username;
        }
 
        if (!(nt_domain = unistr2_tdup(mem_ctx, &(info3->uni_logon_dom)))) {
-               /* If the server didn't give us one, just use the one we sent them */
+               /* If the server didn't give us one, just use the one we sent
+                * them */
                nt_domain = domain;
        }
        
@@ -1271,21 +1469,25 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
 
           We use the _unmapped_ username here in an attempt to provide
           consistent username mapping behavior between kerberos and NTLM[SSP]
-          authentication in domain mode security.  I.E. Username mapping should
-          be applied to the fully qualified username (e.g. DOMAIN\user) and
-          no just the login name.  Yes this mean swe called map_username()
-          unnecessarily in make_user_info_map() but that is how the current
-          code is designed.  Making the change here is the least disruptive 
-          place.    -- jerry */
+          authentication in domain mode security.  I.E. Username mapping
+          should be applied to the fully qualified username
+          (e.g. DOMAIN\user) and not just the login name.  Yes this means we
+          called map_username() unnecessarily in make_user_info_map() but
+          that is how the current code is designed.  Making the change here
+          is the least disruptive place.  -- jerry */
           
        nt_status = fill_sam_account(mem_ctx, nt_domain, sent_nt_username,
-               &found_username, &uid, &gid, &sam_account);
+                                    &found_username, &uid, &gid,
+                                    &sam_account);
 
        if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER)) {
-               DEBUG(3,("User %s does not exist, trying to add it\n", internal_username));
+               DEBUG(3,("User %s does not exist, trying to add it\n",
+                        internal_username));
                smb_create_user( nt_domain, sent_nt_username, NULL);
-               nt_status = fill_sam_account( mem_ctx, nt_domain, sent_nt_username, 
-                       &found_username, &uid, &gid, &sam_account );
+               nt_status = fill_sam_account( mem_ctx, nt_domain,
+                                             sent_nt_username, 
+                                             &found_username, &uid, &gid,
+                                             &sam_account );
        }
        
        /* if we still don't have a valid unix account check for 
@@ -1326,96 +1528,77 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
                return NT_STATUS_UNSUCCESSFUL;
        }
                
-       if (!pdb_set_fullname(sam_account, unistr2_static(&(info3->uni_full_name)), 
+       if (!pdb_set_fullname(sam_account,
+                             unistr2_static(&(info3->uni_full_name)), 
                              PDB_CHANGED)) {
                pdb_free_sam(&sam_account);
                return NT_STATUS_NO_MEMORY;
        }
 
-       if (!pdb_set_logon_script(sam_account, unistr2_static(&(info3->uni_logon_script)), PDB_CHANGED)) {
+       if (!pdb_set_logon_script(sam_account,
+                                 unistr2_static(&(info3->uni_logon_script)),
+                                 PDB_CHANGED)) {
                pdb_free_sam(&sam_account);
                return NT_STATUS_NO_MEMORY;
        }
 
-       if (!pdb_set_profile_path(sam_account, unistr2_static(&(info3->uni_profile_path)), PDB_CHANGED)) {
+       if (!pdb_set_profile_path(sam_account,
+                                 unistr2_static(&(info3->uni_profile_path)),
+                                 PDB_CHANGED)) {
                pdb_free_sam(&sam_account);
                return NT_STATUS_NO_MEMORY;
        }
 
-       if (!pdb_set_homedir(sam_account, unistr2_static(&(info3->uni_home_dir)), PDB_CHANGED)) {
+       if (!pdb_set_homedir(sam_account,
+                            unistr2_static(&(info3->uni_home_dir)),
+                            PDB_CHANGED)) {
                pdb_free_sam(&sam_account);
                return NT_STATUS_NO_MEMORY;
        }
 
-       if (!pdb_set_dir_drive(sam_account, unistr2_static(&(info3->uni_dir_drive)), PDB_CHANGED)) {
+       if (!pdb_set_dir_drive(sam_account,
+                              unistr2_static(&(info3->uni_dir_drive)),
+                              PDB_CHANGED)) {
                pdb_free_sam(&sam_account);
                return NT_STATUS_NO_MEMORY;
        }
 
-       if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info))) {
+       result = make_server_info(NULL);
+       if (result == NULL) {
                DEBUG(4, ("make_server_info failed!\n"));
                pdb_free_sam(&sam_account);
-               return nt_status;
+               return NT_STATUS_NO_MEMORY;
        }
 
        /* save this here to _net_sam_logon() doesn't fail (it assumes a 
           valid SAM_ACCOUNT) */
                   
-       (*server_info)->sam_account = sam_account;
-
-       (*server_info)->unix_name = smb_xstrdup(found_username);
+       result->sam_account = sam_account;
+       result->unix_name = talloc_strdup(result, found_username);
 
        /* Fill in the unix info we found on the way */
 
-       (*server_info)->sam_fill_level = SAM_FILL_ALL;
-       (*server_info)->uid = uid;
-       (*server_info)->gid = gid;
-
-       /* Store the user group information in the server_info 
-          returned to the caller. */
-       
-       nt_status = get_user_groups((*server_info)->unix_name,
-               uid, gid, &n_lgroupSIDs, &lgroupSIDs, &unix_groups);
-               
-       if ( !NT_STATUS_IS_OK(nt_status) ) {
-               DEBUG(4,("get_user_groups failed\n"));
-               return nt_status;
-       }
+       result->uid = uid;
+       result->gid = gid;
 
-       (*server_info)->groups = unix_groups;
-       (*server_info)->n_groups = n_lgroupSIDs;
-       
        /* Create a 'combined' list of all SIDs we might want in the SD */
-       
-       all_group_SIDs = SMB_MALLOC_ARRAY(DOM_SID,info3->num_groups2 + info3->num_other_sids + n_lgroupSIDs);
-       
-       if (!all_group_SIDs) {
-               DEBUG(0, ("malloc() failed for DOM_SID list!\n"));
-               SAFE_FREE(lgroupSIDs);
-               free_server_info(server_info);
-               return NT_STATUS_NO_MEMORY;
-       }
+
+       result->num_sids = 0;
+       result->sids = NULL;
 
        /* and create (by appending rids) the 'domain' sids */
        
        for (i = 0; i < info3->num_groups2; i++) {
-       
-               sid_copy(&all_group_SIDs[i], &(info3->dom_sid.sid));
-               
-               if (!sid_append_rid(&all_group_SIDs[i], info3->gids[i].g_rid)) {
-               
-                       nt_status = NT_STATUS_INVALID_PARAMETER;
-                       
-                       DEBUG(3,("could not append additional group rid 0x%x\n",
-                               info3->gids[i].g_rid));                 
-                               
-                       SAFE_FREE(lgroupSIDs);
-                       SAFE_FREE(all_group_SIDs);
-                       free_server_info(server_info);
-                       
-                       return nt_status;
-                       
+               DOM_SID sid;
+               if (!sid_compose(&sid, &info3->dom_sid.sid,
+                                info3->gids[i].g_rid)) {
+                       DEBUG(3,("could not append additional group rid "
+                                "0x%x\n", info3->gids[i].g_rid));
+                       talloc_free(result);
+                       return NT_STATUS_INVALID_PARAMETER;
                }
+               add_sid_to_array(result, &sid, &result->sids,
+                                &result->num_sids);
        }
 
        /* Copy 'other' sids.  We need to do sid filtering here to
@@ -1425,56 +1608,33 @@ NTSTATUS make_server_info_info3(TALLOC_CTX *mem_ctx,
          */
 
        for (i = 0; i < info3->num_other_sids; i++) {
-               sid_copy(&all_group_SIDs[info3->num_groups2 + i],
-                        &info3->other_sids[i].sid);
-       }
-
-
-       /* add local alias sids */ 
-
-       for (i = 0; i < n_lgroupSIDs; i++) {
-               sid_copy(&all_group_SIDs[info3->num_groups2 +
-                                        info3->num_other_sids + i],
-                        &lgroupSIDs[i]);
-       }
-       
-       /* Where are the 'global' sids... */
-
-       /* can the user be guest? if yes, where is it stored? */
-       
-       nt_status = create_nt_user_token(&user_sid, &group_sid,
-               info3->num_groups2 + info3->num_other_sids + n_lgroupSIDs,
-               all_group_SIDs, False, &token);
-               
-       if ( !NT_STATUS_IS_OK(nt_status) ) {
-               DEBUG(4,("create_nt_user_token failed\n"));
-               SAFE_FREE(lgroupSIDs);
-               SAFE_FREE(all_group_SIDs);
-               free_server_info(server_info);
-               return nt_status;
+               add_sid_to_array(result, &info3->other_sids[i].sid,
+                                &result->sids,
+                                &result->num_sids);
        }
 
-       (*server_info)->login_server = unistr2_tdup(mem_ctx, 
-                                                   &(info3->uni_logon_srv));
-
-       (*server_info)->ptok = token; 
-
-       SAFE_FREE(lgroupSIDs);
-       SAFE_FREE(all_group_SIDs);
+       result->login_server = unistr2_tdup(result, 
+                                           &(info3->uni_logon_srv));
 
        /* ensure we are never given NULL session keys */
        
        if (memcmp(info3->user_sess_key, zeros, sizeof(zeros)) == 0) {
-               (*server_info)->user_session_key = data_blob(NULL, 0);
+               result->user_session_key = data_blob(NULL, 0);
        } else {
-               (*server_info)->user_session_key = data_blob(info3->user_sess_key, sizeof(info3->user_sess_key));
+               result->user_session_key = data_blob_talloc(
+                       result, info3->user_sess_key,
+                       sizeof(info3->user_sess_key));
        }
 
        if (memcmp(info3->lm_sess_key, zeros, 8) == 0) {
-               (*server_info)->lm_session_key = data_blob(NULL, 0);
+               result->lm_session_key = data_blob(NULL, 0);
        } else {
-               (*server_info)->lm_session_key = data_blob(info3->lm_sess_key, sizeof(info3->lm_sess_key));
-       } 
+               result->lm_session_key = data_blob_talloc(
+                       result, info3->lm_sess_key,
+                       sizeof(info3->lm_sess_key));
+       }
+
+       *server_info = result;
 
        return NT_STATUS_OK;
 }
@@ -1487,14 +1647,15 @@ void free_user_info(auth_usersupplied_info **user_info)
 {
        DEBUG(5,("attempting to free (and zero) a user_info structure\n"));
        if (*user_info != NULL) {
-               if ((*user_info)->smb_name.str) {
-                       DEBUG(10,("structure was created for %s\n", (*user_info)->smb_name.str));
+               if ((*user_info)->smb_name) {
+                       DEBUG(10,("structure was created for %s\n",
+                                 (*user_info)->smb_name));
                }
-               SAFE_FREE((*user_info)->smb_name.str);
-               SAFE_FREE((*user_info)->internal_username.str);
-               SAFE_FREE((*user_info)->client_domain.str);
-               SAFE_FREE((*user_info)->domain.str);
-               SAFE_FREE((*user_info)->wksta_name.str);
+               SAFE_FREE((*user_info)->smb_name);
+               SAFE_FREE((*user_info)->internal_username);
+               SAFE_FREE((*user_info)->client_domain);
+               SAFE_FREE((*user_info)->domain);
+               SAFE_FREE((*user_info)->wksta_name);
                data_blob_free(&(*user_info)->lm_resp);
                data_blob_free(&(*user_info)->nt_resp);
                data_blob_clear_free(&(*user_info)->lm_interactive_pwd);
@@ -1505,27 +1666,6 @@ void free_user_info(auth_usersupplied_info **user_info)
        SAFE_FREE(*user_info);
 }
 
-/***************************************************************************
- Clear out a server_info struct that has been allocated
-***************************************************************************/
-
-void free_server_info(auth_serversupplied_info **server_info)
-{
-       DEBUG(5,("attempting to free (and zero) a server_info structure\n"));
-       if (*server_info != NULL) {
-               pdb_free_sam(&(*server_info)->sam_account);
-
-               /* call pam_end here, unless we know we are keeping it */
-               delete_nt_token( &(*server_info)->ptok );
-               SAFE_FREE((*server_info)->groups);
-               SAFE_FREE((*server_info)->unix_name);
-               data_blob_free(&(*server_info)->lm_session_key);
-               data_blob_free(&(*server_info)->user_session_key);
-               ZERO_STRUCT(**server_info);
-       }
-       SAFE_FREE(*server_info);
-}
-
 /***************************************************************************
  Make an auth_methods struct
 ***************************************************************************/
@@ -1533,11 +1673,13 @@ void free_server_info(auth_serversupplied_info **server_info)
 BOOL make_auth_methods(struct auth_context *auth_context, auth_methods **auth_method) 
 {
        if (!auth_context) {
-               smb_panic("no auth_context supplied to make_auth_methods()!\n");
+               smb_panic("no auth_context supplied to "
+                         "make_auth_methods()!\n");
        }
 
        if (!auth_method) {
-               smb_panic("make_auth_methods: pointer to auth_method pointer is NULL!\n");
+               smb_panic("make_auth_methods: pointer to auth_method pointer "
+                         "is NULL!\n");
        }
 
        *auth_method = TALLOC_P(auth_context->mem_ctx, auth_methods);
@@ -1550,41 +1692,29 @@ BOOL make_auth_methods(struct auth_context *auth_context, auth_methods **auth_me
        return True;
 }
 
-/****************************************************************************
- Delete a SID token.
-****************************************************************************/
-
-void delete_nt_token(NT_USER_TOKEN **pptoken)
-{
-       if (*pptoken) {
-               NT_USER_TOKEN *ptoken = *pptoken;
-
-               SAFE_FREE( ptoken->user_sids );
-               ZERO_STRUCTP(ptoken);
-       }
-       SAFE_FREE(*pptoken);
-}
-
 /****************************************************************************
  Duplicate a SID token.
 ****************************************************************************/
 
-NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken)
+NT_USER_TOKEN *dup_nt_token(TALLOC_CTX *mem_ctx, NT_USER_TOKEN *ptoken)
 {
        NT_USER_TOKEN *token;
 
        if (!ptoken)
                return NULL;
 
-       if ((token = SMB_MALLOC_P(NT_USER_TOKEN)) == NULL)
+       token = TALLOC_P(mem_ctx, NT_USER_TOKEN);
+       if (token == NULL) {
+               DEBUG(0, ("talloc failed\n"));
                return NULL;
+       }
 
-       ZERO_STRUCTP(token);
-       
-       token->user_sids = (DOM_SID *)memdup( ptoken->user_sids, sizeof(DOM_SID) * ptoken->num_sids );
-       
-       if ( !token ) {
-               SAFE_FREE(token);
+       token->user_sids = talloc_memdup(token, ptoken->user_sids,
+                                        sizeof(DOM_SID) * ptoken->num_sids );
+
+       if ((ptoken->user_sids != NULL) && (token->user_sids == NULL)) {
+               DEBUG(0, ("talloc_memdup failed\n"));
+               talloc_free(token);
                return NULL;
        }
 
@@ -1593,7 +1723,8 @@ NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken)
        /* copy the privileges; don't consider failure to be critical here */
        
        if ( !se_priv_copy( &token->privileges, &ptoken->privileges ) ) {
-               DEBUG(0,("dup_nt_token: Failure to copy SE_PRIV!.  Continuing with 0 privileges assigned.\n"));
+               DEBUG(0,("dup_nt_token: Failure to copy SE_PRIV!.  "
+                        "Continuing with 0 privileges assigned.\n"));
        }
 
        return token;
@@ -1603,7 +1734,7 @@ NT_USER_TOKEN *dup_nt_token(NT_USER_TOKEN *ptoken)
  Check for a SID in an NT_USER_TOKEN
 ****************************************************************************/
 
-static BOOL nt_token_check_sid ( DOM_SID *sid, NT_USER_TOKEN *token )
+BOOL nt_token_check_sid ( const DOM_SID *sid, const NT_USER_TOKEN *token )
 {
        int i;
        
@@ -1626,9 +1757,10 @@ BOOL nt_token_check_domain_rid( NT_USER_TOKEN *token, uint32 rid )
           a DC or standalone server, use our own SID */
 
        if ( lp_server_role() == ROLE_DOMAIN_MEMBER ) {
-               if ( !secrets_fetch_domain_sid( lp_workgroup(), &domain_sid ) ) {
-                       DEBUG(1,("nt_token_check_domain_rid: Cannot lookup SID for domain [%s]\n",
-                               lp_workgroup()));
+               if ( !secrets_fetch_domain_sid( lp_workgroup(),
+                                               &domain_sid ) ) {
+                       DEBUG(1,("nt_token_check_domain_rid: Cannot lookup "
+                                "SID for domain [%s]\n", lp_workgroup()));
                        return False;
                }
        } 
@@ -1662,9 +1794,10 @@ BOOL is_trusted_domain(const char* dom_name)
 
        if ( IS_DC ) {
                become_root();
-               DEBUG (5,("is_trusted_domain: Checking for domain trust with [%s]\n",
-                       dom_name ));
-               ret = secrets_fetch_trusted_domain_password(dom_name, NULL, NULL, NULL);
+               DEBUG (5,("is_trusted_domain: Checking for domain trust with "
+                         "[%s]\n", dom_name ));
+               ret = secrets_fetch_trusted_domain_password(dom_name, NULL,
+                                                           NULL, NULL);
                unbecome_root();
                if (ret)
                        return True;
index ad72bd9a1fd561c4ba8c00de255c2a73d68bcb78..6e2f26a57222d8b81c3e9cb810221bc9f0ba0317 100644 (file)
@@ -71,13 +71,13 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
 
        if (!auth_context) {
                DEBUG(3,("Password for user %s cannot be checked because we have no auth_info to get the challenge from.\n", 
-                        user_info->internal_username.str));            
+                        user_info->internal_username));
                return NT_STATUS_INVALID_PARAMETER;
        }               
 
-       if (strequal(user_info->domain.str, get_global_sam_name())) {
+       if (strequal(user_info->domain, get_global_sam_name())) {
                DEBUG(3,("check_winbind_security: Not using winbind, requested domain [%s] was for this SAM.\n",
-                       user_info->domain.str));
+                       user_info->domain));
                return NT_STATUS_NOT_IMPLEMENTED;
        }
 
@@ -90,12 +90,9 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
 
        request.data.auth_crap.logon_parameters = user_info->logon_parameters;
 
-       fstrcpy(request.data.auth_crap.user, 
-                         user_info->smb_name.str);
-       fstrcpy(request.data.auth_crap.domain, 
-                         user_info->domain.str);
-       fstrcpy(request.data.auth_crap.workstation, 
-                         user_info->wksta_name.str);
+       fstrcpy(request.data.auth_crap.user, user_info->smb_name);
+       fstrcpy(request.data.auth_crap.domain, user_info->domain);
+       fstrcpy(request.data.auth_crap.workstation, user_info->wksta_name);
 
        memcpy(request.data.auth_crap.chal, auth_context->challenge.data, sizeof(request.data.auth_crap.chal));
        
@@ -131,8 +128,8 @@ static NTSTATUS check_winbind_security(const struct auth_context *auth_context,
                if (NT_STATUS_IS_OK(nt_status)) {
                        if (NT_STATUS_IS_OK(nt_status = get_info3_from_ndr(mem_ctx, &response, &info3))) { 
                                nt_status = make_server_info_info3(mem_ctx, 
-                                       user_info->internal_username.str
-                                       user_info->smb_name.str, user_info->domain.str
+                                       user_info->internal_username, 
+                                       user_info->smb_name, user_info->domain
                                        server_info, &info3); 
                        }
                        
index 7079bf7437a7ce13a9036a21dff99d5abb0568c0..e901e065d27cbc838308cf69c2be54d829fdcf93 100644 (file)
@@ -462,7 +462,7 @@ DYNEXP=
 
 dnl Add modules that have to be built by default here
 dnl These have to be built static:
-default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_svcctl rpc_ntsvcs rpc_net rpc_dfs rpc_srv rpc_spoolss rpc_eventlog auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin"
+default_static_modules="pdb_smbpasswd pdb_tdbsam rpc_lsa rpc_samr rpc_reg rpc_lsa_ds rpc_wks rpc_svcctl rpc_ntsvcs rpc_net rpc_netdfs rpc_srv rpc_spoolss rpc_eventlog auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin"
 
 dnl These are preferably build shared, and static if dlopen() is not available
 default_shared_modules="vfs_recycle vfs_audit vfs_extd_audit vfs_full_audit vfs_netatalk vfs_fake_perms vfs_default_quota vfs_readonly vfs_cap vfs_expand_msdfs vfs_shadow_copy charset_CP850 charset_CP437 auth_script"
@@ -2871,6 +2871,8 @@ if test x"$with_ldap_support" != x"no"; then
   
   AC_DEFINE_UNQUOTED(LDAP_SET_REBIND_PROC_ARGS, $smb_ldap_cv_ldap_set_rebind_proc, [Number of arguments to ldap_set_rebind_proc])
 
+  AC_CHECK_FUNC_EXT(ldap_dn2ad_canonical,$LDAP_LIBS)   
+  
   if test x"$ac_cv_lib_ext_ldap_ldap_init" = x"yes"; then
     AC_DEFINE(HAVE_LDAP,1,[Whether ldap is available])
     CPPFLAGS="$CPPFLAGS -DLDAP_DEPRECATED"
@@ -3144,6 +3146,9 @@ if test x"$with_ads_support" != x"no"; then
   AC_CHECK_FUNC_EXT(krb5_principal_compare_any_realm, $KRB5_LIBS)
   AC_CHECK_FUNC_EXT(krb5_parse_name_norealm, $KRB5_LIBS)
   AC_CHECK_FUNC_EXT(krb5_princ_size, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_get_init_creds_opt_set_pac_request, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_get_renewed_creds, $KRB5_LIBS)
+  AC_CHECK_FUNC_EXT(krb5_get_kdc_cred, $KRB5_LIBS)
 
   LIBS="$KRB5_LIBS $LIBS"
 
@@ -3445,6 +3450,29 @@ if test x"$with_ads_support" != x"no"; then
 LIBS="$ac_save_LIBS"
 fi
 
+#################################################
+# check for KCM support
+
+with_kcm_support=no
+AC_MSG_CHECKING([for KCM support])
+
+AC_ARG_WITH(kcm,
+[  --with-kcm              KCM support (default no)],
+[ case "$withval" in
+    yes)
+       if test x$FOUND_KRB5 = x"no"; then
+               AC_MSG_ERROR(libkrb5 is needed for KCM support)
+       fi
+       with_kcm_support="$withval"
+       AC_DEFINE(WITH_KCM,1,[Whether to include KCM support])
+       ;;
+    *)
+       with_kcm_support="no"
+       AC_DEFINE(WITH_KCM,0,[Whether to include KCM support])
+       ;;
+  esac ])
+
+AC_MSG_RESULT($with_kcm_support)
 ########################################################
 # Compile experimental passdb backends?
 # (pdb_xml, pdb_mysql, pdb_pgsql)
@@ -5177,7 +5205,7 @@ SMB_MODULE(rpc_wks, \$(RPC_WKS_OBJ), "bin/librpc_wkssvc.$SHLIBEXT", RPC)
 SMB_MODULE(rpc_svcctl, \$(RPC_SVCCTL_OBJ), "bin/librpc_svcctl.$SHLIBEXT", RPC)
 SMB_MODULE(rpc_ntsvcs, \$(RPC_NTSVCS_OBJ), "bin/librpc_ntsvcs.$SHLIBEXT", RPC)
 SMB_MODULE(rpc_net, \$(RPC_NETLOG_OBJ), "bin/librpc_NETLOGON.$SHLIBEXT", RPC)
-SMB_MODULE(rpc_dfs, \$(RPC_DFS_OBJ), "bin/librpc_netdfs.$SHLIBEXT", RPC)
+SMB_MODULE(rpc_netdfs, \$(RPC_DFS_OBJ), "bin/librpc_netdfs.$SHLIBEXT", RPC)
 SMB_MODULE(rpc_srv, \$(RPC_SVC_OBJ), "bin/librpc_srvsvc.$SHLIBEXT", RPC)
 SMB_MODULE(rpc_spoolss, \$(RPC_SPOOLSS_OBJ), "bin/librpc_spoolss.$SHLIBEXT", RPC)
 SMB_MODULE(rpc_eventlog, \$(RPC_EVENTLOG_OBJ), "bin/librpc_eventlog.$SHLIBEXT", RPC)
index 7dc0426c4493849e0295cc8cc308936de2e25044..2790d4758770964df2f652bbbd2df205502a6b05 100644 (file)
@@ -176,7 +176,65 @@ BOOL add_initial_entry(gid_t gid, const char *sid, enum SID_NAME_USE sid_name_us
        fstrcpy(map.nt_name, nt_name);
        fstrcpy(map.comment, comment);
 
-       return pdb_add_group_mapping_entry(&map);
+       return NT_STATUS_IS_OK(pdb_add_group_mapping_entry(&map));
+}
+
+/****************************************************************************
+ Map a unix group to a newly created mapping
+****************************************************************************/
+NTSTATUS map_unix_group(const struct group *grp, GROUP_MAP *pmap)
+{
+       NTSTATUS status;
+       GROUP_MAP map;
+       const char *grpname, *dom, *name;
+       uint32 rid;
+
+       if (pdb_getgrgid(&map, grp->gr_gid)) {
+               return NT_STATUS_GROUP_EXISTS;
+       }
+
+       map.gid = grp->gr_gid;
+       grpname = grp->gr_name;
+
+       if (lookup_name(tmp_talloc_ctx(), grpname, LOOKUP_NAME_ISOLATED,
+                       &dom, &name, NULL, NULL)) {
+
+               const char *tmp = talloc_asprintf(
+                       tmp_talloc_ctx(), "Unix Group %s", grp->gr_name);
+
+               DEBUG(5, ("%s exists as %s\\%s, retrying as \"%s\"\n",
+                         grpname, dom, name, tmp));
+               grpname = tmp;
+       }
+
+       if (lookup_name(tmp_talloc_ctx(), grpname, LOOKUP_NAME_ISOLATED,
+                       NULL, NULL, NULL, NULL)) {
+               DEBUG(3, ("\"%s\" exists, can't map it\n", grp->gr_name));
+               return NT_STATUS_GROUP_EXISTS;
+       }
+
+       fstrcpy(map.nt_name, grpname);
+
+       if (pdb_rid_algorithm()) {
+               rid = pdb_gid_to_group_rid( grp->gr_gid );
+       } else {
+               if (!pdb_new_rid(&rid)) {
+                       DEBUG(3, ("Could not get a new RID for %s\n",
+                                 grp->gr_name));
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+       }
+
+       sid_compose(&map.sid, get_global_sam_sid(), rid);
+       map.sid_name_use = SID_NAME_DOM_GRP;
+       fstrcpy(map.comment, talloc_asprintf(tmp_talloc_ctx(), "Unix Group %s",
+                                            grp->gr_name));
+
+       status = pdb_add_group_mapping_entry(&map);
+       if (NT_STATUS_IS_OK(status)) {
+               *pmap = map;
+       }
+       return status;
 }
 
 /****************************************************************************
@@ -794,99 +852,6 @@ BOOL get_domain_group_from_sid(DOM_SID sid, GROUP_MAP *map)
        return True;
 }
 
-
-/* get a local (alias) group from it's SID */
-
-BOOL get_local_group_from_sid(DOM_SID *sid, GROUP_MAP *map)
-{
-       BOOL ret;
-       
-       if(!init_group_mapping()) {
-               DEBUG(0,("failed to initialize group mapping\n"));
-               return(False);
-       }
-
-       /* The group is in the mapping table */
-       become_root();
-       ret = pdb_getgrsid(map, *sid);
-       unbecome_root();
-       
-       if ( !ret )
-               return False;
-               
-       if ( ( (map->sid_name_use != SID_NAME_ALIAS) &&
-              (map->sid_name_use != SID_NAME_WKN_GRP) )
-               || (map->gid == -1)
-               || (getgrgid(map->gid) == NULL) ) 
-       {
-               return False;
-       }               
-                       
-#if 1  /* JERRY */
-       /* local groups only exist in the group mapping DB so this 
-          is not necessary */
-          
-       else {
-               /* the group isn't in the mapping table.
-                * make one based on the unix information */
-               uint32 alias_rid;
-               struct group *grp;
-
-               sid_peek_rid(sid, &alias_rid);
-               map->gid=pdb_group_rid_to_gid(alias_rid);
-               
-               grp = getgrgid(map->gid);
-               if ( !grp ) {
-                       DEBUG(3,("get_local_group_from_sid: No unix group for [%ul]\n", map->gid));
-                       return False;
-               }
-
-               map->sid_name_use=SID_NAME_ALIAS;
-
-               fstrcpy(map->nt_name, grp->gr_name);
-               fstrcpy(map->comment, "Local Unix Group");
-
-               sid_copy(&map->sid, sid);
-       }
-#endif
-
-       return True;
-}
-
-/* get a builtin group from it's SID */
-
-BOOL get_builtin_group_from_sid(DOM_SID *sid, GROUP_MAP *map)
-{
-       BOOL ret;
-       
-
-       if(!init_group_mapping()) {
-               DEBUG(0,("failed to initialize group mapping\n"));
-               return(False);
-       }
-
-       become_root();
-       ret = pdb_getgrsid(map, *sid);
-       unbecome_root();
-       
-       if ( !ret )
-               return False;
-
-       if (map->sid_name_use!=SID_NAME_WKN_GRP) {
-               return False;
-       }
-
-       if (map->gid==-1) {
-               return False;
-       }
-
-       if ( getgrgid(map->gid) == NULL) {
-               return False;
-       }
-
-       return True;
-}
-
 /****************************************************************************
  Create a UNIX group on demand.
 ****************************************************************************/
@@ -1101,9 +1066,12 @@ NTSTATUS pdb_default_create_alias(struct pdb_methods *methods,
        gid_t gid;
        BOOL exists;
        GROUP_MAP map;
+       TALLOC_CTX *mem_ctx;
+       NTSTATUS status;
 
-       TALLOC_CTX *mem_ctx = talloc_new(NULL);
+       DEBUG(10, ("Trying to create alias %s\n", name));
 
+       mem_ctx = talloc_new(NULL);
        if (mem_ctx == NULL) {
                return NT_STATUS_NO_MEMORY;
        }
@@ -1116,8 +1084,18 @@ NTSTATUS pdb_default_create_alias(struct pdb_methods *methods,
                return NT_STATUS_ALIAS_EXISTS;
        }
 
-       if (!winbind_allocate_rid_and_gid(&new_rid, &gid))
+       if (!winbind_allocate_gid(&gid)) {
+               DEBUG(3, ("Could not get a gid out of winbind\n"));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       if (!pdb_new_rid(&new_rid)) {
+               DEBUG(0, ("Could not allocate a RID -- wasted a gid :-(\n"));
                return NT_STATUS_ACCESS_DENIED;
+       }
+
+       DEBUG(10, ("Creating alias %s with gid %d and rid %d\n",
+                  name, gid, new_rid));
 
        sid_copy(&sid, get_global_sam_sid());
        sid_append_rid(&sid, new_rid);
@@ -1128,10 +1106,12 @@ NTSTATUS pdb_default_create_alias(struct pdb_methods *methods,
        fstrcpy(map.nt_name, name);
        fstrcpy(map.comment, "");
 
-       if (!pdb_add_group_mapping_entry(&map)) {
-               DEBUG(0, ("Could not add group mapping entry for alias %s\n",
-                         name));
-               return NT_STATUS_ACCESS_DENIED;
+       status = pdb_add_group_mapping_entry(&map);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(0, ("Could not add group mapping entry for alias %s "
+                         "(%s)\n", name, nt_errstr(status)));
+               return status;
        }
 
        *rid = new_rid;
@@ -1155,6 +1135,14 @@ NTSTATUS pdb_default_get_aliasinfo(struct pdb_methods *methods,
        if (!pdb_getgrsid(&map, *sid))
                return NT_STATUS_NO_SUCH_ALIAS;
 
+       if ((map.sid_name_use != SID_NAME_ALIAS) &&
+           (map.sid_name_use != SID_NAME_WKN_GRP)) {
+               DEBUG(2, ("%s is a %s, expected an alias\n",
+                         sid_string_static(sid),
+                         sid_type_lookup(map.sid_name_use)));
+               return NT_STATUS_NO_SUCH_ALIAS;
+       }
+
        fstrcpy(info->acct_name, map.nt_name);
        fstrcpy(info->acct_desc, map.comment);
        sid_peek_rid(&map.sid, &info->rid);
@@ -1172,10 +1160,7 @@ NTSTATUS pdb_default_set_aliasinfo(struct pdb_methods *methods,
 
        fstrcpy(map.comment, info->acct_desc);
 
-       if (!pdb_update_group_mapping_entry(&map))
-               return NT_STATUS_ACCESS_DENIED;
-
-       return NT_STATUS_OK;
+       return pdb_update_group_mapping_entry(&map);
 }
 
 NTSTATUS pdb_default_add_aliasmem(struct pdb_methods *methods,
@@ -1315,7 +1300,7 @@ BOOL pdb_set_dom_grp_info(const DOM_SID *sid, const struct acct_info *info)
        fstrcpy(map.nt_name, info->acct_name);
        fstrcpy(map.comment, info->acct_desc);
 
-       return pdb_update_group_mapping_entry(&map);
+       return NT_STATUS_IS_OK(pdb_update_group_mapping_entry(&map));
 }
 
 
index decb823ea99a56f4c3f9911a2aa01dfcda742330..ce643666ad9655a5d49b26af95399a2af0b2d192 100644 (file)
@@ -30,6 +30,7 @@ typedef struct {
                unsigned flags;
                int time_offset;
                time_t expire;
+               time_t renewable;
        } auth;
 
        /* info derived from the servers config */
@@ -91,6 +92,7 @@ typedef void **ADS_MODLIST;
 #define ADS_NO_REFERRALS_OID   "1.2.840.113556.1.4.1339"
 #define ADS_SERVER_SORT_OID    "1.2.840.113556.1.4.473"
 #define ADS_PERMIT_MODIFY_OID  "1.2.840.113556.1.4.1413"
+#define ADS_ASQ_OID            "1.2.840.113556.1.4.1504"
 
 /* ldap attribute oids (Services for Unix) */
 #define ADS_ATTR_SFU_UIDNUMBER_OID     "1.2.840.113556.1.6.18.1.310"
index 03206c03c6a894822936f2fa5f7a177e9b814f7b..79fbb93895fb2bd3278876d1503df8e8c8b62d8d 100644 (file)
    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 
-/* AUTH_STR - string */
-typedef struct normal_string {
-       int len;
-       char *str;
-} AUTH_STR;
-
 typedef struct auth_usersupplied_info {
        DATA_BLOB lm_resp;
        DATA_BLOB nt_resp;
@@ -35,25 +29,24 @@ typedef struct auth_usersupplied_info {
        
        BOOL encrypted;
        
-       AUTH_STR           client_domain;          /* domain name string */
-       AUTH_STR           domain;               /* domain name after mapping */
-       AUTH_STR           internal_username;    /* username after mapping */
-       AUTH_STR           smb_name;        /* username before mapping */
-       AUTH_STR           wksta_name;           /* workstation name (netbios calling name) unicode string */
+       char *client_domain;          /* domain name string */
+       char *domain;                 /* domain name after mapping */
+       char *internal_username;      /* username after mapping */
+       char *smb_name;               /* username before mapping */
+       char *wksta_name;             /* workstation name (netbios calling
+                                      * name) unicode string */
        
        uint32 logon_parameters;
 
 } auth_usersupplied_info;
 
-#define SAM_FILL_NAME  0x01
-#define SAM_FILL_INFO3 0x02
-#define SAM_FILL_SAM   0x04
-#define SAM_FILL_UNIX  0x08
-#define SAM_FILL_ALL (SAM_FILL_NAME | SAM_FILL_INFO3 | SAM_FILL_SAM | SAM_FILL_UNIX)
-
 typedef struct auth_serversupplied_info {
        BOOL guest;
 
+       DOM_SID *sids;  /* These SIDs are preliminary between
+                          check_ntlm_password and the token creation. */
+       size_t num_sids;
+
        uid_t uid;
        gid_t gid;
        
@@ -70,8 +63,6 @@ typedef struct auth_serversupplied_info {
 
         char *login_server; /* which server authorized the login? */
        
-       uint32 sam_fill_level;  /* How far is this structure filled? */
-       
        SAM_ACCOUNT *sam_account;
        
        void *pam_handle;
index 62c1e4fa22d47611796c983af5bbe66763d8762d..8f8ea06696461e89f6bcc6b3fd32a66d92acbcb5 100644 (file)
 #define WERR_SERVICE_NEVER_STARTED W_ERROR(1077)
 #define WERR_MACHINE_LOCKED W_ERROR(1271)
 #define WERR_INVALID_SECURITY_DESCRIPTOR W_ERROR(1338)
+#define WERR_TIME_SKEW W_ERROR(1398)
 #define WERR_EVENTLOG_FILE_CORRUPT W_ERROR(1500)
 #define WERR_SERVER_UNAVAILABLE W_ERROR(1722)
 #define WERR_INVALID_FORM_NAME W_ERROR(1902)
diff --git a/source3/include/event.h b/source3/include/event.h
new file mode 100644 (file)
index 0000000..fdb9906
--- /dev/null
@@ -0,0 +1,31 @@
+/*
+   Unix SMB/CIFS implementation.
+   event handling
+   Copyright (C) Andrew Tridgell 1992-1998
+   Copyright (C) Volker Lendecke 2005
+
+   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.
+*/
+
+struct timed_event {
+       struct timed_event *next, *prev;
+       struct timeval when;
+       const char *event_name;
+       void (*handler)(struct timed_event *te,
+                       const struct timeval *now,
+                       void *private_data);
+       void *private_data;
+};
+
diff --git a/source3/include/gpo.h b/source3/include/gpo.h
new file mode 100644 (file)
index 0000000..65c96c3
--- /dev/null
@@ -0,0 +1,91 @@
+/* 
+ *  Unix SMB/CIFS implementation.
+ *  Group Policy Object Support
+ *  Copyright (C) Guenther Deschner 2005
+ *  
+ *  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.
+ */
+
+
+enum GPO_LINK_TYPE {
+       GP_LINK_UNKOWN,
+       GP_LINK_MACHINE,
+       GP_LINK_SITE,
+       GP_LINK_DOMAIN,
+       GP_LINK_OU
+};
+
+/* GPO_OPTIONS */
+#define GPO_FLAG_DISABLE       0x00000001
+#define GPO_FLAG_FORCE         0x00000002
+
+/* GPO_LIST_FLAGS */
+#define GPO_LIST_FLAG_MACHINE  0x00000001
+#define GPO_LIST_FLAG_SITEONLY 0x00000002
+
+struct GROUP_POLICY_OBJECT {
+       uint32 options; /* GPFLAGS_* */ 
+       uint32 version;
+       uint16 version_user;
+       uint16 version_machine;
+       const char *ds_path;
+       const char *file_sys_path;
+       const char *display_name;
+       const char *name;
+       const char *link;
+       uint32 link_type; /* GPO_LINK_TYPE */
+       const char *user_extensions;
+       const char *machine_extensions;
+       struct GROUP_POLICY_OBJECT *next, *prev;
+};
+
+/* the following is seen on the DS (see adssearch.pl for details) */
+
+/* the type field in a 'gPLink', the same as GPO_FLAG ? */
+#define GPO_LINK_OPT_NONE      0x00000000
+#define GPO_LINK_OPT_DISABLED  0x00000001
+#define GPO_LINK_OPT_ENFORCED  0x00000002
+
+/* GPO_LINK_OPT_ENFORCED takes precedence over GPOPTIONS_BLOCK_INHERITANCE */
+
+/* 'gPOptions', maybe a bitmask as well */
+enum GPO_INHERIT {
+       GPOPTIONS_INHERIT,
+       GPOPTIONS_BLOCK_INHERITANCE
+};
+
+/* 'flags' in a 'groupPolicyContainer' object */
+#define GPFLAGS_ALL_ENABLED                    0x00000000
+#define GPFLAGS_USER_SETTINGS_DISABLED         0x00000001
+#define GPFLAGS_MACHINE_SETTINGS_DISABLED      0x00000002
+#define GPFLAGS_ALL_DISABLED (GPFLAGS_USER_SETTINGS_DISABLED | \
+                             GPFLAGS_MACHINE_SETTINGS_DISABLED)
+
+struct GP_LINK {
+       const char *gp_link;    /* raw link name */
+       uint32 gp_opts;         /* inheritance options GPO_INHERIT */
+       uint32 num_links;       /* number of links */
+       char **link_names;      /* array of parsed link names */
+       uint32 *link_opts;      /* array of parsed link opts GPO_LINK_OPT_* */
+};
+
+struct GP_EXT {
+       const char *gp_extension;       /* raw extension name */
+       uint32 num_exts;
+       char **extensions;
+       char **extensions_guid;
+       char **snapins;
+       char **snapins_guid;
+};
index c81b94a718a0cc382b03e77565e0cdb381add8b4..474982f2926eacfa88cbdf0050d13596d54863c4 100644 (file)
@@ -24,6 +24,9 @@
    Boston, MA  02111-1307, USA.   
 */
 
+/* idmap version determines auto-conversion */
+#define IDMAP_VERSION 2
+
 #define SMB_IDMAP_INTERFACE_VERSION    2
 
 
@@ -43,7 +46,6 @@ struct idmap_methods {
        /* Called when backend is first loaded */
        NTSTATUS (*init)( char *params );
 
-       NTSTATUS (*allocate_rid)(uint32 *rid, int rid_type);
        NTSTATUS (*allocate_id)(unid_t *id, int id_type);
        NTSTATUS (*get_sid_from_id)(DOM_SID *sid, unid_t id, int id_type);
        NTSTATUS (*get_id_from_sid)(unid_t *id, int *id_type, const DOM_SID *sid);
index a9b792d5f67b8f25577b0b7582f1983c0cd03575..8aa100324084c9cc78f2b77e548e674cb924e672 100644 (file)
@@ -989,6 +989,8 @@ extern int errno;
 
 #include "rpc_client.h"
 
+#include "event.h"
+
 /*
  * Type for wide character dirent structure.
  * Only d_name is defined by POSIX.
@@ -1018,6 +1020,11 @@ struct functable {
        int (*fn)(int argc, const char **argv);
 };
 
+struct functable2 {
+       const char *funcname;
+       int (*fn)(int argc, const char **argv);
+       const char *helptext;
+};
 
 /* Defines for wisXXX functions. */
 #define UNI_UPPER    0x1
@@ -1508,8 +1515,10 @@ BOOL smb_krb5_principal_compare_any_realm(krb5_context context,
                                          krb5_const_principal princ1, 
                                          krb5_const_principal princ2);
 int cli_krb5_get_ticket(const char *principal, time_t time_offset, 
-                       DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts);
+                       DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts, const char *ccname);
 PAC_LOGON_INFO *get_logon_info_from_pac(PAC_DATA *pac_data);
+krb5_error_code smb_krb5_renew_ticket(const char *ccache_string, const char *client_string, const char *service_string, time_t *new_start_time);
+krb5_error_code kpasswd_err_to_krb5_err(krb5_error_code res_code);
 #endif /* HAVE_KRB5 */
 
 
index c9b54ab1a21888595e35397c4652568645792076..916fb6e46d309703f6396ee67a496e9a2a670bfa 100644 (file)
 /* tdb hash size for the open database. */
 #define SMB_OPEN_DATABASE_TDB_HASH_SIZE 1049
 
+/* Characters we disallow in sharenames. */
+#define INVALID_SHARENAME_CHARS "%<>*?|/\\+=;:\","
+
+/* Seconds between connection attempts to a remote server. */
+#define FAILED_CONNECTION_CACHE_TIMEOUT 30
+
+/* Default hash size for the winbindd cache. */
+#define WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE 5000
+
 #endif
index 4b1732d42d17d0f39ff4bde29db900edf49bb33b..dc4f4ca2c032d8b54ca8d64547fa2dab0af76476 100644 (file)
@@ -73,6 +73,8 @@
 /* winbind messages */
 #define MSG_WINBIND_FINISHED     4001
 #define MSG_WINBIND_FORGET_STATE 4002
+#define MSG_WINBIND_ONLINE       4003
+#define MSG_WINBIND_OFFLINE      4004
 
 /* Flags to classify messages - used in message_send_all() */
 /* Sender will filter by flag. */
index ab768258df17fbccf04ad58c4567b9a1a00e2d91..14c83eba4b37036901c2713018875d3cb9edb898 100644 (file)
@@ -61,4 +61,10 @@ typedef uint32 WERROR;
 #define W_ERROR_IS_OK(x) (W_ERROR_V(x) == 0)
 #define W_ERROR_EQUAL(x,y) (W_ERROR_V(x) == W_ERROR_V(y))
 
+#define NT_STATUS_HAVE_NO_MEMORY(x) do { \
+        if (!(x)) {\
+                return NT_STATUS_NO_MEMORY;\
+        }\
+} while (0)
+
 #endif
index f1896710dc930cba134d63c7f6f5fdced0a1dff3..0035fc5b05ed7c2f1d4af6f95f82bc67800b5db0 100644 (file)
@@ -304,9 +304,10 @@ typedef struct pdb_context
                                           size_t *p_num_members);
 
        NTSTATUS (*pdb_enum_group_memberships)(struct pdb_context *context,
-                                              const char *username,
-                                              gid_t primary_gid,
-                                              DOM_SID **pp_sids, gid_t **pp_gids,
+                                              TALLOC_CTX *mem_ctx,
+                                              SAM_ACCOUNT *user,
+                                              DOM_SID **pp_sids,
+                                              gid_t **pp_gids,
                                               size_t *p_num_groups);
 
        NTSTATUS (*pdb_find_alias)(struct pdb_context *context,
@@ -376,6 +377,15 @@ typedef struct pdb_context
        BOOL (*pdb_search_aliases)(struct pdb_context *context,
                                   struct pdb_search *search,
                                   const DOM_SID *sid);
+       BOOL (*pdb_uid_to_rid)(struct pdb_context *context,
+                              uid_t uid, uint32 *rid);
+       BOOL (*pdb_gid_to_sid)(struct pdb_context *context,
+                              uid_t gid, DOM_SID *sid);
+       BOOL (*pdb_sid_to_id)(struct pdb_context *context, const DOM_SID *sid,
+                             union unid_t *id, enum SID_NAME_USE *type);
+
+       BOOL (*pdb_rid_algorithm)(struct pdb_context *context);
+       BOOL (*pdb_new_rid)(struct pdb_context *context, uint32 *rid);
 
        void (*free_fn)(struct pdb_context **);
        
@@ -439,8 +449,8 @@ typedef struct pdb_methods
                                       size_t *p_num_members);
 
        NTSTATUS (*enum_group_memberships)(struct pdb_methods *methods,
-                                          const char *username,
-                                          gid_t primary_gid,
+                                          TALLOC_CTX *mem_ctx,
+                                          SAM_ACCOUNT *user,
                                           DOM_SID **pp_sids, gid_t **pp_gids,
                                           size_t *p_num_groups);
 
@@ -507,6 +517,16 @@ typedef struct pdb_methods
                               struct pdb_search *search,
                               const DOM_SID *sid);
 
+       BOOL (*uid_to_rid)(struct pdb_methods *methods, uid_t uid,
+                          uint32 *rid);
+       BOOL (*gid_to_sid)(struct pdb_methods *methods, gid_t gid,
+                          DOM_SID *sid);
+       BOOL (*sid_to_id)(struct pdb_methods *methods, const DOM_SID *sid,
+                         union unid_t *id, enum SID_NAME_USE *type);
+
+       BOOL (*rid_algorithm)(struct pdb_methods *methods);
+       BOOL (*new_rid)(struct pdb_methods *methods, uint32 *rid);
+
        void *private_data;  /* Private data of some kind */
        
        void (*free_private_data)(void **);
index 7aee208c14b0fa3d8c333b8a3054e0054375ae5f..adf25c9938bc027f828c63afe29e35529520a46e 100644 (file)
-/* 
-   Unix SMB/CIFS implementation.
-   Samba parameters and setup
-   Copyright (C) Andrew Tridgell 1992-2000
-   Copyright (C) Luke Kenneth Casson Leighton 1996 - 2000
-   Copyright (C) Shirish Kalele 2000
-
-   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.
-*/
-
-#ifndef _RPC_DFS_H
-#define _RPC_DFS_H
-
-/* NETDFS pipe: calls */
-#define DFS_EXIST                0x00
-#define DFS_ADD                  0x01
-#define DFS_REMOVE               0x02
-#define DFS_GET_INFO             0x04
-#define DFS_ENUM                 0x05
-
-/* dfsadd flags */
-#define DFSFLAG_ADD_VOLUME           0x00000001
-#define DFSFLAG_RESTORE_VOLUME       0x00000002
-
-typedef struct dfs_q_dfs_exist {
-       uint32 dummy;
-} DFS_Q_DFS_EXIST;
-
-/* status == 1 if dfs exists. */
-typedef struct dfs_r_dfs_exist {
-       uint32 status;          /* Not a WERROR or NTSTATUS code */
-} DFS_R_DFS_EXIST;
-
-typedef struct dfs_q_dfs_add {
-       uint32 ptr_DfsEntryPath;
-       UNISTR2 DfsEntryPath;
-       uint32 ptr_ServerName;
-       UNISTR2 ServerName;
-       uint32 ptr_ShareName;
-       UNISTR2 ShareName;
-       uint32 ptr_Comment;
-       UNISTR2 Comment;
-       uint32 Flags;
-} DFS_Q_DFS_ADD;
-
-typedef struct dfs_r_dfs_add {
-       WERROR status;
-} DFS_R_DFS_ADD;
-
-/********************************************/
-typedef struct dfs_q_dfs_remove {
-       UNISTR2 DfsEntryPath;
-       uint32 ptr_ServerName;
-       UNISTR2 ServerName;
-       uint32 ptr_ShareName;
-       UNISTR2 ShareName;
-} DFS_Q_DFS_REMOVE;
-
-typedef struct dfs_r_dfs_remove {
-       WERROR status;
-} DFS_R_DFS_REMOVE;
-
-/********************************************/
-typedef struct dfs_info_1 {
-       uint32 ptr_entrypath;
-       UNISTR2 entrypath;
-} DFS_INFO_1;
-
-typedef struct dfs_info_2 {
-       uint32 ptr_entrypath;
-       UNISTR2 entrypath;
-       uint32 ptr_comment;
+/*
+ * Unix SMB/CIFS implementation.
+ * header auto-generated by pidl. DO NOT MODIFY!
+ */
+
+
+#ifndef _RPC_NETDFS_H
+#define _RPC_NETDFS_H
+
+#define DFS_GETMANAGERVERSION 0
+#define DFS_ADD 1
+#define DFS_REMOVE 2
+#define DFS_SETINFO 3
+#define DFS_GETINFO 4
+#define DFS_ENUM 5
+#define DFS_RENAME 6
+#define DFS_MOVE 7
+#define DFS_MANAGERGETCONFIGINFO 8
+#define DFS_MANAGERSENDSITEINFO 9
+#define DFS_ADDFTROOT 10
+#define DFS_REMOVEFTROOT 11
+#define DFS_ADDSTDROOT 12
+#define DFS_REMOVESTDROOT 13
+#define DFS_MANAGERINITIALIZE 14
+#define DFS_ADDSTDROOTFORCED 15
+#define DFS_GETDCADDRESS 16
+#define DFS_SETDCADDRESS 17
+#define DFS_FLUSHFTTABLE 18
+#define DFS_ADD2 19
+#define DFS_REMOVE2 20
+#define DFS_ENUMEX 21
+#define DFS_SETINFO2 22
+
+typedef struct netdfs_dfs_Info0 {
+       uint32 dummy;
+} NETDFS_DFS_INFO0;
+
+typedef struct netdfs_dfs_Info1 {
+       uint32 ptr0_path;
+       UNISTR2 path;
+} NETDFS_DFS_INFO1;
+
+typedef struct netdfs_dfs_Info2 {
+       uint32 ptr0_path;
+       UNISTR2 path;
+       uint32 ptr0_comment;
        UNISTR2 comment;
        uint32 state;
-       uint32 num_storages;
-} DFS_INFO_2;
+       uint32 num_stores;
+} NETDFS_DFS_INFO2;
 
-typedef struct dfs_storage_info {
+typedef struct netdfs_dfs_StorageInfo {
        uint32 state;
-       uint32 ptr_servername;
-       UNISTR2 servername;
-       uint32 ptr_sharename;
-       UNISTR2 sharename;
-} DFS_STORAGE_INFO;
-
-typedef struct dfs_info_3 {
-       uint32 ptr_entrypath;
-       UNISTR2 entrypath;
-       uint32 ptr_comment;
+       uint32 ptr0_server;
+       UNISTR2 server;
+       uint32 ptr0_share;
+       UNISTR2 share;
+} NETDFS_DFS_STORAGEINFO;
+
+typedef struct netdfs_dfs_Info3 {
+       uint32 ptr0_path;
+       UNISTR2 path;
+       uint32 ptr0_comment;
        UNISTR2 comment;
        uint32 state;
-       uint32 num_storages;
-       uint32 ptr_storages;
-       uint32 num_storage_infos;
-       DFS_STORAGE_INFO* storages;
-} DFS_INFO_3;
+       uint32 num_stores;
+       uint32 ptr0_stores;
+       uint32 size_stores;
+       NETDFS_DFS_STORAGEINFO *stores;
+} NETDFS_DFS_INFO3;
+
+typedef struct netdfs_dfs_Info4 {
+       uint32 ptr0_path;
+       UNISTR2 path;
+       uint32 ptr0_comment;
+       UNISTR2 comment;
+       uint32 state;
+       uint32 timeout;
+       struct uuid guid;
+       uint32 num_stores;
+       uint32 ptr0_stores;
+       uint32 size_stores;
+       NETDFS_DFS_STORAGEINFO *stores;
+} NETDFS_DFS_INFO4;
+
+typedef struct netdfs_dfs_Info100 {
+       uint32 ptr0_comment;
+       UNISTR2 comment;
+} NETDFS_DFS_INFO100;
+
+typedef struct netdfs_dfs_Info101 {
+       uint32 state;
+} NETDFS_DFS_INFO101;
 
-typedef struct dfs_info_ctr {
+typedef struct netdfs_dfs_Info102 {
+       uint32 timeout;
+} NETDFS_DFS_INFO102;
+
+typedef struct netdfs_dfs_Info200 {
+       uint32 ptr0_dom_root;
+       UNISTR2 dom_root;
+} NETDFS_DFS_INFO200;
+
+typedef struct netdfs_dfs_Info300 {
+       uint32 flags;
+       uint32 ptr0_dom_root;
+       UNISTR2 dom_root;
+} NETDFS_DFS_INFO300;
+
+typedef struct netdfs_dfs_Info_ctr {
        uint32 switch_value;
-       uint32 num_entries;
-       uint32 ptr_dfs_ctr; /* pointer to dfs info union */
-       union {
-               DFS_INFO_1 *info1;
-               DFS_INFO_2 *info2;
-               DFS_INFO_3 *info3;
-       } dfs;
-} DFS_INFO_CTR;
-
-typedef struct dfs_q_dfs_get_info {
-       UNISTR2 uni_path;
-  
-       uint32 ptr_server;
-       UNISTR2 uni_server;
-
-       uint32 ptr_share;
-       UNISTR2 uni_share;
-  
-       uint32 level;
-} DFS_Q_DFS_GET_INFO;
+       uint32 ptr0;
+       union netdfs_dfs_Info {
+                       NETDFS_DFS_INFO0 info0;
+                       NETDFS_DFS_INFO1 info1;
+                       NETDFS_DFS_INFO2 info2;
+                       NETDFS_DFS_INFO3 info3;
+                       NETDFS_DFS_INFO4 info4;
+                       NETDFS_DFS_INFO100 info100;
+                       NETDFS_DFS_INFO101 info101;
+                       NETDFS_DFS_INFO102 info102;
+       } u;
+} NETDFS_DFS_INFO_CTR;
+
+typedef struct netdfs_dfs_EnumArray1 {
+       uint32 count;
+       uint32 ptr0_s;
+       uint32 size_s;
+       NETDFS_DFS_INFO1 *s;
+} NETDFS_DFS_ENUMARRAY1;
+
+typedef struct netdfs_dfs_EnumArray2 {
+       uint32 count;
+       uint32 ptr0_s;
+       uint32 size_s;
+       NETDFS_DFS_INFO2 *s;
+} NETDFS_DFS_ENUMARRAY2;
+
+typedef struct netdfs_dfs_EnumArray3 {
+       uint32 count;
+       uint32 ptr0_s;
+       uint32 size_s;
+       NETDFS_DFS_INFO3 *s;
+} NETDFS_DFS_ENUMARRAY3;
 
-typedef struct dfs_r_dfs_get_info {
+typedef struct netdfs_dfs_EnumArray4 {
+       uint32 count;
+       uint32 ptr0_s;
+       uint32 size_s;
+       NETDFS_DFS_INFO4 *s;
+} NETDFS_DFS_ENUMARRAY4;
+
+typedef struct netdfs_dfs_EnumArray200 {
+       uint32 count;
+       uint32 ptr0_s;
+       uint32 size_s;
+       NETDFS_DFS_INFO200 *s;
+} NETDFS_DFS_ENUMARRAY200;
+
+typedef struct netdfs_dfs_EnumArray300 {
+       uint32 count;
+       uint32 ptr0_s;
+       uint32 size_s;
+       NETDFS_DFS_INFO300 *s;
+} NETDFS_DFS_ENUMARRAY300;
+
+typedef struct netdfs_dfs_EnumInfo_ctr {
+       uint32 switch_value;
+       uint32 ptr0;
+       union netdfs_dfs_EnumInfo {
+                       NETDFS_DFS_ENUMARRAY1 info1;
+                       NETDFS_DFS_ENUMARRAY2 info2;
+                       NETDFS_DFS_ENUMARRAY3 info3;
+                       NETDFS_DFS_ENUMARRAY4 info4;
+                       NETDFS_DFS_ENUMARRAY200 info200;
+                       NETDFS_DFS_ENUMARRAY300 info300;
+       } u;
+} NETDFS_DFS_ENUMINFO_CTR;
+
+typedef struct netdfs_dfs_EnumStruct {
        uint32 level;
-       uint32 ptr_ctr;
-       DFS_INFO_CTR ctr;
+       NETDFS_DFS_ENUMINFO_CTR e;
+} NETDFS_DFS_ENUMSTRUCT;
+
+typedef struct netdfs_q_dfs_GetManagerVersion {
+       uint32 dummy;
+} NETDFS_Q_DFS_GETMANAGERVERSION;
+
+typedef struct netdfs_r_dfs_GetManagerVersion {
+       uint32 exist_flag;
+} NETDFS_R_DFS_GETMANAGERVERSION;
+
+typedef struct netdfs_q_dfs_Add {
+       UNISTR2 path;
+       UNISTR2 server;
+       uint32 ptr0_share;
+       UNISTR2 share;
+       uint32 ptr0_comment;
+       UNISTR2 comment;
+       uint32 flags;
+} NETDFS_Q_DFS_ADD;
+
+typedef struct netdfs_r_dfs_Add {
+       WERROR status;
+} NETDFS_R_DFS_ADD;
+
+typedef struct netdfs_q_dfs_Remove {
+       UNISTR2 path;
+       uint32 ptr0_server;
+       UNISTR2 server;
+       uint32 ptr0_share;
+       UNISTR2 share;
+} NETDFS_Q_DFS_REMOVE;
+
+typedef struct netdfs_r_dfs_Remove {
        WERROR status;
-} DFS_R_DFS_GET_INFO;
+} NETDFS_R_DFS_REMOVE;
 
-typedef struct dfs_q_dfs_enum {
+typedef struct netdfs_q_dfs_SetInfo {
+       uint32 dummy;
+} NETDFS_Q_DFS_SETINFO;
+
+typedef struct netdfs_r_dfs_SetInfo {
+       WERROR status;
+} NETDFS_R_DFS_SETINFO;
+
+typedef struct netdfs_q_dfs_GetInfo {
+       UNISTR2 path;
+       uint32 ptr0_server;
+       UNISTR2 server;
+       uint32 ptr0_share;
+       UNISTR2 share;
        uint32 level;
-       uint32 maxpreflen;
-       uint32 ptr_buffer;
-       uint32 level2;
-       uint32 ptr_num_entries;
-       uint32 num_entries;
-       uint32 ptr_num_entries2;
-       uint32 num_entries2;
-       ENUM_HND reshnd;
-} DFS_Q_DFS_ENUM;
-
-typedef struct dfs_r_dfs_enum {
-       DFS_INFO_CTR *ctr;
-       uint32 ptr_buffer;
+} NETDFS_Q_DFS_GETINFO;
+
+typedef struct netdfs_r_dfs_GetInfo {
+       NETDFS_DFS_INFO_CTR info;
+       WERROR status;
+} NETDFS_R_DFS_GETINFO;
+
+typedef struct netdfs_q_dfs_Enum {
        uint32 level;
-       uint32 level2;
-       uint32 ptr_num_entries;
-       uint32 num_entries;
-       uint32 ptr_num_entries2;
-       uint32 num_entries2;
-       ENUM_HND reshnd;
-       WERROR status;
-} DFS_R_DFS_ENUM;
-#endif  
+       uint32 bufsize;
+       uint32 ptr0_info;
+       NETDFS_DFS_ENUMSTRUCT info;
+       uint32 ptr0_unknown;
+       uint32 unknown;
+       uint32 ptr0_total;
+       uint32 total;
+} NETDFS_Q_DFS_ENUM;
+
+typedef struct netdfs_r_dfs_Enum {
+       uint32 ptr0_info;
+       NETDFS_DFS_ENUMSTRUCT info;
+       uint32 ptr0_total;
+       uint32 total;
+       WERROR status;
+} NETDFS_R_DFS_ENUM;
+
+typedef struct netdfs_q_dfs_Rename {
+       uint32 dummy;
+} NETDFS_Q_DFS_RENAME;
+
+typedef struct netdfs_r_dfs_Rename {
+       WERROR status;
+} NETDFS_R_DFS_RENAME;
+
+typedef struct netdfs_q_dfs_Move {
+       uint32 dummy;
+} NETDFS_Q_DFS_MOVE;
+
+typedef struct netdfs_r_dfs_Move {
+       WERROR status;
+} NETDFS_R_DFS_MOVE;
+
+typedef struct netdfs_q_dfs_ManagerGetConfigInfo {
+       uint32 dummy;
+} NETDFS_Q_DFS_MANAGERGETCONFIGINFO;
+
+typedef struct netdfs_r_dfs_ManagerGetConfigInfo {
+       WERROR status;
+} NETDFS_R_DFS_MANAGERGETCONFIGINFO;
+
+typedef struct netdfs_q_dfs_ManagerSendSiteInfo {
+       uint32 dummy;
+} NETDFS_Q_DFS_MANAGERSENDSITEINFO;
+
+typedef struct netdfs_r_dfs_ManagerSendSiteInfo {
+       WERROR status;
+} NETDFS_R_DFS_MANAGERSENDSITEINFO;
+
+typedef struct netdfs_q_dfs_AddFtRoot {
+       uint32 dummy;
+} NETDFS_Q_DFS_ADDFTROOT;
+
+typedef struct netdfs_r_dfs_AddFtRoot {
+       WERROR status;
+} NETDFS_R_DFS_ADDFTROOT;
+
+typedef struct netdfs_q_dfs_RemoveFtRoot {
+       uint32 dummy;
+} NETDFS_Q_DFS_REMOVEFTROOT;
+
+typedef struct netdfs_r_dfs_RemoveFtRoot {
+       WERROR status;
+} NETDFS_R_DFS_REMOVEFTROOT;
+
+typedef struct netdfs_q_dfs_AddStdRoot {
+       uint32 dummy;
+} NETDFS_Q_DFS_ADDSTDROOT;
+
+typedef struct netdfs_r_dfs_AddStdRoot {
+       WERROR status;
+} NETDFS_R_DFS_ADDSTDROOT;
+
+typedef struct netdfs_q_dfs_RemoveStdRoot {
+       uint32 dummy;
+} NETDFS_Q_DFS_REMOVESTDROOT;
+
+typedef struct netdfs_r_dfs_RemoveStdRoot {
+       WERROR status;
+} NETDFS_R_DFS_REMOVESTDROOT;
+
+typedef struct netdfs_q_dfs_ManagerInitialize {
+       uint32 dummy;
+} NETDFS_Q_DFS_MANAGERINITIALIZE;
+
+typedef struct netdfs_r_dfs_ManagerInitialize {
+       WERROR status;
+} NETDFS_R_DFS_MANAGERINITIALIZE;
+
+typedef struct netdfs_q_dfs_AddStdRootForced {
+       uint32 dummy;
+} NETDFS_Q_DFS_ADDSTDROOTFORCED;
+
+typedef struct netdfs_r_dfs_AddStdRootForced {
+       WERROR status;
+} NETDFS_R_DFS_ADDSTDROOTFORCED;
+
+typedef struct netdfs_q_dfs_GetDcAddress {
+       uint32 dummy;
+} NETDFS_Q_DFS_GETDCADDRESS;
+
+typedef struct netdfs_r_dfs_GetDcAddress {
+       WERROR status;
+} NETDFS_R_DFS_GETDCADDRESS;
+
+typedef struct netdfs_q_dfs_SetDcAddress {
+       uint32 dummy;
+} NETDFS_Q_DFS_SETDCADDRESS;
+
+typedef struct netdfs_r_dfs_SetDcAddress {
+       WERROR status;
+} NETDFS_R_DFS_SETDCADDRESS;
+
+typedef struct netdfs_q_dfs_FlushFtTable {
+       uint32 dummy;
+} NETDFS_Q_DFS_FLUSHFTTABLE;
+
+typedef struct netdfs_r_dfs_FlushFtTable {
+       WERROR status;
+} NETDFS_R_DFS_FLUSHFTTABLE;
+
+typedef struct netdfs_q_dfs_Add2 {
+       uint32 dummy;
+} NETDFS_Q_DFS_ADD2;
+
+typedef struct netdfs_r_dfs_Add2 {
+       WERROR status;
+} NETDFS_R_DFS_ADD2;
+
+typedef struct netdfs_q_dfs_Remove2 {
+       uint32 dummy;
+} NETDFS_Q_DFS_REMOVE2;
+
+typedef struct netdfs_r_dfs_Remove2 {
+       WERROR status;
+} NETDFS_R_DFS_REMOVE2;
+
+typedef struct netdfs_q_dfs_EnumEx {
+       uint32 dummy;
+} NETDFS_Q_DFS_ENUMEX;
+
+typedef struct netdfs_r_dfs_EnumEx {
+       WERROR status;
+} NETDFS_R_DFS_ENUMEX;
+
+typedef struct netdfs_q_dfs_SetInfo2 {
+       uint32 dummy;
+} NETDFS_Q_DFS_SETINFO2;
+
+typedef struct netdfs_r_dfs_SetInfo2 {
+       WERROR status;
+} NETDFS_R_DFS_SETINFO2;
+
+#endif /* _RPC_NETDFS_H */
index dd255c28d5d5e3b52166db8fe0a5375bb45c7d23..c8d6a210b51eb3e1806849ea1f72d9c47533699a 100644 (file)
@@ -80,6 +80,7 @@
 #define LSA_UNK_GET_CONNUSER   0x2d /* LsaGetConnectedCredentials ? */
 #define LSA_QUERYINFO2         0x2e
 #define LSA_QUERYTRUSTDOMINFOBYNAME 0x30
+#define LSA_QUERYDOMINFOPOL    0x35
 #define LSA_OPENTRUSTDOMBYNAME 0x37
 
 /* XXXX these are here to get a compile! */
@@ -393,7 +394,7 @@ typedef struct lsa_trans_name_info
 } LSA_TRANS_NAME;
 
 /* This number is based on Win2k and later maximum response allowed */
-#define MAX_LOOKUP_SIDS 20480
+#define MAX_LOOKUP_SIDS 20480  /* 0x5000 */
 
 /* LSA_TRANS_NAME_ENUM - LSA Translated Name Enumeration container */
 typedef struct lsa_trans_name_enum_info
@@ -750,6 +751,25 @@ typedef struct {
 
 /*******************************************************/
 
+/* LSA_Q_OPEN_TRUSTED_DOMAIN_BY_NAME - LSA Query Open Trusted Domain by Name*/
+typedef struct lsa_q_open_trusted_domain_by_name
+{
+       POLICY_HND      pol;    /* policy handle */
+       LSA_STRING      name;   /* domain name */
+       uint32  access_mask;    /* access mask */
+       
+} LSA_Q_OPEN_TRUSTED_DOMAIN_BY_NAME;
+
+/* LSA_R_OPEN_TRUSTED_DOMAIN_BY_NAME - response to LSA Query Open Trusted Domain by Name */
+typedef struct {
+       POLICY_HND      handle; /* trustdom policy handle */
+       NTSTATUS        status; /* return code */
+} LSA_R_OPEN_TRUSTED_DOMAIN_BY_NAME;
+
+
+/*******************************************************/
+
+
 typedef struct {
        POLICY_HND      handle; 
        UNISTR4         secretname;
@@ -955,4 +975,38 @@ typedef struct r_lsa_query_trusted_domain_info
        NTSTATUS status;
 } LSA_R_QUERY_TRUSTED_DOMAIN_INFO;
 
+typedef struct dom_info_kerberos {
+       uint32 enforce_restrictions;
+       NTTIME service_tkt_lifetime;
+       NTTIME user_tkt_lifetime;
+       NTTIME user_tkt_renewaltime;
+       NTTIME clock_skew;
+       NTTIME unknown6;
+} LSA_DOM_INFO_POLICY_KERBEROS;
+
+typedef struct dom_info_efs {
+       uint32 blob_len;
+       UNISTR2 efs_blob;
+} LSA_DOM_INFO_POLICY_EFS;
+
+typedef struct lsa_dom_info_union {
+       uint16 info_class;
+       LSA_DOM_INFO_POLICY_EFS efs_policy;
+       LSA_DOM_INFO_POLICY_KERBEROS krb_policy;
+} LSA_DOM_INFO_UNION;
+
+/* LSA_Q_QUERY_DOM_INFO_POLICY - LSA query info */
+typedef struct lsa_q_query_dom_info_policy
+{
+       POLICY_HND pol;    /* policy handle */
+       uint16 info_class; /* info class */
+} LSA_Q_QUERY_DOM_INFO_POLICY;
+
+typedef struct lsa_r_query_dom_info_policy
+{
+       LSA_DOM_INFO_UNION *info;
+       NTSTATUS status;
+} LSA_R_QUERY_DOM_INFO_POLICY;
+
+
 #endif /* _RPC_LSA_H */
index c1d85403448959826c11e2ded4ff9bc5794aebb9..91f85601e3033272f1e1b300dfde4a9e03d1ef87 100644 (file)
 #define NL_CTRL_REPL_IN_PROGRESS 0x0002
 #define NL_CTRL_FULL_SYNC        0x0004
 
-#define LOGON_EXTRA_SIDS             0x0020
-#define LOGON_RESOURCE_GROUPS        0x0200 
+#define LOGON_GUEST                    0x00000001
+#define LOGON_NOENCRYPTION             0x00000002
+#define LOGON_CACHED_ACCOUNT           0x00000004
+#define LOGON_USED_LM_PASSWORD         0x00000008
+#define LOGON_EXTRA_SIDS               0x00000020
+#define LOGON_SUBAUTH_SESSION_KEY      0x00000040
+#define LOGON_SERVER_TRUST_ACCOUNT     0x00000080
+#define LOGON_NTLMV2_ENABLED           0x00000100
+#define LOGON_RESOURCE_GROUPS          0x00000200
+#define LOGON_PROFILE_PATH_RETURNED    0x00000400
+#define LOGON_GRACE_LOGON              0x01000000
 
 #define SE_GROUP_MANDATORY             0x00000001
 #define SE_GROUP_ENABLED_BY_DEFAULT    0x00000002
index 342db37ea574721eced74205661bb2e1d5e726f0..2fae514c3d1f1d9e368f721765f39e68e072f484 100644 (file)
@@ -1843,6 +1843,10 @@ typedef struct q_samr_chgpasswd3
 
 } SAMR_Q_CHGPASSWD3;
 
+#define REJECT_REASON_TOO_SHORT                0x00000001
+#define REJECT_REASON_IN_HISTORY       0x00000002
+#define REJECT_REASON_NOT_COMPLEX      0x00000005
+
 /* SAMR_CHANGE_REJECT */
 typedef struct samr_change_reject
 {
index f2d1afd96b3924eb74448f7a797e4de1d161081d..610a14b52be628f0ff08db940ab2f1492a4d49d2 100644 (file)
@@ -75,10 +75,10 @@ typedef struct trusted_dom_pass {
  * trusted domain entry/entries returned by secrets_get_trusted_domains
  * (used in _lsa_enum_trust_dom call)
  */
-typedef struct trustdom {
-       smb_ucs2_t *name;
+struct trustdom_info {
+       char *name;
        DOM_SID sid;
-} TRUSTDOM;
+};
 
 /*
  * Format of an OpenAFS keyfile
index 3a6f68b9ecc4a113b29c5dbac6c33489bfca1793..b167e4ee126b7099ee84d2ae751a6f4ffb85ca13 100644 (file)
@@ -224,18 +224,26 @@ typedef struct nttime_info {
 
 
 /* Allowable account control bits */
-#define ACB_DISABLED   0x0001  /* 1 = User account disabled */
-#define ACB_HOMDIRREQ  0x0002  /* 1 = Home directory required */
-#define ACB_PWNOTREQ   0x0004  /* 1 = User password not required */
-#define ACB_TEMPDUP    0x0008  /* 1 = Temporary duplicate account */
-#define ACB_NORMAL     0x0010  /* 1 = Normal user account */
-#define ACB_MNS        0x0020  /* 1 = MNS logon user account */
-#define ACB_DOMTRUST   0x0040  /* 1 = Interdomain trust account */
-#define ACB_WSTRUST    0x0080  /* 1 = Workstation trust account */
-#define ACB_SVRTRUST   0x0100  /* 1 = Server trust account (BDC) */
-#define ACB_PWNOEXP    0x0200  /* 1 = User password does not expire */
-#define ACB_AUTOLOCK   0x0400  /* 1 = Account auto locked */
+#define ACB_DISABLED                   0x00000001  /* 1 = User account disabled */
+#define ACB_HOMDIRREQ                  0x00000002  /* 1 = Home directory required */
+#define ACB_PWNOTREQ                   0x00000004  /* 1 = User password not required */
+#define ACB_TEMPDUP                    0x00000008  /* 1 = Temporary duplicate account */
+#define ACB_NORMAL                     0x00000010  /* 1 = Normal user account */
+#define ACB_MNS                                0x00000020  /* 1 = MNS logon user account */
+#define ACB_DOMTRUST                   0x00000040  /* 1 = Interdomain trust account */
+#define ACB_WSTRUST                    0x00000080  /* 1 = Workstation trust account */
+#define ACB_SVRTRUST                   0x00000100  /* 1 = Server trust account (BDC) */
+#define ACB_PWNOEXP                    0x00000200  /* 1 = User password does not expire */
+#define ACB_AUTOLOCK                   0x00000400  /* 1 = Account auto locked */
+
+/* only valid for > Windows 2000 */
+#define ACB_ENC_TXT_PWD_ALLOWED                0x00000800  /* 1 = Text password encryped */
+#define ACB_SMARTCARD_REQUIRED         0x00001000  /* 1 = Smart Card required */
+#define ACB_TRUSTED_FOR_DELEGATION     0x00002000  /* 1 = Trusted for Delegation */
+#define ACB_NOT_DELEGATED              0x00004000  /* 1 = Not delegated */
+#define ACB_USE_DES_KEY_ONLY           0x00008000  /* 1 = Use DES key only */
+#define ACB_DONT_REQUIRE_PREAUTH       0x00010000  /* 1 = Preauth not required */
+
 #define MAX_HOURS_LEN 32
 
 #ifndef MAXSUBAUTHS
@@ -262,6 +270,9 @@ enum SID_NAME_USE {
 #define LOOKUP_NAME_REMOTE   2  /* Ask others */
 #define LOOKUP_NAME_ALL (LOOKUP_NAME_ISOLATED|LOOKUP_NAME_REMOTE)
 
+#define LOOKUP_NAME_GROUP    4  /* This is a NASTY hack for valid users = @foo
+                                * where foo also exists in as user. */
+
 /**
  * @brief Security Identifier
  *
@@ -280,6 +291,21 @@ typedef struct sid_info {
        uint32 sub_auths[MAXSUBAUTHS];  
 } DOM_SID;
 
+struct lsa_dom_info {
+       BOOL valid;
+       DOM_SID sid;
+       const char *name;
+       int num_idxs;
+       int *idxs;
+};
+
+struct lsa_name_info {
+       uint32 rid;
+       enum SID_NAME_USE type;
+       const char *name;
+       int dom_idx;
+};
+
 /* Some well-known SIDs */
 extern const DOM_SID global_sid_World_Domain;
 extern const DOM_SID global_sid_World;
@@ -302,6 +328,8 @@ extern const DOM_SID global_sid_Builtin_Server_Operators;
 extern const DOM_SID global_sid_Builtin_Print_Operators;
 extern const DOM_SID global_sid_Builtin_Backup_Operators;
 extern const DOM_SID global_sid_Builtin_Replicator;
+extern const DOM_SID global_sid_Unix_Users;
+extern const DOM_SID global_sid_Unix_Groups;
 
 /*
  * The complete list of SIDS belonging to this user.
@@ -316,7 +344,7 @@ extern const DOM_SID global_sid_Builtin_Replicator;
 #define PRIMARY_USER_SID_INDEX 0
 #define PRIMARY_GROUP_SID_INDEX 1
 
-typedef struct _nt_user_token {
+typedef struct nt_user_token {
        size_t num_sids;
        DOM_SID *user_sids;
        SE_PRIV privileges;
@@ -1719,6 +1747,22 @@ typedef struct uuid_flat {
 /* map readonly options */
 enum mapreadonly_options {MAP_READONLY_NO, MAP_READONLY_YES, MAP_READONLY_PERMISSIONS};
 
+/* usershare error codes. */
+enum usershare_err {
+               USERSHARE_OK=0,
+               USERSHARE_MALFORMED_FILE,
+               USERSHARE_BAD_VERSION,
+               USERSHARE_MALFORMED_PATH,
+               USERSHARE_MALFORMED_COMMENT_DEF,
+               USERSHARE_MALFORMED_ACL_DEF,
+               USERSHARE_ACL_ERR,
+               USERSHARE_PATH_NOT_ABSOLUTE,
+               USERSHARE_PATH_IS_DENIED,
+               USERSHARE_PATH_NOT_ALLOWED,
+               USERSHARE_PATH_NOT_DIRECTORY,
+               USERSHARE_POSIX_ERR
+};
+
 /* Different reasons for closing a file. */
 enum file_close_type {NORMAL_CLOSE=0,SHUTDOWN_CLOSE,ERROR_CLOSE};
 
index bea1a6d84a36c54dd3eec4bf6a4aa93009f64dfe..8870205bbbc79c4f99bf96f486da56ce545904ff 100644 (file)
@@ -131,8 +131,7 @@ NTSTATUS smbldap_init(TALLOC_CTX *mem_ctx,
                       struct smbldap_state **smbldap_state);
 
 const char* get_attr_key2string( ATTRIB_MAP_ENTRY table[], int key );
-const char** get_attr_list( ATTRIB_MAP_ENTRY table[] );
-void free_attr_list( const char **list );
+const char** get_attr_list( TALLOC_CTX *mem_ctx, ATTRIB_MAP_ENTRY table[] );
 void smbldap_set_mod (LDAPMod *** modlist, int modop, const char *attribute, const char *value);
 void smbldap_make_mod(LDAP *ldap_struct, LDAPMessage *existing,
                      LDAPMod ***mods,
@@ -207,7 +206,17 @@ int ldapsam_search_suffix_by_name(struct ldapsam_privates *ldap_state,
 NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context,
                           PDB_METHODS **pdb_method,
                           const char *location);
-const char** get_userattr_list( int schema_ver );
+const char** get_userattr_list( TALLOC_CTX *mem_ctx, int schema_ver );
+
+char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry,
+                                      const char *attribute,
+                                      TALLOC_CTX *mem_ctx);
+void talloc_autofree_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result);
+void talloc_autofree_ldapmod(TALLOC_CTX *mem_ctx, LDAPMod **mod);
+const char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld,
+                             LDAPMessage *entry);
+
+
 
 #endif         /* HAVE_LDAP */
 
index d3422f0d78ac03d599ac2fc2898455ca083bf1be..d20a15d90e26c7ce74cfb74f6a7ab00d6753d5b8 100644 (file)
@@ -34,7 +34,7 @@ static BOOL load_msg(const char *msg_file)
        char *msgid, *msgstr;
        TDB_DATA key, data;
 
-       lines = file_lines_load(msg_file, &num_lines);
+       lines = file_lines_load(msg_file, &num_lines,0);
 
        if (!lines) {
                return False;
index 1b31dff4995063a8fc37996b03c592737bf4b51a..9b587224e3e8b19624061ed92081ebbedc3e6030 100644 (file)
@@ -29,3 +29,12 @@ void decrement_smbd_process_count( void )
        return;
 }
 
+int find_service(fstring service)
+{
+       return -1;
+}
+
+BOOL conn_snum_used(int snum)
+{
+       return False;
+}
diff --git a/source3/lib/events.c b/source3/lib/events.c
new file mode 100644 (file)
index 0000000..314f074
--- /dev/null
@@ -0,0 +1,125 @@
+/*
+   Unix SMB/CIFS implementation.
+   Timed event library.
+   Copyright (C) Andrew Tridgell 1992-1998
+   Copyright (C) Volker Lendecke 2005
+
+   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"
+
+static struct timed_event *timed_events;
+
+static int timed_event_destructor(void *p)
+{
+       struct timed_event *te = talloc_get_type_abort(p, struct timed_event);
+       DEBUG(10, ("Destroying timed event %lx \"%s\"\n", (unsigned long)te,
+               te->event_name));
+       DLIST_REMOVE(timed_events, te);
+       return 0;
+}
+
+/****************************************************************************
+ Schedule a function for future calling, cancel with talloc_free().
+ It's the responsibility of the handler to call talloc_free() on the event
+ handed to it.
+****************************************************************************/
+
+struct timed_event *add_timed_event(TALLOC_CTX *mem_ctx,
+                               struct timeval when,
+                               const char *event_name,
+                               void (*handler)(struct timed_event *te,
+                                               const struct timeval *now,
+                                               void *private_data),
+                               void *private_data)
+{
+       struct timed_event *te, *last_te, *cur_te;
+
+       te = TALLOC_P(mem_ctx, struct timed_event);
+       if (te == NULL) {
+               DEBUG(0, ("talloc failed\n"));
+               return NULL;
+       }
+
+       te->when = when;
+       te->event_name = event_name;
+       te->handler = handler;
+       te->private_data = private_data;
+
+       /* keep the list ordered */
+       last_te = NULL;
+       for (cur_te = timed_events; cur_te; cur_te = cur_te->next) {
+               /* if the new event comes before the current one break */
+               if (!timeval_is_zero(&cur_te->when) &&
+                               timeval_compare(&te->when, &cur_te->when) < 0) {
+                       break;
+               }
+               last_te = cur_te;
+       }
+
+       DLIST_ADD_AFTER(timed_events, te, last_te);
+       talloc_set_destructor(te, timed_event_destructor);
+
+       DEBUG(10, ("Added timed event \"%s\": %lx\n", event_name,
+                       (unsigned long)te));
+       return te;
+}
+
+void run_events(void)
+{
+       struct timeval now;
+
+       if (timed_events == NULL) {
+               /* No syscall if there are no events */
+               DEBUG(10, ("run_events: No events\n"));
+               return;
+       }
+
+       GetTimeOfDay(&now);
+
+       if (timeval_compare(&now, &timed_events->when) < 0) {
+               /* Nothing to do yet */
+               DEBUG(10, ("run_events: Nothing to do\n"));
+               return;
+       }
+
+       DEBUG(10, ("Running event \"%s\" %lx\n", timed_events->event_name,
+               (unsigned long)timed_events));
+
+       timed_events->handler(timed_events, &now, timed_events->private_data);
+       return;
+}
+
+struct timeval *get_timed_events_timeout(struct timeval *to_ret, time_t default_to)
+{
+       struct timeval now;
+
+       if (timed_events == NULL) {
+               if (default_to == (time_t)-1) {
+                       return NULL;
+               }
+               *to_ret = timeval_set(default_to, 0);
+               return to_ret;
+       }
+
+       now = timeval_current();
+       *to_ret = timeval_until(&now, &timed_events->when);
+
+       DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)to_ret->tv_sec,
+               (int)to_ret->tv_usec));
+
+       return to_ret;
+}
index f37bbc9c2fd3b310e7971246d80aa2e5801af7c6..5b643bf297ef7503fea19895a1347eaa6be24fb9 100644 (file)
@@ -114,14 +114,14 @@ static int do_reseed(BOOL use_fd, int fd)
         * seriously this will be secret.
         */
 
-       pw = getpwnam_alloc("root");
+       pw = getpwnam_alloc(NULL, "root");
        if (pw && pw->pw_passwd) {
                size_t i;
                unsigned char md4_tmp[16];
                mdfour(md4_tmp, (unsigned char *)pw->pw_passwd, strlen(pw->pw_passwd));
                for (i=0;i<16;i++)
                        seed_inbuf[8+i] ^= md4_tmp[i];
-               passwd_free(&pw);
+               talloc_free(pw);
        }
 
        /*
index 058bbc99b0bcce105609c18af40a633096a95ad0..2d6518aed6a718a429962e487e61702f4a9b2836 100644 (file)
@@ -604,4 +604,19 @@ BOOL message_send_all(TDB_CONTEXT *conn_tdb, int msg_type,
                *n_sent = msg_all.n_sent;
        return True;
 }
+
+/*
+ * Block and unblock receiving of messages. Allows removal of race conditions
+ * when doing a fork and changing message disposition.
+ */
+
+void message_block(void)
+{
+       BlockSignals(True, SIGUSR1);
+}
+
+void message_unblock(void)
+{
+       BlockSignals(False, SIGUSR1);
+}
 /** @} **/
index 212d3831fd588d891898c3b032c791243587f3a2..8a4c41d7df55bf86bebfb8f846f24673e38bd987 100644 (file)
@@ -71,6 +71,7 @@ static const struct {
        {NT_STATUS_PASSWORD_MUST_CHANGE, PAM_NEW_AUTHTOK_REQD},
        {NT_STATUS_ACCOUNT_LOCKED_OUT, PAM_MAXTRIES},
        {NT_STATUS_NO_MEMORY, PAM_BUF_ERR},
+       {NT_STATUS_PASSWORD_RESTRICTION, PAM_PERM_DENIED},
        {NT_STATUS_OK, PAM_SUCCESS}
 };
 
index b041eb7f1b2d5b1e2b300a0cff3b01c3661eb0c5..08e41083b59946f0ef1ac29e33b61544961c997a 100644 (file)
@@ -32,7 +32,8 @@ pid_t pidfile_pid(const char *name)
 {
        int fd;
        char pidstr[20];
-       unsigned ret;
+       pid_t pid;
+       unsigned int ret;
        pstring pidFile;
 
        slprintf(pidFile, sizeof(pidFile)-1, "%s/%s.pid", lp_piddir(), name);
@@ -57,7 +58,8 @@ pid_t pidfile_pid(const char *name)
                goto noproc;
        }
        
-       if (!process_exists_by_pid(ret)) {
+       pid = (pid_t)ret;
+       if (!process_exists_by_pid(pid)) {
                goto noproc;
        }
 
index 78b99fd7fb03168fe78c71d1e4d8feea61e6d1cb..c1f1dc7f4003c872a01b0e29bb48f94d86e76bdf 100644 (file)
@@ -50,7 +50,7 @@
  Display the prompt and wait for input. Call callback() regularly
 ****************************************************************************/
 
-static char *smb_readline_replacement(char *prompt, void (*callback)(void), 
+static char *smb_readline_replacement(const char *prompt, void (*callback)(void), 
                                char **(completion_fn)(const char *text, int start, int end))
 {
        fd_set fds;
@@ -82,7 +82,7 @@ static char *smb_readline_replacement(char *prompt, void (*callback)(void),
  Display the prompt and wait for input. Call callback() regularly.
 ****************************************************************************/
 
-char *smb_readline(char *prompt, void (*callback)(void), 
+char *smb_readline(const char *prompt, void (*callback)(void), 
                   char **(completion_fn)(const char *text, int start, int end))
 {
 #if HAVE_LIBREADLINE
index ace0aee866464e2d0ba8a8169b750d6ccb44ffd8..273bf0f0a3f365fa915ce1ace9adba2fe1c3c595 100644 (file)
 
 #include "includes.h"
 
+/* Map generic permissions to file object specific permissions */
+
+struct generic_mapping file_generic_mapping = {
+       FILE_GENERIC_READ,
+       FILE_GENERIC_WRITE,
+       FILE_GENERIC_EXECUTE,
+       FILE_GENERIC_ALL
+};
+
 /*******************************************************************
  Works out the linearization size of a SEC_DESC.
 ********************************************************************/
@@ -520,3 +529,4 @@ void init_sec_access(SEC_ACCESS *t, uint32 mask)
        t->mask = mask;
 }
 
+
diff --git a/source3/lib/sharesec.c b/source3/lib/sharesec.c
new file mode 100644 (file)
index 0000000..b98e304
--- /dev/null
@@ -0,0 +1,308 @@
+/* 
+ *  Unix SMB/Netbios implementation.
+ *  SEC_DESC handling functions
+ *  Copyright (C) Jeremy R. Allison            1995-2003.
+ *  
+ *  This program is free software; you can redistribute it and/or modify
+ *  it under the terms of the GNU General Public License as published by
+ *  the Free Software Foundation; either version 2 of the License, or
+ *  (at your option) any later version.
+ *  
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *  
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, write to the Free Software
+ *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include "includes.h"
+
+/*******************************************************************
+ Create the share security tdb.
+ ********************************************************************/
+
+static TDB_CONTEXT *share_tdb; /* used for share security descriptors */
+#define SHARE_DATABASE_VERSION_V1 1
+#define SHARE_DATABASE_VERSION_V2 2 /* version id in little endian. */
+
+/* Map generic permissions to file object specific permissions */
+
+static struct generic_mapping file_generic_mapping = {
+        FILE_GENERIC_READ,
+        FILE_GENERIC_WRITE,
+        FILE_GENERIC_EXECUTE,
+        FILE_GENERIC_ALL
+};
+
+
+BOOL share_info_db_init(void)
+{
+       const char *vstring = "INFO/version";
+       int32 vers_id;
+       if (share_tdb) {
+               return True;
+       }
+
+       share_tdb = tdb_open_log(lock_path("share_info.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
+       if (!share_tdb) {
+               DEBUG(0,("Failed to open share info database %s (%s)\n",
+                       lock_path("share_info.tdb"), strerror(errno) ));
+               return False;
+       }
+       /* handle a Samba upgrade */
+       tdb_lock_bystring(share_tdb, vstring, 0);
+
+       /* Cope with byte-reversed older versions of the db. */
+       vers_id = tdb_fetch_int32(share_tdb, vstring);
+       if ((vers_id == SHARE_DATABASE_VERSION_V1) || (IREV(vers_id) == SHARE_DATABASE_VERSION_V1)) {
+               /* Written on a bigendian machine with old fetch_int code. Save as le. */
+               tdb_store_int32(share_tdb, vstring, SHARE_DATABASE_VERSION_V2);
+               vers_id = SHARE_DATABASE_VERSION_V2;
+       }
+
+       if (vers_id != SHARE_DATABASE_VERSION_V2) {
+               tdb_traverse(share_tdb, tdb_traverse_delete_fn, NULL);
+               tdb_store_int32(share_tdb, vstring, SHARE_DATABASE_VERSION_V2);
+       }
+       tdb_unlock_bystring(share_tdb, vstring);
+
+       return True;
+}
+
+/*******************************************************************
+ Fake up a Everyone, default access as a default.
+ def_access is a GENERIC_XXX access mode.
+ ********************************************************************/
+
+SEC_DESC *get_share_security_default( TALLOC_CTX *ctx, size_t *psize, uint32 def_access)
+{
+       SEC_ACCESS sa;
+       SEC_ACE ace;
+       SEC_ACL *psa = NULL;
+       SEC_DESC *psd = NULL;
+       uint32 spec_access = def_access;
+
+       se_map_generic(&spec_access, &file_generic_mapping);
+
+       init_sec_access(&sa, def_access | spec_access );
+       init_sec_ace(&ace, &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 0);
+
+       if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 1, &ace)) != NULL) {
+               psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, psize);
+       }
+
+       if (!psd) {
+               DEBUG(0,("get_share_security: Failed to make SEC_DESC.\n"));
+               return NULL;
+       }
+
+       return psd;
+}
+
+/*******************************************************************
+ Pull a security descriptor from the share tdb.
+ ********************************************************************/
+
+SEC_DESC *get_share_security( TALLOC_CTX *ctx, int snum, size_t *psize)
+{
+       prs_struct ps;
+       fstring key;
+       SEC_DESC *psd = NULL;
+
+       if (!share_info_db_init()) {
+               return NULL;
+       }
+
+       *psize = 0;
+
+       /* Fetch security descriptor from tdb */
+       slprintf(key, sizeof(key)-1, "SECDESC/%s", lp_servicename(snum));
+       if (tdb_prs_fetch(share_tdb, key, &ps, ctx)!=0 ||
+               !sec_io_desc("get_share_security", &psd, &ps, 1)) {
+               DEBUG(4,("get_share_security: using default secdesc for %s\n", lp_servicename(snum) ));
+               return get_share_security_default(ctx, psize, GENERIC_ALL_ACCESS);
+       }
+
+       if (psd)
+               *psize = sec_desc_size(psd);
+
+       prs_mem_free(&ps);
+       return psd;
+}
+
+/*******************************************************************
+ Store a security descriptor in the share db.
+ ********************************************************************/
+
+BOOL set_share_security(TALLOC_CTX *ctx, const char *share_name, SEC_DESC *psd)
+{
+       prs_struct ps;
+       TALLOC_CTX *mem_ctx = NULL;
+       fstring key;
+       BOOL ret = False;
+
+       if (!share_info_db_init()) {
+               return False;
+       }
+
+       mem_ctx = talloc_init("set_share_security");
+       if (mem_ctx == NULL)
+               return False;
+
+       prs_init(&ps, (uint32)sec_desc_size(psd), mem_ctx, MARSHALL);
+       if (!sec_io_desc("share_security", &psd, &ps, 1))
+               goto out;
+       slprintf(key, sizeof(key)-1, "SECDESC/%s", share_name);
+       if (tdb_prs_store(share_tdb, key, &ps)==0) {
+               ret = True;
+               DEBUG(5,("set_share_security: stored secdesc for %s\n", share_name ));
+       } else {
+               DEBUG(1,("set_share_security: Failed to store secdesc for %s\n", share_name ));
+       } 
+
+       /* Free malloc'ed memory */
+out:
+       prs_mem_free(&ps);
+       if (mem_ctx)
+               talloc_destroy(mem_ctx);
+       return ret;
+}
+
+/*******************************************************************
+ Delete a security descriptor.
+********************************************************************/
+
+BOOL delete_share_security(int snum)
+{
+       TDB_DATA kbuf;
+       fstring key;
+
+       slprintf(key, sizeof(key)-1, "SECDESC/%s", lp_servicename(snum));
+       kbuf.dptr = key;
+       kbuf.dsize = strlen(key)+1;
+
+       if (tdb_delete(share_tdb, kbuf) != 0) {
+               DEBUG(0,("delete_share_security: Failed to delete entry for share %s\n",
+                               lp_servicename(snum) ));
+               return False;
+       }
+
+       return True;
+}
+
+/***************************************************************************
+ Parse the contents of an acl string from a usershare file.
+***************************************************************************/
+
+BOOL parse_usershare_acl(TALLOC_CTX *ctx, const char *acl_str, SEC_DESC **ppsd)
+{
+       size_t s_size = 0;
+       const char *pacl = acl_str;
+       int num_aces = 0;
+       SEC_ACE *ace_list = NULL;
+       SEC_ACL *psa = NULL;
+       SEC_DESC *psd = NULL;
+       size_t sd_size = 0;
+       int i;
+
+       *ppsd = NULL;
+
+       /* If the acl string is blank return "Everyone:R" */
+       if (!*acl_str) {
+               SEC_DESC *default_psd = get_share_security_default(ctx, &s_size, GENERIC_READ_ACCESS);
+               if (!default_psd) {
+                       return False;
+               }
+               *ppsd = default_psd;
+               return True;
+       }
+
+       num_aces = 1;
+
+       /* Add the number of ',' characters to get the number of aces. */
+       num_aces += count_chars(pacl,',');
+
+       ace_list = TALLOC_ARRAY(ctx, SEC_ACE, num_aces);
+       if (!ace_list) {
+               return False;
+       }
+
+       for (i = 0; i < num_aces; i++) {
+               SEC_ACCESS sa;
+               uint32 g_access;
+               uint32 s_access;
+               DOM_SID sid;
+               fstring sidstr;
+               uint8 type = SEC_ACE_TYPE_ACCESS_ALLOWED;
+
+               if (!next_token(&pacl, sidstr, ":", sizeof(sidstr))) {
+                       DEBUG(0,("parse_usershare_acl: malformed usershare acl looking "
+                               "for ':' in string '%s'\n", pacl));
+                       return False;
+               }
+
+               if (!string_to_sid(&sid, sidstr)) {
+                       DEBUG(0,("parse_usershare_acl: failed to convert %s to sid.\n",
+                               sidstr ));
+                       return False;
+               }
+
+               switch (*pacl) {
+                       case 'F': /* Full Control, ie. R+W */
+                       case 'f': /* Full Control, ie. R+W */
+                               s_access = g_access = GENERIC_ALL_ACCESS;
+                               break;
+                       case 'R': /* Read only. */
+                       case 'r': /* Read only. */
+                               s_access = g_access = GENERIC_READ_ACCESS;
+                               break;
+                       case 'D': /* Deny all to this SID. */
+                       case 'd': /* Deny all to this SID. */
+                               type = SEC_ACE_TYPE_ACCESS_DENIED;
+                               s_access = g_access = GENERIC_ALL_ACCESS;
+                               break;
+                       default:
+                               DEBUG(0,("parse_usershare_acl: unknown acl type at %s.\n",
+                                       pacl ));
+                               return False;
+               }
+
+               pacl++;
+               if (*pacl && *pacl != ',') {
+                       DEBUG(0,("parse_usershare_acl: bad acl string at %s.\n",
+                               pacl ));
+                       return False;
+               }
+               pacl++; /* Go past any ',' */
+
+               se_map_generic(&s_access, &file_generic_mapping);
+               init_sec_access(&sa, g_access | s_access );
+               init_sec_ace(&ace_list[i], &sid, type, sa, 0);
+       }
+
+       if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, num_aces, ace_list)) != NULL) {
+               psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, &sd_size);
+       }
+
+       if (!psd) {
+               DEBUG(0,("parse_usershare_acl: Failed to make SEC_DESC.\n"));
+               return False;
+       }
+
+       *ppsd = psd;
+       return True;
+}
index 609816b877424eda44a88d35a5101d2c3e15285a..c045be51c5f63c817f704adf2fefd10e7d7dfe54 100644 (file)
@@ -230,7 +230,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
  Return the list of attribute names from a mapping table
  **********************************************************************/
 
- const char** get_attr_list( ATTRIB_MAP_ENTRY table[] )
+ const char** get_attr_list( TALLOC_CTX *mem_ctx, ATTRIB_MAP_ENTRY table[] )
 {
        const char **names;
        int i = 0;
@@ -239,7 +239,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
                i++;
        i++;
 
-       names = SMB_MALLOC_ARRAY( const char*, i );
+       names = TALLOC_ARRAY( mem_ctx, const char*, i );
        if ( !names ) {
                DEBUG(0,("get_attr_list: out of memory\n"));
                return NULL;
@@ -247,7 +247,7 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
 
        i = 0;
        while ( table[i].attrib != LDAP_ATTR_LIST_END ) {
-               names[i] = SMB_STRDUP( table[i].name );
+               names[i] = talloc_strdup( names, table[i].name );
                i++;
        }
        names[i] = NULL;
@@ -255,29 +255,6 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
        return names;
 }
 
-/*********************************************************************
- Cleanup 
- ********************************************************************/
-
- void free_attr_list( const char **list )
-{
-       int i = 0;
-
-       if ( !list )
-               return; 
-
-       while ( list[i] ) {
-               /* SAFE_FREE generates a warning here that can't be gotten rid
-                * of with CONST_DISCARD */
-               if (list[i] != NULL) {
-                       free(CONST_DISCARD(char *, list[i]));
-               }
-               i+=1;
-       }
-
-       SAFE_FREE( list );
-}
-
 /*******************************************************************
  Search an attribute and return the first value found.
 ******************************************************************/
@@ -321,6 +298,88 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = {
                                            sizeof(pstring));
 }
 
+ char * smbldap_talloc_single_attribute(LDAP *ldap_struct, LDAPMessage *entry,
+                                       const char *attribute,
+                                       TALLOC_CTX *mem_ctx)
+{
+       char **values;
+       char *result;
+
+       if (attribute == NULL) {
+               return NULL;
+       }
+
+       values = ldap_get_values(ldap_struct, entry, attribute);
+
+       if (values == NULL) {
+               DEBUG(10, ("attribute %s does not exist\n", attribute));
+               return NULL;
+       }
+
+       if (ldap_count_values(values) != 1) {
+               DEBUG(10, ("attribute %s has %d values, expected only one\n",
+                          attribute, ldap_count_values(values)));
+               ldap_value_free(values);
+               return NULL;
+       }
+
+       if (pull_utf8_talloc(mem_ctx, &result, values[0]) < 0) {
+               DEBUG(10, ("pull_utf8_talloc failed\n"));
+               ldap_value_free(values);
+               return NULL;
+       }
+
+       ldap_value_free(values);
+
+#ifdef DEBUG_PASSWORDS
+       DEBUG (100, ("smbldap_get_single_attribute: [%s] = [%s]\n",
+                    attribute, result));
+#endif 
+       return result;
+}
+
+ static int ldapmsg_destructor(void *p) {
+       LDAPMessage **result = talloc_get_type_abort(p, LDAPMessage *);
+       ldap_msgfree(*result);
+       return 0;
+}
+
+ void talloc_autofree_ldapmsg(TALLOC_CTX *mem_ctx, LDAPMessage *result)
+{
+       LDAPMessage **handle;
+
+       if (result == NULL) {
+               return;
+       }
+
+       handle = TALLOC_P(mem_ctx, LDAPMessage *);
+       SMB_ASSERT(handle != NULL);
+
+       *handle = result;
+       talloc_set_destructor(handle, ldapmsg_destructor);
+}
+
+ static int ldapmod_destructor(void *p) {
+       LDAPMod ***result = talloc_get_type_abort(p, LDAPMod **);
+       ldap_mods_free(*result, True);
+       return 0;
+}
+
+ void talloc_autofree_ldapmod(TALLOC_CTX *mem_ctx, LDAPMod **mod)
+{
+       LDAPMod ***handle;
+
+       if (mod == NULL) {
+               return;
+       }
+
+       handle = TALLOC_P(mem_ctx, LDAPMod **);
+       SMB_ASSERT(handle != NULL);
+
+       *handle = mod;
+       talloc_set_destructor(handle, ldapmod_destructor);
+}
+
 /************************************************************************
  Routine to manage the LDAPMod structure array
  manage memory used by the array, by each struct, and values
@@ -1041,6 +1100,14 @@ static int another_ldap_try(struct smbldap_state *ldap_state, int *rc,
                        return True;
                }
 
+               if (open_rc == LDAP_INSUFFICIENT_ACCESS) {
+                       /* The fact that we are non-root or any other
+                        * access-denied condition will not change in the next
+                        * round of trying */
+                       *rc = open_rc;
+                       break;
+               }
+
                if (got_alarm) {
                        *rc = LDAP_TIMEOUT;
                        break;
@@ -1123,12 +1190,22 @@ static int smbldap_search_ext(struct smbldap_state *ldap_state,
        alarm(lp_ldap_timeout());
        /* End setup timeout. */
 
-       while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
+       while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) {
                rc = ldap_search_ext_s(ldap_state->ldap_struct, base, scope, 
                                       utf8_filter,
                                       CONST_DISCARD(char **, attrs),
                                       attrsonly, sctrls, cctrls, &timeout,
                                       sizelimit, res);
+               if (rc != LDAP_SUCCESS) {
+                       char *ld_error = NULL;
+                       ldap_get_option(ldap_state->ldap_struct,
+                                       LDAP_OPT_ERROR_STRING, &ld_error);
+                       DEBUG(10,("Failed search for base: %s, error: %s "
+                                 "(%s)\n", base, ldap_err2string(rc),
+                                 ld_error ? ld_error : "unknown"));
+                       SAFE_FREE(ld_error);
+               }
+       }
 
        SAFE_FREE(utf8_filter);
 
@@ -1257,8 +1334,18 @@ int smbldap_modify(struct smbldap_state *ldap_state, const char *dn, LDAPMod *at
                return LDAP_NO_MEMORY;
        }
 
-       while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
+       while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) {
                rc = ldap_modify_s(ldap_state->ldap_struct, utf8_dn, attrs);
+               if (rc != LDAP_SUCCESS) {
+                       char *ld_error = NULL;
+                       ldap_get_option(ldap_state->ldap_struct,
+                                       LDAP_OPT_ERROR_STRING, &ld_error);
+                       DEBUG(10,("Failed to modify dn: %s, error: %s "
+                                 "(%s)\n", dn, ldap_err2string(rc),
+                                 ld_error ? ld_error : "unknown"));
+                       SAFE_FREE(ld_error);
+               }
+       }
                
        SAFE_FREE(utf8_dn);
        return rc;
@@ -1279,8 +1366,18 @@ int smbldap_add(struct smbldap_state *ldap_state, const char *dn, LDAPMod *attrs
                return LDAP_NO_MEMORY;
        }
 
-       while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
+       while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) {
                rc = ldap_add_s(ldap_state->ldap_struct, utf8_dn, attrs);
+               if (rc != LDAP_SUCCESS) {
+                       char *ld_error = NULL;
+                       ldap_get_option(ldap_state->ldap_struct,
+                                       LDAP_OPT_ERROR_STRING, &ld_error);
+                       DEBUG(10,("Failed to add dn: %s, error: %s "
+                                 "(%s)\n", dn, ldap_err2string(rc),
+                                 ld_error ? ld_error : "unknown"));
+                       SAFE_FREE(ld_error);
+               }
+       }
        
        SAFE_FREE(utf8_dn);
        return rc;
@@ -1301,8 +1398,18 @@ int smbldap_delete(struct smbldap_state *ldap_state, const char *dn)
                return LDAP_NO_MEMORY;
        }
 
-       while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
+       while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) {
                rc = ldap_delete_s(ldap_state->ldap_struct, utf8_dn);
+               if (rc != LDAP_SUCCESS) {
+                       char *ld_error = NULL;
+                       ldap_get_option(ldap_state->ldap_struct,
+                                       LDAP_OPT_ERROR_STRING, &ld_error);
+                       DEBUG(10,("Failed to delete dn: %s, error: %s "
+                                 "(%s)\n", dn, ldap_err2string(rc),
+                                 ld_error ? ld_error : "unknown"));
+                       SAFE_FREE(ld_error);
+               }
+       }
        
        SAFE_FREE(utf8_dn);
        return rc;
@@ -1320,34 +1427,33 @@ int smbldap_extended_operation(struct smbldap_state *ldap_state,
        if (!ldap_state)
                return (-1);
 
-       while (another_ldap_try(ldap_state, &rc, &attempts, endtime))
+       while (another_ldap_try(ldap_state, &rc, &attempts, endtime)) {
                rc = ldap_extended_operation_s(ldap_state->ldap_struct, reqoid,
                                               reqdata, serverctrls,
                                               clientctrls, retoidp, retdatap);
+               if (rc != LDAP_SUCCESS) {
+                       char *ld_error = NULL;
+                       ldap_get_option(ldap_state->ldap_struct,
+                                       LDAP_OPT_ERROR_STRING, &ld_error);
+                       DEBUG(10,("Extended operation failed with error: %s "
+                                 "(%s)\n", ldap_err2string(rc),
+                                 ld_error ? ld_error : "unknown"));
+                       SAFE_FREE(ld_error);
+               }
+       }
+               
        return rc;
 }
 
 /*******************************************************************
  run the search by name.
 ******************************************************************/
-int smbldap_search_suffix (struct smbldap_state *ldap_state, const char *filter, 
-                          const char **search_attr, LDAPMessage ** result)
+int smbldap_search_suffix (struct smbldap_state *ldap_state,
+                          const char *filter, const char **search_attr,
+                          LDAPMessage ** result)
 {
-       int scope = LDAP_SCOPE_SUBTREE;
-       int rc;
-
-       rc = smbldap_search(ldap_state, lp_ldap_suffix(), scope, filter, search_attr, 0, result);
-
-       if (rc != LDAP_SUCCESS) {
-               char *ld_error = NULL;
-               ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
-                               &ld_error);
-               DEBUG(0,("smbldap_search_suffix: Problem during the LDAP search: %s (%s)\n", 
-                       ld_error?ld_error:"(unknown)", ldap_err2string (rc)));
-               SAFE_FREE(ld_error);
-       }
-       
-       return rc;
+       return smbldap_search(ldap_state, lp_ldap_suffix(), LDAP_SCOPE_SUBTREE,
+                             filter, search_attr, 0, result);
 }
 
 static void smbldap_idle_fn(void **data, time_t *interval, time_t now)
@@ -1442,6 +1548,25 @@ char *smbldap_get_dn(LDAP *ld, LDAPMessage *entry)
        return unix_dn;
 }
 
+ const char *smbldap_talloc_dn(TALLOC_CTX *mem_ctx, LDAP *ld,
+                              LDAPMessage *entry)
+{
+       char *utf8_dn, *unix_dn;
+
+       utf8_dn = ldap_get_dn(ld, entry);
+       if (!utf8_dn) {
+               DEBUG (5, ("smbldap_get_dn: ldap_get_dn failed\n"));
+               return NULL;
+       }
+       if (pull_utf8_talloc(mem_ctx, &unix_dn, utf8_dn) == (size_t)-1) {
+               DEBUG (0, ("smbldap_get_dn: String conversion failure utf8 "
+                          "[%s]\n", utf8_dn));
+               return NULL;
+       }
+       ldap_memfree(utf8_dn);
+       return unix_dn;
+}
+
 /*******************************************************************
  Check if root-dse has a certain Control or Extension
 ********************************************************************/
index 4679b864874a01115d5eb92f257691c5afd9bdc6..7b4cf4d079f8ffa6e636091d533892dc5a16202a 100644 (file)
@@ -99,21 +99,17 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
        pstring filter, dn;
        LDAPMod **mods = NULL;
        int rc;
-       int ldap_op;
        LDAPMessage *result = NULL;
        int num_result;
        const char **attr_list;
-       uid_t u_low, u_high;
-       gid_t g_low, g_high;
-       uint32 rid_low, rid_high;
 
        slprintf (filter, sizeof (filter) - 1, "(&(%s=%s)(objectclass=%s))", 
                  get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), 
                  domain_name, LDAP_OBJ_DOMINFO);
 
-       attr_list = get_attr_list( dominfo_attr_list );
+       attr_list = get_attr_list( NULL, dominfo_attr_list );
        rc = smbldap_search_suffix(ldap_state, filter, attr_list, &result);
-       free_attr_list( attr_list );
+       talloc_free( attr_list );
 
        if (rc != LDAP_SUCCESS) {
                return NT_STATUS_UNSUCCESSFUL;
@@ -122,80 +118,72 @@ static NTSTATUS add_new_domain_info(struct smbldap_state *ldap_state,
        num_result = ldap_count_entries(ldap_state->ldap_struct, result);
        
        if (num_result > 1) {
-               DEBUG (0, ("More than domain with that name exists: bailing out!\n"));
+               DEBUG (0, ("More than domain with that name exists: bailing "
+                          "out!\n"));
                ldap_msgfree(result);
                return NT_STATUS_UNSUCCESSFUL;
        }
        
        /* Check if we need to add an entry */
        DEBUG(3,("Adding new domain\n"));
-       ldap_op = LDAP_MOD_ADD;
 
-       pstr_sprintf(dn, "%s=%s,%s", get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
-               domain_name, lp_ldap_suffix());
+       pstr_sprintf(dn, "%s=%s,%s",
+                    get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN),
+                    domain_name, lp_ldap_suffix());
 
        /* Free original search */
        ldap_msgfree(result);
 
-       /* make the changes - the entry *must* not already have samba attributes */
-       smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), 
-               domain_name);
+       /* make the changes - the entry *must* not already have samba
+        * attributes */
 
-       /* If we don't have an entry, then ask secrets.tdb for what it thinks.  
+       smbldap_set_mod(&mods, LDAP_MOD_ADD,
+                       get_attr_key2string(dominfo_attr_list,
+                                           LDAP_ATTR_DOMAIN), 
+                       domain_name);
+
+       /* If we don't have an entry, then ask secrets.tdb for what it thinks.
           It may choose to make it up */
 
        sid_to_string(sid_string, get_global_sam_sid());
-       smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID), sid_string);
-
-       slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string) - 1, "%i", algorithmic_rid_base());
-       smbldap_set_mod(&mods, LDAP_MOD_ADD, get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE), 
+       smbldap_set_mod(&mods, LDAP_MOD_ADD,
+                       get_attr_key2string(dominfo_attr_list,
+                                           LDAP_ATTR_DOM_SID),
+                       sid_string);
+
+       slprintf(algorithmic_rid_base_string,
+                sizeof(algorithmic_rid_base_string) - 1, "%i",
+                algorithmic_rid_base());
+       smbldap_set_mod(&mods, LDAP_MOD_ADD,
+                       get_attr_key2string(dominfo_attr_list,
+                                           LDAP_ATTR_ALGORITHMIC_RID_BASE), 
                        algorithmic_rid_base_string);
        smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectclass", LDAP_OBJ_DOMINFO);
        
-       /* add the sambaNext[User|Group]Rid attributes if the idmap ranges are set.
-          TODO: fix all the places where the line between idmap and normal operations
-          needed by smbd gets fuzzy   --jerry 2003-08-11                              */
+       /* add the sambaNextUserRid attributes. */
        
-       if ( lp_idmap_uid(&u_low, &u_high) && lp_idmap_gid(&g_low, &g_high)
-               && get_free_rid_range(&rid_low, &rid_high) ) 
        {
+               uint32 rid = BASE_RID;
                fstring rid_str;
                
-               fstr_sprintf( rid_str, "%i", rid_high|USER_RID_TYPE );
+               fstr_sprintf( rid_str, "%i", rid );
                DEBUG(10,("setting next available user rid [%s]\n", rid_str));
                smbldap_set_mod(&mods, LDAP_MOD_ADD, 
-                       get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), 
-                       rid_str);
-                       
-               fstr_sprintf( rid_str, "%i", rid_high|GROUP_RID_TYPE );
-               DEBUG(10,("setting next available group rid [%s]\n", rid_str));
-               smbldap_set_mod(&mods, LDAP_MOD_ADD, 
-                       get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID), 
+                       get_attr_key2string(dominfo_attr_list,
+                                           LDAP_ATTR_NEXT_USERRID), 
                        rid_str);
-               
         }
 
 
-       switch(ldap_op)
-       {
-       case LDAP_MOD_ADD: 
-               rc = smbldap_add(ldap_state, dn, mods);
-               break;
-       case LDAP_MOD_REPLACE: 
-               rc = smbldap_modify(ldap_state, dn, mods);
-               break;
-       default:        
-               DEBUG(0,("Wrong LDAP operation type: %d!\n", ldap_op));
-               return NT_STATUS_INVALID_PARAMETER;
-       }
-       
+       rc = smbldap_add(ldap_state, dn, mods);
+
        if (rc!=LDAP_SUCCESS) {
                char *ld_error = NULL;
-               ldap_get_option(ldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
-               DEBUG(1,("failed to %s domain dn= %s with: %s\n\t%s\n",
-                      ldap_op == LDAP_MOD_ADD ? "add" : "modify",
-                      dn, ldap_err2string(rc),
-                      ld_error?ld_error:"unknown"));
+               ldap_get_option(ldap_state->ldap_struct,
+                               LDAP_OPT_ERROR_STRING, &ld_error);
+               DEBUG(1,("failed to add domain dn= %s with: %s\n\t%s\n",
+                        dn, ldap_err2string(rc),
+                        ld_error?ld_error:"unknown"));
                SAFE_FREE(ld_error);
 
                ldap_mods_free(mods, True);
@@ -227,9 +215,9 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state,
 
        DEBUG(2, ("Searching for:[%s]\n", filter));
 
-       attr_list = get_attr_list( dominfo_attr_list );
+       attr_list = get_attr_list( NULL, dominfo_attr_list );
        rc = smbldap_search_suffix(ldap_state, filter, attr_list , result);
-       free_attr_list( attr_list );
+       talloc_free( attr_list );
 
        if (rc != LDAP_SUCCESS) {
                DEBUG(2,("Problem during LDAPsearch: %s\n", ldap_err2string (rc)));
index 6c65f61ad7a0db0493c9074971647c4af2f7c5f3..1d4f88fbb96cd81698ae69faddb677c7e1445d07 100644 (file)
 
 #ifndef HAVE_GETGROUPLIST
 
-static int int_compare( int *a, int *b )
-{
-       if ( *a == *b )
-               return 0;
-       else if ( *a < *b )
-               return -1;
-       else
-               return 1;
-}
-
-void remove_duplicate_gids( int *num_groups, gid_t *groups )
-{
-       int i;
-       int count = *num_groups;
-
-       if ( *num_groups <= 0 || !groups )
-               return;
-
-       DEBUG(8,("remove_duplicate_gids: Enter %d gids\n", *num_groups));
-
-       qsort( groups, *num_groups, sizeof(gid_t), QSORT_CAST int_compare );
-
-       for ( i=1; i<count; ) {
-               if ( groups[i-1] == groups[i] ) {
-                       memmove( &groups[i-1], &groups[i], (count - i + 1)*sizeof(gid_t) );
-
-                       /* decrement the total number of groups and do not increment
-                          the loop counter */
-                       count--;
-                       continue;
-               }
-               i++;
-       }
-
-       *num_groups = count;
-
-       DEBUG(8,("remove_duplicate_gids: Exit %d gids\n", *num_groups));
-
-       return;
-}
-
 /*
   This is a *much* faster way of getting the list of groups for a user
   without changing the current supplementary group list. The old
@@ -79,7 +38,8 @@ void remove_duplicate_gids( int *num_groups, gid_t *groups )
   NOTE!! this function only works if it is called as root!
   */
 
-static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, int *grpcnt)
+static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups,
+                                 int *grpcnt)
 {
        gid_t *gids_saved;
        int ret, ngrp_saved, num_gids;
@@ -140,9 +100,6 @@ static int getgrouplist_internals(const char *user, gid_t gid, gid_t *groups, in
                }
                groups[0] = gid;
                *grpcnt = ret + 1;
-
-               /* remove any duplicates gids in the list */
-               remove_duplicate_gids( grpcnt, groups );
        }
 
        restore_re_gid();
@@ -169,11 +126,11 @@ static int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grp
        /* see if we should disable winbindd lookups for local users */
        if (strchr(user, *lp_winbind_separator()) == NULL) {
                if ( !winbind_off() )
-                       DEBUG(0,("sys_getgroup_list: Insufficient environment space for %s\n",
-                               WINBINDD_DONT_ENV));
+                       DEBUG(0,("sys_getgroup_list: Insufficient environment space "
+                                "for %s\n", WINBINDD_DONT_ENV));
                else
-                       DEBUG(10,("sys_getgrouplist(): disabled winbindd for group lookup [user == %s]\n",
-                               user));
+                       DEBUG(10,("sys_getgrouplist(): disabled winbindd for group "
+                                 "lookup [user == %s]\n", user));
        }
 
 #ifdef HAVE_GETGROUPLIST
@@ -190,8 +147,9 @@ static int sys_getgrouplist(const char *user, gid_t gid, gid_t *groups, int *grp
        return retval;
 }
 
-static BOOL getgroups_user(const char *user, gid_t primary_gid,
-                          gid_t **ret_groups, size_t *p_ngroups)
+BOOL getgroups_unix_user(TALLOC_CTX *mem_ctx, const char *user,
+                        gid_t primary_gid,
+                        gid_t **ret_groups, size_t *p_ngroups)
 {
        size_t ngrp;
        int max_grp;
@@ -229,10 +187,11 @@ static BOOL getgroups_user(const char *user, gid_t primary_gid,
        groups = NULL;
 
        /* Add in primary group first */
-       add_gid_to_array_unique(NULL, primary_gid, &groups, &ngrp);
+       add_gid_to_array_unique(mem_ctx, primary_gid, &groups, &ngrp);
 
        for (i=0; i<max_grp; i++)
-               add_gid_to_array_unique(NULL, temp_groups[i], &groups, &ngrp);
+               add_gid_to_array_unique(mem_ctx, temp_groups[i],
+                                       &groups, &ngrp);
 
        *p_ngroups = ngrp;
        *ret_groups = groups;
@@ -241,15 +200,22 @@ static BOOL getgroups_user(const char *user, gid_t primary_gid,
 }
 
 NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods,
-                                           const char *username,
-                                           gid_t primary_gid,
+                                           TALLOC_CTX *mem_ctx,
+                                           SAM_ACCOUNT *user,
                                            DOM_SID **pp_sids,
                                            gid_t **pp_gids,
                                            size_t *p_num_groups)
 {
        size_t i;
+       gid_t gid;
+
+       if (!sid_to_gid(pdb_get_group_sid(user), &gid)) {
+               DEBUG(10, ("sid_to_gid failed\n"));
+               return NT_STATUS_NO_SUCH_USER;
+       }
 
-       if (!getgroups_user(username, primary_gid, pp_gids, p_num_groups)) {
+       if (!getgroups_unix_user(mem_ctx, pdb_get_username(user), gid,
+                                pp_gids, p_num_groups)) {
                return NT_STATUS_NO_SUCH_USER;
        }
 
@@ -257,22 +223,15 @@ NTSTATUS pdb_default_enum_group_memberships(struct pdb_methods *methods,
                smb_panic("primary group missing");
        }
 
-       *pp_sids = SMB_MALLOC_ARRAY(DOM_SID, *p_num_groups);
+       *pp_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *p_num_groups);
 
        if (*pp_sids == NULL) {
-               SAFE_FREE(pp_gids);
+               talloc_free(*pp_gids);
                return NT_STATUS_NO_MEMORY;
        }
 
        for (i=0; i<*p_num_groups; i++) {
-               if (!NT_STATUS_IS_OK(gid_to_sid(&(*pp_sids)[i], (*pp_gids)[i]))) {
-                       DEBUG(1, ("get_user_groups: failed to convert "
-                                 "gid %ld to a sid!\n", 
-                                 (long int)(*pp_gids)[i+1]));
-                       SAFE_FREE(*pp_sids);
-                       SAFE_FREE(*pp_gids);
-                       return NT_STATUS_NO_SUCH_USER;
-               }
+               gid_to_sid(&(*pp_sids)[i], (*pp_gids)[i]);
        }
 
        return NT_STATUS_OK;
index 7d66b320adf8d61abd2aefdddd2b056bc1ba8ffe..c04dfd05da10ba05fca94ff264f190b6be1d3234 100644 (file)
 #include "includes.h"
 
 /* internal functions */
-static struct passwd *uname_string_combinations(char *s, struct passwd * (*fn) (const char *), int N);
-static struct passwd *uname_string_combinations2(char *s, int offset, struct passwd * (*fn) (const char *), int N);
+static struct passwd *uname_string_combinations(char *s, TALLOC_CTX *mem_ctx,
+                                               struct passwd * (*fn) (TALLOC_CTX *mem_ctx, const char *),
+                                               int N);
+static struct passwd *uname_string_combinations2(char *s, TALLOC_CTX *mem_ctx, int offset,
+                                                struct passwd * (*fn) (TALLOC_CTX *mem_ctx, const char *),
+                                                int N);
 
 /*****************************************************************
  Check if a user or group name is local (this is a *local* name for
@@ -108,7 +112,7 @@ BOOL map_username(fstring user)
                }
 
                numlines = 0;
-               qlines = fd_lines_load(fd, &numlines);
+               qlines = fd_lines_load(fd, &numlines,0);
                DEBUGADD(10,("Lines returned = [%d]\n", numlines));
                close(fd);
 
@@ -180,7 +184,8 @@ BOOL map_username(fstring user)
                        return False;
                }
 
-               if (strchr_m(dosname,'*') || user_in_list(user, (const char **)dosuserlist, NULL, 0)) {
+               if (strchr_m(dosname,'*') ||
+                   user_in_list(user, (const char **)dosuserlist)) {
                        DEBUG(3,("Mapped user %s to %s\n",user,unixname));
                        mapped_user = True;
                        fstrcpy( last_from,user );
@@ -218,7 +223,8 @@ BOOL map_username(fstring user)
 
 static struct passwd *Get_Pwnam_ret = NULL;
 
-static struct passwd *Get_Pwnam_internals(const char *user, char *user2)
+static struct passwd *Get_Pwnam_internals(TALLOC_CTX *mem_ctx,
+                                         const char *user, char *user2)
 {
        struct passwd *ret = NULL;
 
@@ -232,7 +238,7 @@ static struct passwd *Get_Pwnam_internals(const char *user, char *user2)
           common case on UNIX systems */
        strlower_m(user2);
        DEBUG(5,("Trying _Get_Pwnam(), username as lowercase is %s\n",user2));
-       ret = getpwnam_alloc(user2);
+       ret = getpwnam_alloc(mem_ctx, user2);
        if(ret)
                goto done;
 
@@ -240,7 +246,7 @@ static struct passwd *Get_Pwnam_internals(const char *user, char *user2)
        if(strcmp(user, user2) != 0) {
                DEBUG(5,("Trying _Get_Pwnam(), username as given is %s\n",
                         user));
-               ret = getpwnam_alloc(user);
+               ret = getpwnam_alloc(mem_ctx, user);
                if(ret)
                        goto done;
        }
@@ -250,7 +256,7 @@ static struct passwd *Get_Pwnam_internals(const char *user, char *user2)
        if(strcmp(user, user2) != 0) {
                DEBUG(5,("Trying _Get_Pwnam(), username as uppercase is %s\n",
                         user2));
-               ret = getpwnam_alloc(user2);
+               ret = getpwnam_alloc(mem_ctx, user2);
                if(ret)
                        goto done;
        }
@@ -259,7 +265,7 @@ static struct passwd *Get_Pwnam_internals(const char *user, char *user2)
        strlower_m(user2);
        DEBUG(5,("Checking combinations of %d uppercase letters in %s\n",
                 lp_usernamelevel(), user2));
-       ret = uname_string_combinations(user2, getpwnam_alloc,
+       ret = uname_string_combinations(user2, mem_ctx, getpwnam_alloc,
                                        lp_usernamelevel());
 
 done:
@@ -275,7 +281,7 @@ done:
   This will return an allocated structure
 ****************************************************************************/
 
-struct passwd *Get_Pwnam_alloc(const char *user)
+struct passwd *Get_Pwnam_alloc(TALLOC_CTX *mem_ctx, const char *user)
 {
        fstring user2;
        struct passwd *ret;
@@ -289,7 +295,7 @@ struct passwd *Get_Pwnam_alloc(const char *user)
 
        DEBUG(5,("Finding user %s\n", user));
 
-       ret = Get_Pwnam_internals(user, user2);
+       ret = Get_Pwnam_internals(mem_ctx, user, user2);
        
        return ret;  
 }
@@ -303,7 +309,7 @@ struct passwd *Get_Pwnam(const char *user)
 {
        struct passwd *ret;
 
-       ret = Get_Pwnam_alloc(user);
+       ret = Get_Pwnam_alloc(NULL, user);
        
        /* This call used to just return the 'passwd' static buffer.
           This could then have accidental reuse implications, so 
@@ -320,7 +326,7 @@ struct passwd *Get_Pwnam(const char *user)
        */
 
        if (Get_Pwnam_ret) {
-               passwd_free(&Get_Pwnam_ret);
+               talloc_free(Get_Pwnam_ret);
        }
        
        Get_Pwnam_ret = ret;
@@ -333,7 +339,7 @@ struct passwd *Get_Pwnam(const char *user)
  try lower case.
 ****************************************************************************/
 
-static BOOL user_in_netgroup_list(const char *user, const char *ngname)
+BOOL user_in_netgroup(const char *user, const char *ngname)
 {
 #ifdef HAVE_NETGROUP
        static char *mydomain = NULL;
@@ -351,7 +357,7 @@ static BOOL user_in_netgroup_list(const char *user, const char *ngname)
                user, mydomain, ngname));
 
        if (innetgr(ngname, NULL, user, mydomain)) {
-               DEBUG(5,("user_in_netgroup_list: Found\n"));
+               DEBUG(5,("user_in_netgroup: Found\n"));
                return (True);
        } else {
 
@@ -367,7 +373,7 @@ static BOOL user_in_netgroup_list(const char *user, const char *ngname)
                        lowercase_user, mydomain, ngname));
 
                if (innetgr(ngname, NULL, lowercase_user, mydomain)) {
-                       DEBUG(5,("user_in_netgroup_list: Found\n"));
+                       DEBUG(5,("user_in_netgroup: Found\n"));
                        return (True);
                }
        }
@@ -379,8 +385,8 @@ static BOOL user_in_netgroup_list(const char *user, const char *ngname)
  Check if a user is in a winbind group.
 ****************************************************************************/
   
-static BOOL user_in_winbind_group_list(const char *user, const char *gname,
-                                      BOOL *winbind_answered)
+static BOOL user_in_winbind_group(const char *user, const char *gname,
+                                 BOOL *winbind_answered)
 {
        int i;
        gid_t gid, gid_low, gid_high;
@@ -392,7 +398,7 @@ static BOOL user_in_winbind_group_list(const char *user, const char *gname,
        *winbind_answered = False;
  
        if ((gid = nametogid(gname)) == (gid_t)-1) {
-               DEBUG(0,("user_in_winbind_group_list: nametogid for group %s "
+               DEBUG(0,("user_in_winbind_group: nametogid for group %s "
                         "failed.\n", gname ));
                goto err;
        }
@@ -439,11 +445,11 @@ static BOOL user_in_winbind_group_list(const char *user, const char *gname,
                
        }
        else 
-               DEBUG(10,("user_in_winbind_group_list: using cached user "
+               DEBUG(10,("user_in_winbind_group: using cached user "
                          "groups for [%s]\n", user));
  
        if ( DEBUGLEVEL >= 10 ) {
-               DEBUG(10,("user_in_winbind_group_list: using groups -- "));
+               DEBUG(10,("user_in_winbind_group: using groups -- "));
                for ( i=0; i<num_groups; i++ )
                        DEBUGADD(10,("%lu ", (unsigned long)groups[i]));
                DEBUGADD(10,("\n"));    
@@ -477,13 +483,13 @@ static BOOL user_in_winbind_group_list(const char *user, const char *gname,
  Check if a user is in a UNIX group.
 ****************************************************************************/
 
-BOOL user_in_unix_group_list(const char *user,const char *gname)
+BOOL user_in_unix_group(const char *user,const char *gname)
 {
        struct passwd *pass = Get_Pwnam(user);
        struct sys_userlist *user_list;
        struct sys_userlist *member;
 
-       DEBUG(10,("user_in_unix_group_list: checking user %s in group %s\n",
+       DEBUG(10,("user_in_unix_group: checking user %s in group %s\n",
                  user, gname));
 
        /*
@@ -493,7 +499,7 @@ BOOL user_in_unix_group_list(const char *user,const char *gname)
  
        if (pass) {
                if (strequal(gname,gidtoname(pass->pw_gid))) {
-                       DEBUG(10,("user_in_unix_group_list: group %s is "
+                       DEBUG(10,("user_in_unix_group: group %s is "
                                  "primary group.\n", gname ));
                        return True;
                }
@@ -501,13 +507,13 @@ BOOL user_in_unix_group_list(const char *user,const char *gname)
  
        user_list = get_users_in_group(gname);
        if (user_list == NULL) {
-               DEBUG(10,("user_in_unix_group_list: no such group %s\n",
+               DEBUG(10,("user_in_unix_group: no such group %s\n",
                          gname ));
                return False;
        }
 
        for (member = user_list; member; member = member->next) {
-               DEBUG(10,("user_in_unix_group_list: checking user %s against "
+               DEBUG(10,("user_in_unix_group: checking user %s against "
                          "member %s\n", user, member->unix_name ));
                if (strequal(member->unix_name,user)) {
                        free_userlist(user_list);
@@ -523,35 +529,17 @@ BOOL user_in_unix_group_list(const char *user,const char *gname)
  Check if a user is in a group list. Ask winbind first, then use UNIX.
 ****************************************************************************/
 
-BOOL user_in_group_list(const char *user, const char *gname, gid_t *groups,
-                       size_t n_groups)
+BOOL user_in_group(const char *user, const char *gname)
 {
        BOOL winbind_answered = False;
        BOOL ret;
-       gid_t gid;
-       unsigned i;
 
-       gid = nametogid(gname);
-       if (gid == (gid_t)-1) 
-               return False;
-
-       if (groups && n_groups > 0) {
-               for (i=0; i < n_groups; i++) {
-                       if (groups[i] == gid) {
-                               return True;
-                       }
-               }
-               return False;
-       }
-
-       /* fallback if we don't yet have the group list */
-
-       ret = user_in_winbind_group_list(user, gname, &winbind_answered);
+       ret = user_in_winbind_group(user, gname, &winbind_answered);
        if (!winbind_answered)
-               ret = user_in_unix_group_list(user, gname);
+               ret = user_in_unix_group(user, gname);
 
        if (ret)
-               DEBUG(10,("user_in_group_list: user |%s| is in group |%s|\n",
+               DEBUG(10,("user_in_group: user |%s| is in group |%s|\n",
                          user, gname));
        return ret;
 }
@@ -561,8 +549,7 @@ BOOL user_in_group_list(const char *user, const char *gname, gid_t *groups,
  and netgroup lists.
 ****************************************************************************/
 
-BOOL user_in_list(const char *user,const char **list, gid_t *groups,
-                 size_t n_groups)
+BOOL user_in_list(const char *user,const char **list)
 {
        if (!list || !*list)
                return False;
@@ -590,10 +577,9 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups,
                         * Old behaviour. Check netgroup list
                         * followed by UNIX list.
                         */
-                       if(user_in_netgroup_list(user, *list +1))
+                       if(user_in_netgroup(user, *list +1))
                                return True;
-                       if(user_in_group_list(user, *list +1, groups,
-                                             n_groups))
+                       if(user_in_group(user, *list +1))
                                return True;
                } else if (**list == '+') {
 
@@ -601,10 +587,9 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups,
                                /*
                                 * Search UNIX list followed by netgroup.
                                 */
-                               if(user_in_group_list(user, *list +2, groups,
-                                                     n_groups))
+                               if(user_in_group(user, *list +2))
                                        return True;
-                               if(user_in_netgroup_list(user, *list +2))
+                               if(user_in_netgroup(user, *list +2))
                                        return True;
 
                        } else {
@@ -613,8 +598,7 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups,
                                 * Just search UNIX list.
                                 */
 
-                               if(user_in_group_list(user, *list +1, groups,
-                                                     n_groups))
+                               if(user_in_group(user, *list +1))
                                        return True;
                        }
 
@@ -624,16 +608,15 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups,
                                /*
                                 * Search netgroup list followed by UNIX list.
                                 */
-                               if(user_in_netgroup_list(user, *list +2))
+                               if(user_in_netgroup(user, *list +2))
                                        return True;
-                               if(user_in_group_list(user, *list +2, groups,
-                                                     n_groups))
+                               if(user_in_group(user, *list +2))
                                        return True;
                        } else {
                                /*
                                 * Just search netgroup list.
                                 */
-                               if(user_in_netgroup_list(user, *list +1))
+                               if(user_in_netgroup(user, *list +1))
                                        return True;
                        }
                } else if (!name_is_local(*list)) {
@@ -676,7 +659,7 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups,
                                        
                                        /* Check if user name is in the
                                         * Windows group */
-                                       ret = user_in_winbind_group_list(
+                                       ret = user_in_winbind_group(
                                                user, *list,
                                                &winbind_answered);
                                        
@@ -705,21 +688,24 @@ BOOL user_in_list(const char *user,const char **list, gid_t *groups,
  it assumes the string starts lowercased
 ****************************************************************************/
 
-static struct passwd *uname_string_combinations2(char *s,int offset,struct passwd *(*fn)(const char *),int N)
+static struct passwd *uname_string_combinations2(char *s, TALLOC_CTX *mem_ctx,
+                                                int offset,
+                                                struct passwd *(*fn)(TALLOC_CTX *mem_ctx, const char *),
+                                                int N)
 {
        ssize_t len = (ssize_t)strlen(s);
        int i;
        struct passwd *ret;
 
        if (N <= 0 || offset >= len)
-               return(fn(s));
+               return(fn(mem_ctx, s));
 
        for (i=offset;i<(len-(N-1));i++) {
                char c = s[i];
                if (!islower_ascii((int)c))
                        continue;
                s[i] = toupper_ascii(c);
-               ret = uname_string_combinations2(s,i+1,fn,N-1);
+               ret = uname_string_combinations2(s, mem_ctx, i+1, fn, N-1);
                if(ret)
                        return(ret);
                s[i] = c;
@@ -735,13 +721,15 @@ static struct passwd *uname_string_combinations2(char *s,int offset,struct passw
  it assumes the string starts lowercased
 ****************************************************************************/
 
-static struct passwd * uname_string_combinations(char *s,struct passwd * (*fn)(const char *),int N)
+static struct passwd * uname_string_combinations(char *s, TALLOC_CTX *mem_ctx,
+                                                struct passwd * (*fn)(TALLOC_CTX *mem_ctx, const char *),
+                                                int N)
 {
        int n;
        struct passwd *ret;
 
        for (n=1;n<=N;n++) {
-               ret = uname_string_combinations2(s,0,fn,n);
+               ret = uname_string_combinations2(s,mem_ctx,0,fn,n);
                if(ret)
                        return(ret);
        }  
index 38878befc776e4454c3c54b660d6c1986045cdfd..dc57839df3415e1f5be5196dc94725d8fd6d3b69 100644 (file)
@@ -1427,10 +1427,10 @@ const char *uidtoname(uid_t uid)
        static fstring name;
        struct passwd *pass;
 
-       pass = getpwuid_alloc(uid);
+       pass = getpwuid_alloc(NULL, uid);
        if (pass) {
                fstrcpy(name, pass->pw_name);
-               passwd_free(&pass);
+               talloc_free(pass);
        } else {
                slprintf(name, sizeof(name) - 1, "%ld",(long int)uid);
        }
@@ -1464,10 +1464,10 @@ uid_t nametouid(const char *name)
        char *p;
        uid_t u;
 
-       pass = getpwnam_alloc(name);
+       pass = getpwnam_alloc(NULL, name);
        if (pass) {
                u = pass->pw_uid;
-               passwd_free(&pass);
+               talloc_free(pass);
                return u;
        }
 
index 407a8b24fc97381c33502cd72c76c24dfa5a6dca..53a9bc9b417a704221237ac19b86044147bf3f2b 100644 (file)
@@ -386,30 +386,37 @@ char *file_pload(char *syscmd, size_t *size)
 
 /****************************************************************************
  Load a file into memory from a fd.
+ Truncate at maxsize. If maxsize == 0 - no limit.
 ****************************************************************************/ 
 
-char *fd_load(int fd, size_t *size)
+char *fd_load(int fd, size_t *psize, size_t maxsize)
 {
        SMB_STRUCT_STAT sbuf;
+       size_t size;
        char *p;
 
        if (sys_fstat(fd, &sbuf) != 0) {
                return NULL;
        }
 
-       p = (char *)SMB_MALLOC(sbuf.st_size+1);
+       size = sbuf.st_size;
+       if (maxsize) {
+               size = MIN(size, maxsize);
+       }
+
+       p = (char *)SMB_MALLOC(size+1);
        if (!p) {
                return NULL;
        }
 
-       if (read(fd, p, sbuf.st_size) != sbuf.st_size) {
+       if (read(fd, p, size) != size) {
                SAFE_FREE(p);
                return NULL;
        }
-       p[sbuf.st_size] = 0;
+       p[size] = 0;
 
-       if (size) {
-               *size = sbuf.st_size;
+       if (psize) {
+               *psize = size;
        }
 
        return p;
@@ -419,7 +426,7 @@ char *fd_load(int fd, size_t *size)
  Load a file into memory.
 ****************************************************************************/
 
-char *file_load(const char *fname, size_t *size)
+char *file_load(const char *fname, size_t *size, size_t maxsize)
 {
        int fd;
        char *p;
@@ -433,7 +440,7 @@ char *file_load(const char *fname, size_t *size)
                return NULL;
        }
 
-       p = fd_load(fd, size);
+       p = fd_load(fd, size, maxsize);
        close(fd);
        return p;
 }
@@ -461,7 +468,7 @@ void *map_file(char *fname, size_t size)
        }
 #endif
        if (!p) {
-               p = file_load(fname, &s2);
+               p = file_load(fname, &s2, 0);
                if (!p) {
                        return NULL;
                }
@@ -522,12 +529,12 @@ static char **file_lines_parse(char *p, size_t size, int *numlines)
  must be freed with file_lines_free(). 
 ****************************************************************************/
 
-char **file_lines_load(const char *fname, int *numlines)
+char **file_lines_load(const char *fname, int *numlines, size_t maxsize)
 {
        char *p;
        size_t size = 0;
 
-       p = file_load(fname, &size);
+       p = file_load(fname, &size, maxsize);
        if (!p) {
                return NULL;
        }
@@ -541,12 +548,12 @@ char **file_lines_load(const char *fname, int *numlines)
  the list.
 ****************************************************************************/
 
-char **fd_lines_load(int fd, int *numlines)
+char **fd_lines_load(int fd, int *numlines, size_t maxsize)
 {
        char *p;
        size_t size;
 
-       p = fd_load(fd, &size);
+       p = fd_load(fd, &size, maxsize);
        if (!p) {
                return NULL;
        }
index 13349bad34e256684fc6d2b60e2e795859ca466a..e026affb44768df85da11602a24fa31ad5dee06c 100644 (file)
 
 #include "includes.h"
 
-static struct passwd *alloc_copy_passwd(const struct passwd *from) 
+static struct passwd *talloc_copy_passwd(TALLOC_CTX *mem_ctx,
+                                        const struct passwd *from) 
 {
-       struct passwd *ret = SMB_XMALLOC_P(struct passwd);
-       ZERO_STRUCTP(ret);
-       ret->pw_name = smb_xstrdup(from->pw_name);
-       ret->pw_passwd = smb_xstrdup(from->pw_passwd);
+       struct passwd *ret = TALLOC_P(mem_ctx, struct passwd);
+       ret->pw_name = talloc_strdup(ret, from->pw_name);
+       ret->pw_passwd = talloc_strdup(ret, from->pw_passwd);
        ret->pw_uid = from->pw_uid;
        ret->pw_gid = from->pw_gid;
-       ret->pw_gecos = smb_xstrdup(from->pw_gecos);
-       ret->pw_dir = smb_xstrdup(from->pw_dir);
-       ret->pw_shell = smb_xstrdup(from->pw_shell);
+       ret->pw_gecos = talloc_strdup(ret, from->pw_gecos);
+       ret->pw_dir = talloc_strdup(ret, from->pw_dir);
+       ret->pw_shell = talloc_strdup(ret, from->pw_shell);
        return ret;
 }
 
-void passwd_free (struct passwd **buf)
-{
-       if (!*buf) {
-               DEBUG(0, ("attempted double-free of allocated passwd\n"));
-               return;
-       }
-
-       SAFE_FREE((*buf)->pw_name);
-       SAFE_FREE((*buf)->pw_passwd);
-       SAFE_FREE((*buf)->pw_gecos);
-       SAFE_FREE((*buf)->pw_dir);
-       SAFE_FREE((*buf)->pw_shell);
-
-       SAFE_FREE(*buf);
-}
-
 #define PWNAMCACHE_SIZE 4
-static struct passwd *pwnam_cache[PWNAMCACHE_SIZE];
-static BOOL pwnam_cache_initialized = False;
+static struct passwd **pwnam_cache = NULL;
 
 static void init_pwnam_cache(void)
 {
-       int i;
-
-       if (pwnam_cache_initialized)
+       if (pwnam_cache != NULL)
                return;
 
-       for (i=0; i<PWNAMCACHE_SIZE; i++)
-               pwnam_cache[i] = NULL;
+       pwnam_cache = TALLOC_ZERO_ARRAY(NULL, struct passwd *,
+                                       PWNAMCACHE_SIZE);
+       if (pwnam_cache == NULL) {
+               smb_panic("Could not init pwnam_cache\n");
+       }
 
-       pwnam_cache_initialized = True;
        return;
 }
 
 void flush_pwnam_cache(void)
 {
-       int i;
-
+       talloc_free(pwnam_cache);
+       pwnam_cache = NULL;
        init_pwnam_cache();
-
-       for (i=0; i<PWNAMCACHE_SIZE; i++) {
-               if (pwnam_cache[i] == NULL)
-                       continue;
-
-               passwd_free(&pwnam_cache[i]);
-       }
 }
 
-struct passwd *getpwnam_alloc(const char *name) 
+struct passwd *getpwnam_alloc(TALLOC_CTX *mem_ctx, const char *name)
 {
        int i;
 
@@ -96,7 +72,7 @@ struct passwd *getpwnam_alloc(const char *name)
                if ((pwnam_cache[i] != NULL) && 
                    (strcmp(name, pwnam_cache[i]->pw_name) == 0)) {
                        DEBUG(10, ("Got %s from pwnam_cache\n", name));
-                       return alloc_copy_passwd(pwnam_cache[i]);
+                       return talloc_reference(mem_ctx, pwnam_cache[i]);
                }
        }
 
@@ -119,15 +95,20 @@ struct passwd *getpwnam_alloc(const char *name)
        if (i == PWNAMCACHE_SIZE)
                i = rand() % PWNAMCACHE_SIZE;
 
-       if (pwnam_cache[i] != NULL)
-               passwd_free(&pwnam_cache[i]);
+       if (pwnam_cache[i] != NULL) {
+               talloc_free(pwnam_cache[i]);
+       }
 
-       pwnam_cache[i] = alloc_copy_passwd(temp);
+       pwnam_cache[i] = talloc_copy_passwd(pwnam_cache, temp);
+
+       if (mem_ctx != NULL) {
+               return talloc_reference(mem_ctx, pwnam_cache[i]);
+       }
 
-       return alloc_copy_passwd(temp);
+       return talloc_copy_passwd(NULL, pwnam_cache[i]);
 }
 
-struct passwd *getpwuid_alloc(uid_t uid) 
+struct passwd *getpwuid_alloc(TALLOC_CTX *mem_ctx, uid_t uid) 
 {
        struct passwd *temp;
 
@@ -142,5 +123,5 @@ struct passwd *getpwuid_alloc(uid_t uid)
                return NULL;
        }
 
-       return alloc_copy_passwd(temp);
+       return talloc_copy_passwd(mem_ctx, temp);
 }
index e2b2ebf28ca6b2fc906b4f4af809b2d2ddd57c44..c7f9dc2fdbec60dbd1355f0f1aee1e67aeb0f679 100644 (file)
@@ -75,6 +75,11 @@ const DOM_SID global_sid_Builtin_Backup_Operators =  /* Builtin backup operators
 const DOM_SID global_sid_Builtin_Replicator =          /* Builtin replicator */
 { 1, 2, {0,0,0,0,0,5}, {32,552,0,0,0,0,0,0,0,0,0,0,0,0,0}};
 
+const DOM_SID global_sid_Unix_Users =                  /* Unmapped Unix users */
+{ 1, 1, {0,0,0,0,0,22}, {1,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
+const DOM_SID global_sid_Unix_Groups =                 /* Unmapped Unix groups */
+{ 1, 1, {0,0,0,0,0,22}, {2,0,0,0,0,0,0,0,0,0,0,0,0,0,0}};
+
 /* Unused, left here for documentary purposes */
 #if 0
 #define SECURITY_NULL_SID_AUTHORITY    0
index 0b02487f774cdb804ce9e90328cd26a14b72eed2..85b5cfc90a7bec7523614e3cc0dd4ab16e8e36ad 100644 (file)
@@ -1667,7 +1667,7 @@ int fstr_sprintf(fstring s, const char *fmt, ...)
 
 #define S_LIST_ABS 16 /* List Allocation Block Size */
 
-char **str_list_make(const char *string, const char *sep)
+static char **str_list_make_internal(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
 {
        char **list, **rlist;
        const char *str;
@@ -1677,7 +1677,11 @@ char **str_list_make(const char *string, const char *sep)
        
        if (!string || !*string)
                return NULL;
-       s = SMB_STRDUP(string);
+       if (mem_ctx) {
+               s = talloc_strdup(mem_ctx, string);
+       } else {
+               s = SMB_STRDUP(string);
+       }
        if (!s) {
                DEBUG(0,("str_list_make: Unable to allocate memory"));
                return NULL;
@@ -1691,32 +1695,64 @@ char **str_list_make(const char *string, const char *sep)
        while (next_token(&str, tok, sep, sizeof(tok))) {               
                if (num == lsize) {
                        lsize += S_LIST_ABS;
-                       rlist = SMB_REALLOC_ARRAY(list, char *, lsize +1);
+                       if (mem_ctx) {
+                               rlist = TALLOC_REALLOC_ARRAY(mem_ctx, list, char *, lsize +1);
+                       } else {
+                               rlist = SMB_REALLOC_ARRAY(list, char *, lsize +1);
+                       }
                        if (!rlist) {
                                DEBUG(0,("str_list_make: Unable to allocate memory"));
                                str_list_free(&list);
-                               SAFE_FREE(s);
+                               if (mem_ctx) {
+                                       talloc_free(s);
+                               } else {
+                                       SAFE_FREE(s);
+                               }
                                return NULL;
                        } else
                                list = rlist;
                        memset (&list[num], 0, ((sizeof(char**)) * (S_LIST_ABS +1)));
                }
+
+               if (mem_ctx) {
+                       list[num] = talloc_strdup(mem_ctx, tok);
+               } else {
+                       list[num] = SMB_STRDUP(tok);
+               }
                
-               list[num] = SMB_STRDUP(tok);
                if (!list[num]) {
                        DEBUG(0,("str_list_make: Unable to allocate memory"));
                        str_list_free(&list);
-                       SAFE_FREE(s);
+                       if (mem_ctx) {
+                               talloc_free(s);
+                       } else {
+                               SAFE_FREE(s);
+                       }
                        return NULL;
                }
        
                num++;  
        }
-       
-       SAFE_FREE(s);
+
+       if (mem_ctx) {
+               talloc_free(s);
+       } else {
+               SAFE_FREE(s);
+       }
+
        return list;
 }
 
+char **str_list_make_talloc(TALLOC_CTX *mem_ctx, const char *string, const char *sep)
+{
+       return str_list_make_internal(mem_ctx, string, sep);
+}
+
+char **str_list_make(const char *string, const char *sep)
+{
+       return str_list_make_internal(NULL, string, sep);
+}
+
 BOOL str_list_copy(char ***dest, const char **src)
 {
        char **list, **rlist;
@@ -1778,16 +1814,35 @@ BOOL str_list_compare(char **list1, char **list2)
        return True;
 }
 
-void str_list_free(char ***list)
+static void str_list_free_internal(TALLOC_CTX *mem_ctx, char ***list)
 {
        char **tlist;
        
        if (!list || !*list)
                return;
        tlist = *list;
-       for(; *tlist; tlist++)
-               SAFE_FREE(*tlist);
-       SAFE_FREE(*list);
+       for(; *tlist; tlist++) {
+               if (mem_ctx) {
+                       talloc_free(*tlist);
+               } else {
+                       SAFE_FREE(*tlist);
+               }
+       }
+       if (mem_ctx) {
+               talloc_free(*tlist);
+       } else {
+               SAFE_FREE(*list);
+       }
+}
+
+void str_list_free_talloc(TALLOC_CTX *mem_ctx, char ***list)
+{
+       str_list_free_internal(mem_ctx, list);
+}
+
+void str_list_free(char ***list)
+{
+       str_list_free_internal(NULL, list);
 }
 
 /******************************************************************************
@@ -2317,3 +2372,23 @@ char *sstring_sub(const char *src, char front, char back)
        temp3[len-1] = '\0';
        return temp3;
 }
+
+/********************************************************************
+ Check a string for any occurrences of a specified list of invalid
+ characters.
+********************************************************************/
+
+BOOL validate_net_name( const char *name, const char *invalid_chars, int max_len )
+{
+       int i;
+
+       for ( i=0; i<max_len && name[i]; i++ ) {
+               /* fail if strchr_m() finds one of the invalid characters */
+               if ( name[i] && strchr_m( invalid_chars, name[i] ) ) {
+                       return False;
+               }
+       }
+
+       return True;
+}
+
index 880416a5491c44b2b4b21bad9edf8e98c4f1a9df..bc90314fcec31079123d9c62c075f5c112a19d50 100644 (file)
@@ -291,24 +291,18 @@ int rpcstr_pull_unistr2_fstring(char *dest, UNISTR2 *src)
  * have been to manually talloc_strdup them in rpc_client/cli_netlogon.c.
  */
 
-size_t rpcstr_pull_unistr2_talloc(TALLOC_CTX *mem_ctx, char **dest,
-                                 UNISTR2 *src)
+char *rpcstr_pull_unistr2_talloc(TALLOC_CTX *mem_ctx, UNISTR2 *src)
 {
        pstring tmp;
        size_t result;
 
        result = pull_ucs2(NULL, tmp, src->buffer, sizeof(tmp),
                           src->uni_str_len * 2, 0);
-       if (result < 0) {
-               return result;
-       }
-
-       *dest = talloc_strdup(mem_ctx, tmp);
-       if (*dest == NULL) {
-               return -1;
+       if (result == (size_t)-1) {
+               return NULL;
        }
 
-       return result;
+       return talloc_strdup(mem_ctx, tmp);
 }
 
 /* Converts a string from internal samba format to unicode
diff --git a/source3/libads/gpo.c b/source3/libads/gpo.c
new file mode 100644 (file)
index 0000000..9cf7aae
--- /dev/null
@@ -0,0 +1,680 @@
+/* 
+ *  Unix SMB/CIFS implementation.
+ *  Group Policy Object Support
+ *  Copyright (C) Guenther Deschner 2005
+ *  
+ *  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"
+
+ADS_STATUS ads_parse_gp_ext(TALLOC_CTX *mem_ctx,
+                           const char *extension_raw,
+                           struct GP_EXT *gp_ext)
+{
+       char **ext_list;
+       char **ext_strings;
+       int i;
+
+       DEBUG(20,("ads_parse_gp_ext: %s\n", extension_raw));
+
+       ext_list = str_list_make_talloc(mem_ctx, extension_raw, "]");
+       if (ext_list == NULL) {
+               goto parse_error;
+       }
+
+       for (i = 0; ext_list[i] != NULL; i++) {
+               /* no op */
+       }
+
+       gp_ext->num_exts = i;
+       
+       gp_ext->extensions = TALLOC_ZERO_ARRAY(mem_ctx, char *, gp_ext->num_exts);
+       gp_ext->extensions_guid = TALLOC_ZERO_ARRAY(mem_ctx, char *, gp_ext->num_exts);
+       gp_ext->snapins = TALLOC_ZERO_ARRAY(mem_ctx, char *, gp_ext->num_exts);
+       gp_ext->snapins_guid = TALLOC_ZERO_ARRAY(mem_ctx, char *, gp_ext->num_exts);
+
+       gp_ext->gp_extension = talloc_strdup(mem_ctx, extension_raw);
+
+       if (gp_ext->extensions == NULL || gp_ext->extensions_guid == NULL || 
+           gp_ext->snapins == NULL || gp_ext->snapins_guid == NULL || 
+           gp_ext->gp_extension == NULL) {
+               goto parse_error;
+       }
+
+       for (i = 0; ext_list[i] != NULL; i++) {
+
+               int k;
+               char *p, *q;
+               
+               DEBUGADD(10,("extension #%d\n", i));
+
+               p = ext_list[i];
+
+               if (p[0] == '[') {
+                       p++;
+               }
+
+               ext_strings = str_list_make_talloc(mem_ctx, p, "}");
+               if (ext_strings == NULL) {
+                       goto parse_error;
+               }
+
+               for (k = 0; ext_strings[k] != NULL; k++) {
+                       /* no op */
+               }
+
+               q = ext_strings[0];
+
+               if (q[0] == '{') {
+                       q++;
+               }
+
+               gp_ext->extensions[i] = talloc_strdup(mem_ctx, cse_gpo_guid_string_to_name(q));
+               gp_ext->extensions_guid[i] = talloc_strdup(mem_ctx, q);
+
+               /* we might have no name for the guid */
+               if (gp_ext->extensions_guid[i] == NULL) {
+                       goto parse_error;
+               }
+               
+               for (k = 1; ext_strings[k] != NULL; k++) {
+
+                       char *m = ext_strings[k];
+
+                       if (m[0] == '{') {
+                               m++;
+                       }
+
+                       /* FIXME: theoretically there could be more than one snapin per extension */
+                       gp_ext->snapins[i] = talloc_strdup(mem_ctx, cse_snapin_gpo_guid_string_to_name(m));
+                       gp_ext->snapins_guid[i] = talloc_strdup(mem_ctx, m);
+
+                       /* we might have no name for the guid */
+                       if (gp_ext->snapins_guid[i] == NULL) {
+                               goto parse_error;
+                       }
+               }
+       }
+
+       if (ext_list) {
+               str_list_free_talloc(mem_ctx, &ext_list); 
+       }
+       if (ext_strings) {
+               str_list_free_talloc(mem_ctx, &ext_strings); 
+       }
+
+       return ADS_ERROR(LDAP_SUCCESS);
+
+parse_error:
+       if (ext_list) {
+               str_list_free_talloc(mem_ctx, &ext_list); 
+       }
+       if (ext_strings) {
+               str_list_free_talloc(mem_ctx, &ext_strings); 
+       }
+
+       return ADS_ERROR(LDAP_NO_MEMORY);
+}
+
+ADS_STATUS ads_parse_gplink(TALLOC_CTX *mem_ctx, 
+                           const char *gp_link_raw,
+                           uint32 options,
+                           struct GP_LINK *gp_link)
+{
+       char **link_list;
+       int i;
+       
+       DEBUG(10,("ads_parse_gplink: gPLink: %s\n", gp_link_raw));
+
+       link_list = str_list_make_talloc(mem_ctx, gp_link_raw, "]");
+       if (link_list == NULL) {
+               goto parse_error;
+       }
+
+       for (i = 0; link_list[i] != NULL; i++) {
+               /* no op */
+       }
+
+       gp_link->gp_opts = options;
+       gp_link->num_links = i;
+       
+       gp_link->link_names = TALLOC_ZERO_ARRAY(mem_ctx, char *, gp_link->num_links);
+       gp_link->link_opts = TALLOC_ZERO_ARRAY(mem_ctx, uint32, gp_link->num_links);
+       
+       gp_link->gp_link = talloc_strdup(mem_ctx, gp_link_raw);
+
+       if (gp_link->link_names == NULL || gp_link->link_opts == NULL || gp_link->gp_link == NULL) {
+               goto parse_error;
+       }
+
+       for (i = 0; link_list[i] != NULL; i++) {
+
+               char *p, *q;
+
+               DEBUGADD(10,("ads_parse_gplink: processing link #%d\n", i));
+
+               q = link_list[i];
+               if (q[0] == '[') {
+                       q++;
+               };
+
+               p = strchr(q, ';');
+               
+               if (p == NULL) {
+                       goto parse_error;
+               }
+
+               gp_link->link_names[i] = talloc_strdup(mem_ctx, q);
+               if (gp_link->link_names[i] == NULL) {
+                       goto parse_error;
+               }
+               gp_link->link_names[i][PTR_DIFF(p, q)] = 0;
+
+               gp_link->link_opts[i] = atoi(p + 1);
+
+               DEBUGADD(10,("ads_parse_gplink: link: %s\n", gp_link->link_names[i]));
+               DEBUGADD(10,("ads_parse_gplink: opt: %d\n", gp_link->link_opts[i]));
+
+       }
+
+       if (link_list) {
+               str_list_free_talloc(mem_ctx, &link_list);
+       }
+
+       return ADS_ERROR(LDAP_SUCCESS);
+
+parse_error:
+       if (link_list) {
+               str_list_free_talloc(mem_ctx, &link_list);
+       }
+
+       return ADS_ERROR(LDAP_NO_MEMORY);
+}
+
+ADS_STATUS ads_get_gpo_link(ADS_STRUCT *ads,
+                           TALLOC_CTX *mem_ctx,
+                           const char *link_dn,
+                           struct GP_LINK *gp_link_struct)
+{
+       ADS_STATUS status;
+       const char *attrs[] = {"gPLink", "gPOptions", NULL};
+       void *res = NULL;
+       const char *gp_link;
+       uint32 gp_options;
+
+       ZERO_STRUCTP(gp_link_struct);
+
+       status = ads_search_dn(ads, &res, link_dn, attrs);
+       if (!ADS_ERR_OK(status)) {
+               DEBUG(10,("ads_get_gpo_link: search failed with %s\n", ads_errstr(status)));
+               return status;
+       }
+
+       if (ads_count_replies(ads, res) != 1) {
+               DEBUG(10,("ads_get_gpo_link: no result\n"));
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+       }
+
+       gp_link = ads_pull_string(ads, mem_ctx, res, "gPLink"); 
+       if (gp_link == NULL) {
+               DEBUG(10,("ads_get_gpo_link: no 'gPLink' attribute found\n"));
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);       
+       }
+
+       if (!ads_pull_uint32(ads, res, "gPOptions", &gp_options)) {
+               DEBUG(10,("ads_get_gpo_link: no 'gPOptions' attribute found\n"));
+               gp_options = 0;
+       }
+
+       ads_msgfree(ads, res);
+
+       return ads_parse_gplink(mem_ctx, gp_link, gp_options, gp_link_struct); 
+}
+
+ADS_STATUS ads_add_gpo_link(ADS_STRUCT *ads, 
+                           TALLOC_CTX *mem_ctx, 
+                           const char *link_dn, 
+                           const char *gpo_dn, 
+                           uint32 gpo_opt)
+{
+       ADS_STATUS status;
+       const char *attrs[] = {"gPLink", NULL};
+       void *res = NULL;
+       const char *gp_link, *gp_link_new;
+       ADS_MODLIST mods;
+
+
+       /* although ADS allows to set anything here, we better check here if
+        * the gpo_dn is sane */
+
+       if (!strnequal(gpo_dn, "LDAP://CN={", strlen("LDAP://CN={")) != 0) {
+               return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);       
+       }
+
+       status = ads_search_dn(ads, &res, link_dn, attrs);
+       if (!ADS_ERR_OK(status)) {
+               DEBUG(10,("ads_add_gpo_link: search failed with %s\n", ads_errstr(status)));
+               return status;
+       }
+
+       if (ads_count_replies(ads, res) != 1) {
+               DEBUG(10,("ads_add_gpo_link: no result\n"));
+               return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+       }
+
+       gp_link = ads_pull_string(ads, mem_ctx, res, "gPLink"); 
+       if (gp_link == NULL) {
+               gp_link_new = talloc_asprintf(mem_ctx, "[%s;%d]", gpo_dn, gpo_opt);
+       } else {
+               gp_link_new = talloc_asprintf(mem_ctx, "%s[%s;%d]", gp_link, gpo_dn, gpo_opt);
+       }
+
+       if (gp_link_new == NULL) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       mods = ads_init_mods(mem_ctx);
+       if (mods == NULL) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       status = ads_mod_str(mem_ctx, &mods, "gPLink", gp_link_new);
+       if (!ADS_ERR_OK(status)) {
+               return status;
+       }
+
+       return ads_gen_mod(ads, link_dn, mods); 
+}
+
+/* untested & broken */
+ADS_STATUS ads_delete_gpo_link(ADS_STRUCT *ads, 
+                              TALLOC_CTX *mem_ctx, 
+                              const char *link_dn, 
+                              const char *gpo_dn)
+{
+       ADS_STATUS status;
+       const char *attrs[] = {"gPLink", NULL};
+       void *res = NULL;
+       const char *gp_link, *gp_link_new = NULL;
+       ADS_MODLIST mods;
+
+       /* check for a sane gpo_dn */
+       if (gpo_dn[0] != '[') {
+               DEBUG(10,("ads_delete_gpo_link: first char not: [\n"));
+               return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
+       }
+               
+       if (gpo_dn[strlen(gpo_dn)] != ']') {
+               DEBUG(10,("ads_delete_gpo_link: last char not: ]\n"));
+               return ADS_ERROR(LDAP_INVALID_DN_SYNTAX);
+       }
+
+       status = ads_search_dn(ads, &res, link_dn, attrs);
+       if (!ADS_ERR_OK(status)) {
+               DEBUG(10,("ads_delete_gpo_link: search failed with %s\n", ads_errstr(status)));
+               return status;
+       }
+
+       if (ads_count_replies(ads, res) != 1) {
+               DEBUG(10,("ads_delete_gpo_link: no result\n"));
+               return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+       }
+
+       gp_link = ads_pull_string(ads, mem_ctx, res, "gPLink"); 
+       if (gp_link == NULL) {
+               return ADS_ERROR(LDAP_NO_SUCH_ATTRIBUTE);
+       }
+
+       /* find link to delete */
+//     gp_link_new = talloc_asprintf(mem_ctx, "%s[%s;%d]", gp_link, gpo_dn, gpo_opt);
+
+       if (gp_link_new == NULL) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       mods = ads_init_mods(mem_ctx);
+       if (mods == NULL) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       status = ads_mod_str(mem_ctx, &mods, "gPLink", gp_link_new);
+       if (!ADS_ERR_OK(status)) {
+               return status;
+       }
+
+       return ads_gen_mod(ads, link_dn, mods); 
+}
+
+ADS_STATUS ads_parse_gpo(ADS_STRUCT *ads,
+                        TALLOC_CTX *mem_ctx,
+                        void *res,
+                        const char *gpo_dn,
+                        struct GROUP_POLICY_OBJECT *gpo)
+{
+       ZERO_STRUCTP(gpo);
+
+       if (res == NULL) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       if (gpo_dn) {
+               gpo->ds_path = talloc_strdup(mem_ctx, gpo_dn);
+       } else {
+               gpo->ds_path = ads_get_dn(ads, res);
+       }
+       if (gpo->ds_path == NULL) {
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       if (!ads_pull_uint32(ads, res, "versionNumber", &gpo->version)) {
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       /* split here for convenience */
+       gpo->version_user = gpo->version >> 16;
+       gpo->version_machine = gpo->version & 0xffff;
+
+       /* sure ??? */
+       if (!ads_pull_uint32(ads, res, "flags", &gpo->options)) {
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       gpo->file_sys_path = ads_pull_string(ads, mem_ctx, res, "gPCFileSysPath");
+       if (gpo->file_sys_path == NULL) {
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       gpo->display_name = ads_pull_string(ads, mem_ctx, res, "displayName");
+       if (gpo->display_name == NULL) {
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       gpo->name = ads_pull_string(ads, mem_ctx, res, "name");
+       if (gpo->name == NULL) {
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       /* ???, this is optional to have and what does it depend on, the 'flags' ?) */
+       gpo->machine_extensions = ads_pull_string(ads, mem_ctx, res, "gPCMachineExtensionNames");
+       gpo->user_extensions = ads_pull_string(ads, mem_ctx, res, "gPCUserExtensionNames");
+
+       ads_msgfree(ads, res);
+
+       return ADS_ERROR(LDAP_SUCCESS);
+}
+
+ADS_STATUS ads_get_gpo(ADS_STRUCT *ads,
+                      TALLOC_CTX *mem_ctx,
+                      const char *gpo_dn,
+                      const char *display_name,
+                      const char *guid_name,
+                      struct GROUP_POLICY_OBJECT *gpo)
+{
+       ADS_STATUS status;
+       void *res = NULL;
+       char *dn;
+       const char *filter;
+       const char *attrs[] = { "cn", "displayName", "flags", "gPCFileSysPath", 
+                               "gPCFunctionalityVersion", "gPCMachineExtensionNames", 
+                               "gPCUserExtensionNames", "gPCWQLFilter", "name", 
+                               "versionNumber", NULL};
+
+       ZERO_STRUCTP(gpo);
+
+       if (!gpo_dn && !display_name && !guid_name) {
+               return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+       }
+
+       if (gpo_dn) {
+       
+               if (strnequal(gpo_dn, "LDAP://", strlen("LDAP://")) != 0) {
+                       gpo_dn = gpo_dn + strlen("LDAP://");
+               }
+
+               status = ads_search_dn(ads, &res, gpo_dn, attrs);
+               
+       } else if (display_name || guid_name) {
+
+               filter = talloc_asprintf(mem_ctx, 
+                                        "(&(objectclass=groupPolicyContainer)(%s=%s))", 
+                                        display_name ? "displayName" : "name",
+                                        display_name ? display_name : guid_name);
+               if (filter == NULL) {
+                       return ADS_ERROR(LDAP_NO_MEMORY);
+               }
+
+               status = ads_do_search_all(ads, ads->config.bind_path,
+                                          LDAP_SCOPE_SUBTREE, filter, 
+                                          attrs, &res);
+       }
+
+       if (!ADS_ERR_OK(status)) {
+               DEBUG(10,("ads_get_gpo: search failed with %s\n", ads_errstr(status)));
+               return status;
+       }
+
+       if (ads_count_replies(ads, res) != 1) {
+               DEBUG(10,("ads_get_gpo: no result\n"));
+               return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+       }
+
+       dn = ads_get_dn(ads, res);
+       if (dn == NULL) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+       
+       status = ads_parse_gpo(ads, mem_ctx, res, dn, gpo);
+       
+       ads_memfree(ads, dn);
+
+       return status;
+}
+
+ADS_STATUS add_gplink_to_gpo_list(ADS_STRUCT *ads,
+                                 TALLOC_CTX *mem_ctx, 
+                                 struct GROUP_POLICY_OBJECT **gpo_list,
+                                 const char *link_dn,
+                                 struct GP_LINK *gp_link,
+                                 enum GPO_LINK_TYPE link_type,
+                                 BOOL only_add_forced_gpos)
+{
+       ADS_STATUS status;
+       int i;
+
+       for (i = 0; i < gp_link->num_links; i++) {
+
+               struct GROUP_POLICY_OBJECT *new_gpo = NULL;
+
+               if (gp_link->link_opts[i] & GPO_LINK_OPT_DISABLED) {
+                       DEBUG(10,("skipping disabled GPO\n"));
+                       continue;
+               }
+
+               if (only_add_forced_gpos) {
+               
+                       if (! (gp_link->link_opts[i] & GPO_LINK_OPT_ENFORCED)) {
+                               DEBUG(10,("skipping nonenforced GPO link because GPOPTIONS_BLOCK_INHERITANCE has been set\n"));
+                               continue;
+                       } else {
+                               DEBUG(10,("adding enforced GPO link although the GPOPTIONS_BLOCK_INHERITANCE has been set\n"));
+                       }
+               }
+
+               new_gpo = TALLOC_P(mem_ctx, struct GROUP_POLICY_OBJECT);
+               if (new_gpo == NULL) {
+                       return ADS_ERROR(LDAP_NO_MEMORY);
+               }
+
+               ZERO_STRUCTP(new_gpo);
+
+               status = ads_get_gpo(ads, mem_ctx, gp_link->link_names[i], NULL, NULL, new_gpo);
+               if (!ADS_ERR_OK(status)) {
+                       return status;
+               }
+
+               new_gpo->link = link_dn;
+               new_gpo->link_type = link_type; 
+
+               DLIST_ADD(*gpo_list, new_gpo);
+
+               DEBUG(10,("add_gplink_to_gplist: added GPLINK #%d %s to GPO list\n", 
+                       i, gp_link->link_names[i]));
+       }
+
+       return ADS_ERROR(LDAP_SUCCESS);
+}
+
+ADS_STATUS ads_get_gpo_list(ADS_STRUCT *ads, 
+                           TALLOC_CTX *mem_ctx, 
+                           const char *dn,
+                           uint32 flags,
+                           struct GROUP_POLICY_OBJECT **gpo_list)
+{
+       /* (L)ocal (S)ite (D)omain (O)rganizational(U)nit */
+       
+       ADS_STATUS status;
+       struct GP_LINK gp_link;
+       const char *parent_dn, *site_dn, *tmp_dn;
+       BOOL add_only_forced_gpos = False;
+
+       ZERO_STRUCTP(gpo_list);
+
+       DEBUG(10,("ads_get_gpo_list: getting GPO list for [%s]\n", dn));
+
+       /* (L)ocal */
+       /* not yet... */
+       
+       /* (S)ite */
+
+       /* are site GPOs valid for users as well ??? */
+       if (flags & GPO_LIST_FLAG_MACHINE) {
+
+               status = ads_site_dn_for_machine(ads, mem_ctx, ads->config.ldap_server_name, &site_dn);
+               if (!ADS_ERR_OK(status)) {
+                       return status;
+               }
+
+               DEBUG(10,("ads_get_gpo_list: query SITE: [%s] for GPOs\n", site_dn));
+
+               status = ads_get_gpo_link(ads, mem_ctx, site_dn, &gp_link);
+               if (ADS_ERR_OK(status)) {
+               
+                       if (DEBUGLEVEL >= 100) {
+                               dump_gplink(ads, mem_ctx, &gp_link);
+                       }
+                       
+                       status = add_gplink_to_gpo_list(ads, mem_ctx, gpo_list, 
+                                                       site_dn, &gp_link, GP_LINK_SITE, 
+                                                       add_only_forced_gpos);
+                       if (!ADS_ERR_OK(status)) {
+                               return status;
+                       }
+       
+                       if (flags & GPO_LIST_FLAG_SITEONLY) {
+                               return ADS_ERROR(LDAP_SUCCESS);
+                       }
+       
+                       /* inheritance can't be blocked at the site level */
+               }
+       }
+
+       tmp_dn = dn;
+
+       while ( (parent_dn = ads_parent_dn(tmp_dn)) && 
+               (!strequal(parent_dn, ads_parent_dn(ads->config.bind_path))) ) {
+
+               /* (D)omain */
+
+               /* An account can just be a member of one domain */
+               if (strncmp(parent_dn, "DC=", strlen("DC=")) == 0) {
+
+                       DEBUG(10,("ads_get_gpo_list: query DC: [%s] for GPOs\n", parent_dn));
+
+                       status = ads_get_gpo_link(ads, mem_ctx, parent_dn, &gp_link);
+                       if (ADS_ERR_OK(status)) {
+                               
+                               if (DEBUGLEVEL >= 100) {
+                                       dump_gplink(ads, mem_ctx, &gp_link);
+                               }
+
+                               /* block inheritance from now on */
+                               if (gp_link.gp_opts & GPOPTIONS_BLOCK_INHERITANCE) {
+                                       add_only_forced_gpos = True;
+                               }
+
+                               status = add_gplink_to_gpo_list(ads, mem_ctx, 
+                                                               gpo_list, parent_dn, 
+                                                               &gp_link, GP_LINK_DOMAIN, 
+                                                               add_only_forced_gpos);
+                               if (!ADS_ERR_OK(status)) {
+                                       return status;
+                               }
+                       }
+               }
+
+               tmp_dn = parent_dn;
+       }
+
+       /* reset dn again */
+       tmp_dn = dn;
+       
+       while ( (parent_dn = ads_parent_dn(tmp_dn)) && 
+               (!strequal(parent_dn, ads_parent_dn(ads->config.bind_path))) ) {
+
+
+               /* (O)rganizational(U)nit */
+
+               /* An account can be a member of more OUs */
+               if (strncmp(parent_dn, "OU=", strlen("OU=")) == 0) {
+               
+                       DEBUG(10,("ads_get_gpo_list: query OU: [%s] for GPOs\n", parent_dn));
+
+                       status = ads_get_gpo_link(ads, mem_ctx, parent_dn, &gp_link);
+                       if (ADS_ERR_OK(status)) {
+
+                               if (DEBUGLEVEL >= 100) {
+                                       dump_gplink(ads, mem_ctx, &gp_link);
+                               }
+
+                               /* block inheritance from now on */
+                               if (gp_link.gp_opts & GPOPTIONS_BLOCK_INHERITANCE) {
+                                       add_only_forced_gpos = True;
+                               }
+
+                               status = add_gplink_to_gpo_list(ads, mem_ctx, 
+                                                               gpo_list, parent_dn, 
+                                                               &gp_link, GP_LINK_OU, 
+                                                               add_only_forced_gpos);
+                               if (!ADS_ERR_OK(status)) {
+                                       return status;
+                               }
+                       }
+               }
+
+               tmp_dn = parent_dn;
+
+       };
+
+       return ADS_ERROR(LDAP_SUCCESS);
+}
diff --git a/source3/libads/gpo_util.c b/source3/libads/gpo_util.c
new file mode 100644 (file)
index 0000000..8f913c1
--- /dev/null
@@ -0,0 +1,496 @@
+/* 
+ *  Unix SMB/CIFS implementation.
+ *  Group Policy Object Support
+ *  Copyright (C) Guenther Deschner 2005
+ *  
+ *  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"
+
+#define DEFAULT_DOMAIN_POLICY "Default Domain Policy"
+#define DEFAULT_DOMAIN_CONTROLLERS_POLICY "Default Domain Controllers Policy"
+
+/* should we store a parsed guid ? UUID_FLAT guid; */
+struct gpo_table {
+       const char *name;
+       const char *guid_string;
+};
+
+struct snapin_table {
+       const char *name;
+       const char *guid_string;
+       ADS_STATUS (*snapin_fn)(ADS_STRUCT *, TALLOC_CTX *mem_ctx, const char *, const char *);
+};
+
+static struct gpo_table gpo_default_policy[] = {
+       { DEFAULT_DOMAIN_POLICY, 
+               "31B2F340-016D-11D2-945F-00C04FB984F9" },
+       { DEFAULT_DOMAIN_CONTROLLERS_POLICY, 
+               "6AC1786C-016F-11D2-945F-00C04fB984F9" },
+       { NULL, NULL }
+};
+
+
+/* the following is seen in gPCMachineExtensionNames or gPCUserExtensionNames */
+
+static struct gpo_table gpo_cse_extensions[] = {
+       { "Administrative Templates Extension", 
+               "35378EAC-683F-11D2-A89A-00C04FBBCFA2" }, /* Registry Policy ? */
+       { "Microsoft Disc Quota", 
+               "3610EDA5-77EF-11D2-8DC5-00C04FA31A66" },
+       { "EFS recovery", 
+               "B1BE8D72-6EAC-11D2-A4EA-00C04F79F83A" },
+       { "Folder Redirection", 
+               "25537BA6-77A8-11D2-9B6C-0000F8080861" },
+       { "IP Security", 
+               "E437BC1C-AA7D-11D2-A382-00C04F991E27" },
+       { "Internet Explorer Branding", 
+               "A2E30F80-D7DE-11d2-BBDE-00C04F86AE3B" },
+       { "QoS Packet Scheduler", 
+               "426031c0-0b47-4852-b0ca-ac3d37bfcb39" },
+       { "Scripts", 
+               "42B5FAAE-6536-11D2-AE5A-0000F87571E3" },
+       { "Security", 
+               "827D319E-6EAC-11D2-A4EA-00C04F79F83A" },
+       { "Software Installation", 
+               "C6DC5466-785A-11D2-84D0-00C04FB169F7" },
+       { "Wireless Group Policy", 
+               "0ACDD40C-75AC-BAA0-BF6DE7E7FE63" },
+       { NULL, NULL }
+};
+
+/* guess work */
+static struct snapin_table gpo_cse_snapin_extensions[] = {
+       { "Administrative Templates", 
+               "0F6B957D-509E-11D1-A7CC-0000F87571E3", gpo_snapin_handler_none },
+       { "Certificates", 
+               "53D6AB1D-2488-11D1-A28C-00C04FB94F17", gpo_snapin_handler_none },
+       { "EFS recovery policy processing", 
+               "B1BE8D72-6EAC-11D2-A4EA-00C04F79F83A", gpo_snapin_handler_none },
+       { "Folder Redirection policy processing", 
+               "25537BA6-77A8-11D2-9B6C-0000F8080861", gpo_snapin_handler_none },
+       { "Folder Redirection", 
+               "88E729D6-BDC1-11D1-BD2A-00C04FB9603F", gpo_snapin_handler_none },
+       { "Registry policy processing", 
+               "35378EAC-683F-11D2-A89A-00C04FBBCFA2", gpo_snapin_handler_none },
+       { "Remote Installation Services", 
+               "3060E8CE-7020-11D2-842D-00C04FA372D4", gpo_snapin_handler_none },
+       { "Security Settings", 
+               "803E14A0-B4FB-11D0-A0D0-00A0C90F574B", gpo_snapin_handler_security_settings },
+       { "Security policy processing", 
+               "827D319E-6EAC-11D2-A4EA-00C04F79F83A", gpo_snapin_handler_security_settings },
+       { "unknown", 
+               "3060E8D0-7020-11D2-842D-00C04FA372D4", gpo_snapin_handler_none },
+       { "unknown2", 
+               "53D6AB1B-2488-11D1-A28C-00C04FB94F17", gpo_snapin_handler_none },
+       { NULL, NULL, NULL }
+};
+
+static const char *name_to_guid_string(const char *name, struct gpo_table *table)
+{
+       int i;
+
+       for (i = 0; table[i].name; i++) {
+               if (strequal(name, table[i].name)) {
+                       return table[i].guid_string;
+               }
+       }
+       
+       return NULL;
+}
+
+static const char *guid_string_to_name(const char *guid_string, struct gpo_table *table)
+{
+       int i;
+
+       for (i = 0; table[i].guid_string; i++) {
+               if (strequal(guid_string, table[i].guid_string)) {
+                       return table[i].name;
+               }
+       }
+       
+       return NULL;
+}
+
+static const char *default_gpo_name_to_guid_string(const char *name)
+{
+       return name_to_guid_string(name, gpo_default_policy);
+}
+
+static const char *default_gpo_guid_string_to_name(const char *guid)
+{
+       return guid_string_to_name(guid, gpo_default_policy);
+}
+
+const char *cse_gpo_guid_string_to_name(const char *guid)
+{
+       return guid_string_to_name(guid, gpo_cse_extensions);
+}
+
+static const char *cse_gpo_name_to_guid_string(const char *name)
+{
+       return name_to_guid_string(name, gpo_cse_extensions);
+}
+
+const char *cse_snapin_gpo_guid_string_to_name(const char *guid)
+{
+       return guid_string_to_name(guid, gpo_cse_snapin_extensions);
+}
+
+void dump_gp_ext(struct GP_EXT *gp_ext)
+{
+       int lvl = 10;
+       int i;
+
+       if (gp_ext == NULL) {
+               return;
+       }
+
+       DEBUG(lvl,("---------------------\n\n"));
+       DEBUGADD(lvl,("name:\t\t\t%s\n", gp_ext->gp_extension));
+
+       for (i=0; i< gp_ext->num_exts; i++) {
+
+               DEBUGADD(lvl,("extension:\t\t\t%s\n", gp_ext->extensions_guid[i]));
+               DEBUGADD(lvl,("extension (name):\t\t\t%s\n", gp_ext->extensions[i]));
+               
+               DEBUGADD(lvl,("snapin:\t\t\t%s\n", gp_ext->snapins_guid[i]));
+               DEBUGADD(lvl,("snapin (name):\t\t\t%s\n", gp_ext->snapins[i]));
+       }
+}
+
+void dump_gpo(TALLOC_CTX *mem_ctx, struct GROUP_POLICY_OBJECT *gpo) 
+{
+       int lvl = 1;
+
+       if (gpo == NULL) {
+               return;
+       }
+
+       DEBUG(lvl,("---------------------\n\n"));
+
+       DEBUGADD(lvl,("name:\t\t\t%s\n", gpo->name));
+       DEBUGADD(lvl,("displayname:\t\t%s\n", gpo->display_name));
+       DEBUGADD(lvl,("version:\t\t%d (0x%08x)\n", gpo->version, gpo->version));
+       DEBUGADD(lvl,("version_user:\t\t%d (0x%04x)\n", gpo->version_user, gpo->version_user));
+       DEBUGADD(lvl,("version_machine:\t%d (0x%04x)\n", gpo->version_machine, gpo->version_machine));
+       DEBUGADD(lvl,("filesyspath:\t\t%s\n", gpo->file_sys_path));
+       DEBUGADD(lvl,("dspath:\t\t%s\n", gpo->ds_path));
+
+       DEBUGADD(lvl,("options:\t\t%d ", gpo->options));
+       if (gpo->options & GPFLAGS_USER_SETTINGS_DISABLED) {
+               DEBUGADD(lvl,("GPFLAGS_USER_SETTINGS_DISABLED ")); 
+       }
+       if (gpo->options & GPFLAGS_MACHINE_SETTINGS_DISABLED) {
+               DEBUGADD(lvl,("GPFLAGS_MACHINE_SETTINGS_DISABLED")); 
+       }
+       DEBUGADD(lvl,("\n"));
+
+       DEBUGADD(lvl,("link:\t\t\t%s\n", gpo->link));
+       DEBUGADD(lvl,("link_type:\t\t%d ", gpo->link_type));
+       switch (gpo->link_type) {
+       case GP_LINK_UNKOWN:
+               DEBUGADD(lvl,("GP_LINK_UNKOWN\n"));
+               break;
+       case GP_LINK_OU:
+               DEBUGADD(lvl,("GP_LINK_OU\n"));
+               break;
+       case GP_LINK_DOMAIN:
+               DEBUGADD(lvl,("GP_LINK_DOMAIN\n"));
+               break;
+       case GP_LINK_SITE:
+               DEBUGADD(lvl,("GP_LINK_SITE\n"));
+               break;
+       case GP_LINK_MACHINE:
+               DEBUGADD(lvl,("GP_LINK_MACHINE\n"));
+               break;
+       default:
+               break;
+       }
+
+       if (gpo->machine_extensions) {
+
+               struct GP_EXT gp_ext;
+               ADS_STATUS status;
+
+               DEBUGADD(lvl,("machine_extensions:\t%s\n", gpo->machine_extensions));
+
+               status = ads_parse_gp_ext(mem_ctx, gpo->machine_extensions, &gp_ext);
+               if (!ADS_ERR_OK(status)) {
+                       return;
+               }
+               dump_gp_ext(&gp_ext);
+       }
+       
+       if (gpo->user_extensions) {
+       
+               struct GP_EXT gp_ext;
+               ADS_STATUS status;
+               
+               DEBUGADD(lvl,("user_extensions:\t%s\n", gpo->user_extensions));
+
+               status = ads_parse_gp_ext(mem_ctx, gpo->user_extensions, &gp_ext);
+               if (!ADS_ERR_OK(status)) {
+                       return;
+               }
+               dump_gp_ext(&gp_ext);
+       }
+};
+
+void dump_gplink(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, struct GP_LINK *gp_link)
+{
+       ADS_STATUS status;
+       int i;
+       int lvl = 10;
+
+       if (gp_link == NULL) {
+               return;
+       }
+
+       DEBUG(lvl,("---------------------\n\n"));
+
+       DEBUGADD(lvl,("gplink: %s\n", gp_link->gp_link));
+       DEBUGADD(lvl,("gpopts: %d ", gp_link->gp_opts));
+       switch (gp_link->gp_opts) {
+       case GPOPTIONS_INHERIT:
+               DEBUGADD(lvl,("GPOPTIONS_INHERIT\n"));
+               break;
+       case GPOPTIONS_BLOCK_INHERITANCE:
+               DEBUGADD(lvl,("GPOPTIONS_BLOCK_INHERITANCE\n"));
+               break;
+       default:
+               break;
+       }
+
+       DEBUGADD(lvl,("num links: %d\n", gp_link->num_links));
+
+       for (i = 0; i < gp_link->num_links; i++) {
+       
+               DEBUGADD(lvl,("---------------------\n\n"));
+       
+               DEBUGADD(lvl,("link: #%d\n", i + 1));
+               DEBUGADD(lvl,("name: %s\n", gp_link->link_names[i]));
+
+               DEBUGADD(lvl,("opt: %d ", gp_link->link_opts[i]));
+               if (gp_link->link_opts[i] & GPO_LINK_OPT_ENFORCED) {
+                       DEBUGADD(lvl,("GPO_LINK_OPT_ENFORCED "));
+               }
+               if (gp_link->link_opts[i] & GPO_LINK_OPT_DISABLED) {
+                       DEBUGADD(lvl,("GPO_LINK_OPT_DISABLED"));
+               }
+               DEBUGADD(lvl,("\n"));
+
+               if (ads != NULL && mem_ctx != NULL) {
+
+                       struct GROUP_POLICY_OBJECT gpo;
+
+                       status = ads_get_gpo(ads, mem_ctx, gp_link->link_names[i], NULL, NULL, &gpo);
+                       if (!ADS_ERR_OK(status)) {
+                               DEBUG(lvl,("get gpo for %s failed: %s\n", gp_link->link_names[i], ads_errstr(status)));
+                               return;
+                       }
+                       dump_gpo(mem_ctx, &gpo);
+               }
+       }
+}
+
+ADS_STATUS process_extension_with_snapin(ADS_STRUCT *ads,
+                                        TALLOC_CTX *mem_ctx,
+                                        const char *extension_guid,
+                                        const char *snapin_guid)
+{
+       int i;
+
+       for (i=0; gpo_cse_snapin_extensions[i].guid_string; i++) {
+       
+               if (strcmp(gpo_cse_snapin_extensions[i].guid_string, snapin_guid) == 0) {
+               
+                       return gpo_cse_snapin_extensions[i].snapin_fn(ads, mem_ctx, 
+                                                                     extension_guid, snapin_guid);
+               }
+       }
+
+       DEBUG(10,("process_extension_with_snapin: no snapin handler for extension %s (%s) found\n", 
+               extension_guid, snapin_guid));
+
+       return ADS_ERROR(LDAP_SUCCESS);
+}
+
+ADS_STATUS gpo_process_a_gpo(ADS_STRUCT *ads,
+                            TALLOC_CTX *mem_ctx,
+                            struct GROUP_POLICY_OBJECT *gpo,
+                            const char *extension_guid,
+                            uint32 flags)
+{
+       ADS_STATUS status;
+       struct GP_EXT gp_ext;
+       int i;
+       
+       if (flags & GPO_LIST_FLAG_MACHINE) {
+
+               if (gpo->machine_extensions) {
+
+                       status = ads_parse_gp_ext(mem_ctx, gpo->machine_extensions, &gp_ext);
+
+                       if (!ADS_ERR_OK(status)) {
+                               return status;
+                       }
+
+               } else {
+                       /* nothing to apply */
+                       return ADS_ERROR(LDAP_SUCCESS);
+               }
+       
+       } else {
+
+               if (gpo->user_extensions) {
+               
+                       status = ads_parse_gp_ext(mem_ctx, gpo->user_extensions, &gp_ext);
+
+                       if (!ADS_ERR_OK(status)) {
+                               return status;
+                       }
+               } else {
+                       /* nothing to apply */
+                       return ADS_ERROR(LDAP_SUCCESS);
+               }
+       }
+
+       for (i=0; i<gp_ext.num_exts; i++) {
+
+               if (extension_guid && !strequal(extension_guid, gp_ext.extensions_guid[i])) {
+                       continue;
+               }
+
+               status = process_extension_with_snapin(ads, mem_ctx, gp_ext.extensions_guid[i], 
+                                                      gp_ext.snapins_guid[i]);
+               if (!ADS_ERR_OK(status)) {
+                       return status;
+               }
+       }
+
+       return ADS_ERROR(LDAP_SUCCESS);
+}
+
+ADS_STATUS gpo_process_gpo_list(ADS_STRUCT *ads,
+                               TALLOC_CTX *mem_ctx,
+                               struct GROUP_POLICY_OBJECT **gpo_list,
+                               const char *extensions_guid,
+                               uint32 flags)
+{
+       ADS_STATUS status;
+       struct GROUP_POLICY_OBJECT *gpo = *gpo_list;
+
+       for (gpo = *gpo_list; gpo; gpo = gpo->next) {
+       
+               status = gpo_process_a_gpo(ads, mem_ctx, gpo, 
+                                          extensions_guid, flags);
+       
+               if (!ADS_ERR_OK(status)) {
+                       return status;
+               }
+
+       }
+
+       return ADS_ERROR(LDAP_SUCCESS);
+}
+
+ADS_STATUS gpo_snapin_handler_none(ADS_STRUCT *ads, 
+                                  TALLOC_CTX *mem_ctx, 
+                                  const char *extension_guid, 
+                                  const char *snapin_guid)
+{
+       DEBUG(10,("gpo_snapin_handler_none\n"));
+
+       return ADS_ERROR(LDAP_SUCCESS);
+}
+
+ADS_STATUS gpo_snapin_handler_security_settings(ADS_STRUCT *ads, 
+                                               TALLOC_CTX *mem_ctx, 
+                                               const char *extension_guid, 
+                                               const char *snapin_guid)
+{
+       DEBUG(10,("gpo_snapin_handler_security_settings\n"));
+
+       return ADS_ERROR(LDAP_SUCCESS);
+}
+
+ADS_STATUS gpo_lockout_policy(ADS_STRUCT *ads,
+                             TALLOC_CTX *mem_ctx,
+                             const char *hostname,
+                             SAM_UNK_INFO_12 *lockout_policy)
+{
+       return ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
+}
+
+ADS_STATUS gpo_password_policy(ADS_STRUCT *ads,
+                              TALLOC_CTX *mem_ctx,
+                              const char *hostname,
+                              SAM_UNK_INFO_1 *password_policy)
+{
+       ADS_STATUS status;
+       struct GROUP_POLICY_OBJECT *gpo_list;
+       const char *attrs[] = {"distinguishedName", "userAccountControl", NULL};
+       char *filter, *dn;
+       void *res = NULL;
+       uint32 uac;
+
+       return ADS_ERROR_NT(NT_STATUS_NOT_IMPLEMENTED);
+
+       filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)(sAMAccountName=%s))", hostname);
+       if (filter == NULL) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       status = ads_do_search_all(ads, ads->config.bind_path,
+                                  LDAP_SCOPE_SUBTREE,
+                                  filter, attrs, &res);
+       
+       if (!ADS_ERR_OK(status)) {
+               return status;
+       }
+
+       if (ads_count_replies(ads, res) != 1) {
+               return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+       }
+
+       dn = ads_get_dn(ads, res);
+       if (dn == NULL) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       if (!ads_pull_uint32(ads, res, "userAccountControl", &uac)) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       if (!(uac & UF_WORKSTATION_TRUST_ACCOUNT)) {
+               return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+       }
+
+       status = ads_get_gpo_list(ads, mem_ctx, dn, GPO_LIST_FLAG_MACHINE, &gpo_list);
+       if (!ADS_ERR_OK(status)) {
+               return status;
+       }
+
+       status = gpo_process_gpo_list(ads, mem_ctx, &gpo_list, 
+                                     cse_gpo_name_to_guid_string("Security"), 
+                                     GPO_LIST_FLAG_MACHINE); 
+       if (!ADS_ERR_OK(status)) {
+               return status;
+       }
+
+       return ADS_ERROR(LDAP_SUCCESS);
+}
index d5b4b11fa2453df428397c2d7b4b49e3d5adc561..67f843377572de68629c471c093091ca40ce4b89 100644 (file)
@@ -62,13 +62,17 @@ int kerberos_kinit_password(const char *principal,
                                const char *password,
                                int time_offset,
                                time_t *expire_time,
-                               const char *cache_name)
+                               time_t *renew_till_time,
+                               const char *cache_name,
+                               BOOL request_pac,
+                               time_t renewable_time)
 {
        krb5_context ctx = NULL;
        krb5_error_code code = 0;
        krb5_ccache cc = NULL;
        krb5_principal me;
        krb5_creds my_creds;
+       krb5_get_init_creds_opt opt;
 
        initialize_krb5_error_table();
        if ((code = krb5_init_context(&ctx)))
@@ -77,9 +81,11 @@ int kerberos_kinit_password(const char *principal,
        if (time_offset != 0) {
                krb5_set_real_time(ctx, time(NULL) + time_offset, 0);
        }
-       
-       if ((code = krb5_cc_resolve(ctx, cache_name ?
-                       cache_name : krb5_cc_default_name(ctx), &cc))) {
+
+       DEBUG(10,("kerberos_kinit_password: using %s as ccache\n",
+                       cache_name ? cache_name: krb5_cc_default_name(ctx)));
+
+       if ((code = krb5_cc_resolve(ctx, cache_name ? cache_name : krb5_cc_default_name(ctx), &cc))) {
                krb5_free_context(ctx);
                return code;
        }
@@ -88,10 +94,20 @@ int kerberos_kinit_password(const char *principal,
                krb5_free_context(ctx); 
                return code;
        }
+
+       krb5_get_init_creds_opt_init(&opt);
+       krb5_get_init_creds_opt_set_renew_life(&opt, renewable_time);
+       krb5_get_init_creds_opt_set_forwardable(&opt, 1);
        
+       if (request_pac) {
+#ifdef HAVE_KRB5_GET_INIT_CREDS_OPT_SET_PAC_REQUEST
+               krb5_get_init_creds_opt_set_pac_request(ctx, &opt, True);
+#endif
+       }
+
        if ((code = krb5_get_init_creds_password(ctx, &my_creds, me, CONST_DISCARD(char *,password), 
                                                 kerb_prompter, 
-                                                NULL, 0, NULL, NULL))) {
+                                                NULL, 0, NULL, &opt))) {
                krb5_free_principal(ctx, me);
                krb5_free_context(ctx);         
                return code;
@@ -111,9 +127,14 @@ int kerberos_kinit_password(const char *principal,
                krb5_free_context(ctx);         
                return code;
        }
-       
-       if (expire_time)
+
+       if (expire_time) {
                *expire_time = (time_t) my_creds.times.endtime;
+       }
+
+       if (renew_till_time) {
+               *renew_till_time = (time_t) my_creds.times.renew_till;
+       }
 
        krb5_cc_close(ctx, cc);
        krb5_free_cred_contents(ctx, &my_creds);
@@ -157,7 +178,7 @@ int ads_kinit_password(ADS_STRUCT *ads)
        }
        
        ret = kerberos_kinit_password(s, ads->auth.password, ads->auth.time_offset,
-                       &ads->auth.expire, NULL);
+                       &ads->auth.expire, NULL, NULL, False, ads->auth.renewable);
 
        if (ret) {
                DEBUG(0,("kerberos_kinit_password %s failed: %s\n", 
@@ -349,7 +370,8 @@ static krb5_error_code get_service_ticket(krb5_context ctx,
        if (password == NULL) {
                goto out;
        }
-       if ((err = kerberos_kinit_password(machine_account, password, 0, NULL, LIBADS_CCACHE_NAME)) != 0) {
+       if ((err = kerberos_kinit_password(machine_account, password, 0, NULL, NULL, 
+                                          LIBADS_CCACHE_NAME, False, 0)) != 0) {
                DEBUG(0,("get_service_ticket: kerberos_kinit_password %s@%s failed: %s\n", 
                        machine_account,
                        lp_realm(),
diff --git a/source3/libads/krb5_errs.c b/source3/libads/krb5_errs.c
new file mode 100644 (file)
index 0000000..cd227d4
--- /dev/null
@@ -0,0 +1,132 @@
+/* 
+ *  Unix SMB/CIFS implementation.
+ *  Kerberos error mapping functions
+ *  Copyright (C) Guenther Deschner 2005
+ *  
+ *  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"
+
+#ifdef HAVE_KRB5
+
+static const struct {
+       int krb5_code;
+       NTSTATUS ntstatus;
+} krb5_to_nt_status_map[] = {
+       {KRB5_CC_IO, NT_STATUS_UNEXPECTED_IO_ERROR},
+       {KRB5KDC_ERR_BADOPTION, NT_STATUS_INVALID_PARAMETER},
+       {KRB5KDC_ERR_CLIENT_REVOKED, NT_STATUS_ACCESS_DENIED},
+       {KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN, NT_STATUS_INVALID_ACCOUNT_NAME},
+       {KRB5KDC_ERR_ETYPE_NOSUPP, NT_STATUS_LOGON_FAILURE},
+#if defined(KRB5KDC_ERR_KEY_EXPIRED) /* Heimdal */
+       {KRB5KDC_ERR_KEY_EXPIRED, NT_STATUS_PASSWORD_EXPIRED},
+#elif defined(KRB5KDC_ERR_KEY_EXP) /* MIT */
+       {KRB5KDC_ERR_KEY_EXP, NT_STATUS_PASSWORD_EXPIRED},
+#else 
+#error Neither KRB5KDC_ERR_KEY_EXPIRED nor KRB5KDC_ERR_KEY_EXP available
+#endif
+       {25, NT_STATUS_PASSWORD_EXPIRED}, /* FIXME: bug in heimdal 0.7 krb5_get_init_creds_password (Inappropriate ioctl for device (25)) */
+       {KRB5KDC_ERR_NULL_KEY, NT_STATUS_LOGON_FAILURE},
+       {KRB5KDC_ERR_POLICY, NT_STATUS_PASSWORD_RESTRICTION},
+       {KRB5KDC_ERR_PREAUTH_FAILED, NT_STATUS_LOGON_FAILURE},
+       {KRB5KDC_ERR_SERVICE_REVOKED, NT_STATUS_ACCESS_DENIED},
+       {KRB5KDC_ERR_S_PRINCIPAL_UNKNOWN, NT_STATUS_INVALID_ACCOUNT_NAME},
+       {KRB5KDC_ERR_SUMTYPE_NOSUPP, NT_STATUS_LOGON_FAILURE},
+       {KRB5KDC_ERR_TGT_REVOKED, NT_STATUS_ACCESS_DENIED},
+       {KRB5_KDC_UNREACH, NT_STATUS_NO_LOGON_SERVERS},
+       {KRB5KRB_AP_ERR_BAD_INTEGRITY, NT_STATUS_LOGON_FAILURE},
+       {KRB5KRB_AP_ERR_MODIFIED, NT_STATUS_LOGON_FAILURE},
+       {KRB5KRB_AP_ERR_SKEW, NT_STATUS_TIME_DIFFERENCE_AT_DC},
+       {KRB5KRB_AP_ERR_TKT_EXPIRED, NT_STATUS_LOGON_FAILURE},
+       {KRB5KRB_ERR_GENERIC, NT_STATUS_UNSUCCESSFUL},
+       {KRB5KRB_ERR_RESPONSE_TOO_BIG, NT_STATUS_PROTOCOL_UNREACHABLE},
+       {0, NT_STATUS_OK}
+};
+
+static const struct {
+       NTSTATUS ntstatus;
+       int krb5_code;
+} nt_status_to_krb5_map[] = {
+       {NT_STATUS_LOGON_FAILURE, KRB5KDC_ERR_PREAUTH_FAILED},
+       {NT_STATUS_NO_LOGON_SERVERS, KRB5_KDC_UNREACH},
+       {NT_STATUS_OK, 0}
+};
+
+/*****************************************************************************
+convert a KRB5 error to a NT status32 code
+ *****************************************************************************/
+NTSTATUS krb5_to_nt_status(int kerberos_error)
+{
+       int i;
+       
+       if (kerberos_error == 0) {
+               return NT_STATUS_OK;
+       }
+       
+       for (i=0; NT_STATUS_V(krb5_to_nt_status_map[i].ntstatus); i++) {
+               if (kerberos_error == krb5_to_nt_status_map[i].krb5_code)
+                       return krb5_to_nt_status_map[i].ntstatus;
+       }
+
+       return NT_STATUS_UNSUCCESSFUL;
+}
+
+/*****************************************************************************
+convert an NT status32 code to a KRB5 error
+ *****************************************************************************/
+int nt_status_to_krb5(NTSTATUS nt_status)
+{
+       int i;
+       
+       if NT_STATUS_IS_OK(nt_status) {
+               return 0;
+       }
+       
+       for (i=0; NT_STATUS_V(nt_status_to_krb5_map[i].ntstatus); i++) {
+               if (NT_STATUS_EQUAL(nt_status,nt_status_to_krb5_map[i].ntstatus))
+                       return nt_status_to_krb5_map[i].krb5_code;
+       }
+
+       return KRB5KRB_ERR_GENERIC;
+}
+
+#else 
+
+/*****************************************************************************
+convert a KRB5 error to a NT status32 code
+ *****************************************************************************/
+NTSTATUS krb5_to_nt_status(int kerberos_error)
+{
+       if (kerberos_error == 0) {
+               return NT_STATUS_OK;
+       }
+       
+       return NT_STATUS_UNSUCCESSFUL;
+}
+
+/*****************************************************************************
+convert an NT status32 code to a KRB5 error
+ *****************************************************************************/
+int nt_status_to_krb5(NTSTATUS nt_status)
+{
+       if (NT_STATUS_EQUAL(nt_status, NT_STATUS_OK)) {
+               return 0;
+       }
+       return -1; /* FIXME: what to return here ? */
+}
+
+#endif
+
index 31d0a02cad034cd4d42cd987866fbbab694b3421..6ffd218e966a383b9828fbc4c10c654914259743 100644 (file)
 #ifdef HAVE_KRB5
 
 #define DEFAULT_KPASSWD_PORT   464
+
 #define KRB5_KPASSWD_VERS_CHANGEPW             1
+
 #define KRB5_KPASSWD_VERS_SETPW                        0xff80
 #define KRB5_KPASSWD_VERS_SETPW_ALT            2
+
+#define KRB5_KPASSWD_SUCCESS                   0
+#define KRB5_KPASSWD_MALFORMED                 1
+#define KRB5_KPASSWD_HARDERROR                 2
+#define KRB5_KPASSWD_AUTHERROR                 3
+#define KRB5_KPASSWD_SOFTERROR                 4
 #define KRB5_KPASSWD_ACCESSDENIED              5
 #define KRB5_KPASSWD_BAD_VERSION               6
 #define KRB5_KPASSWD_INITIAL_FLAG_NEEDED       7
@@ -213,6 +221,25 @@ static krb5_error_code setpw_result_code_string(krb5_context context,
         return (0);
 }
 
+ krb5_error_code kpasswd_err_to_krb5_err(krb5_error_code res_code) 
+{
+       switch(res_code) {
+               case KRB5_KPASSWD_ACCESSDENIED:
+                       return KRB5KDC_ERR_BADOPTION;
+               case KRB5_KPASSWD_INITIAL_FLAG_NEEDED:
+                       return KRB5KDC_ERR_BADOPTION;
+                       /* return KV5M_ALT_METHOD; MIT-only define */
+               case KRB5_KPASSWD_ETYPE_NOSUPP:
+                       return KRB5KDC_ERR_ETYPE_NOSUPP;
+               case KRB5_KPASSWD_BAD_PRINCIPAL:
+                       return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
+               case KRB5_KPASSWD_POLICY_REJECT:
+               case KRB5_KPASSWD_SOFTERROR:
+                       return KRB5KDC_ERR_POLICY;
+               default:
+                       return KRB5KRB_ERR_GENERIC;
+       }
+}
 static krb5_error_code parse_setpw_reply(krb5_context context, 
                                         krb5_auth_context auth_context,
                                         krb5_data *packet)
@@ -312,23 +339,9 @@ static krb5_error_code parse_setpw_reply(krb5_context context,
        else {
                const char *errstr;
                setpw_result_code_string(context, res_code, &errstr);
-               DEBUG(1, ("Error changing password: %s\n", errstr));
-
-               switch(res_code) {
-                       case KRB5_KPASSWD_ACCESSDENIED:
-                               return KRB5KDC_ERR_BADOPTION;
-                       case KRB5_KPASSWD_INITIAL_FLAG_NEEDED:
-                               return KRB5KDC_ERR_BADOPTION;
-                               /* return KV5M_ALT_METHOD; MIT-only define */
-                       case KRB5_KPASSWD_ETYPE_NOSUPP:
-                               return KRB5KDC_ERR_ETYPE_NOSUPP;
-                       case KRB5_KPASSWD_BAD_PRINCIPAL:
-                               return KRB5KDC_ERR_C_PRINCIPAL_UNKNOWN;
-                       case KRB5_KPASSWD_POLICY_REJECT:
-                               return KRB5KDC_ERR_POLICY;
-                       default:
-                               return KRB5KRB_ERR_GENERIC;
-               }
+               DEBUG(1, ("Error changing password: %s (%d)\n", errstr, res_code));
+
+               return kpasswd_err_to_krb5_err(res_code);
        }
 }
 
@@ -664,7 +677,7 @@ ADS_STATUS kerberos_set_password(const char *kpasswd_server,
 {
     int ret;
 
-    if ((ret = kerberos_kinit_password(auth_principal, auth_password, time_offset, NULL, NULL))) {
+    if ((ret = kerberos_kinit_password(auth_principal, auth_password, time_offset, NULL, NULL, NULL, False, 0))) {
        DEBUG(1,("Failed kinit for principal %s (%s)\n", auth_principal, error_message(ret)));
        return ADS_ERROR_KRB5(ret);
     }
index e503da62a47c0ddb69ca16b1a88fb3720bc4cf49..8444989bac385f1dbb749f7a84f626289f209e3c 100644 (file)
@@ -4,6 +4,7 @@
    Copyright (C) Andrew Tridgell 2001
    Copyright (C) Remus Koos 2001
    Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
+   Copyright (C) Guenther Deschner 2005
    
    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
@@ -807,6 +808,65 @@ char *ads_get_dn(ADS_STRUCT *ads, void *msg)
        return unix_dn;
 }
 
+/**
+ * Get a canonical dn from search results
+ * @param ads connection to ads server
+ * @param msg Search result
+ * @return dn string
+ **/
+char *ads_get_dn_canonical(ADS_STRUCT *ads, void *msg)
+{
+#ifdef HAVE_LDAP_DN2AD_CANONICAL
+       return ldap_dn2ad_canonical(ads_get_dn(ads, msg));
+#else
+       return NULL;
+#endif
+}
+
+
+/**
+ * Get the parent dn from a search result
+ * @param ads connection to ads server
+ * @param msg Search result
+ * @return parent dn string
+ **/
+char *ads_get_parent_dn(ADS_STRUCT *ads, void *msg)
+{
+       char *mydn, *p, *dn;
+
+       dn = ads_get_dn(ads, msg);
+       if (dn == NULL) {
+               return NULL;
+       }
+
+       mydn = dn;
+       ads_memfree(ads, dn);
+       
+       p = strchr(mydn, ',');
+
+       if (p == NULL) {
+               return NULL;
+       }
+
+       return p+1;
+}
+
+/**
+ * Get the parent from a dn
+ * @param dn the dn to return the parent from
+ * @return parent dn string
+ **/
+char *ads_parent_dn(const char *dn)
+{
+       char *p = strchr(dn, ',');
+
+       if (p == NULL) {
+               return NULL;
+       }
+
+       return p+1;
+}
+
 /**
  * Find a machine account given a hostname
  * @param ads connection to ads server
@@ -2700,4 +2760,167 @@ ADS_STATUS ads_workgroup_name(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char *
        return ADS_SUCCESS;
 }
 
+/**
+ * find our site name 
+ * @param ads connection to ads server
+ * @param mem_ctx Pointer to talloc context
+ * @param site_name Pointer to the sitename
+ * @return status of search
+ **/
+ADS_STATUS ads_site_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char **site_name)
+{
+       ADS_STATUS status;
+       void *res;
+       const char *dn, *service_name;
+       const char *attrs[] = { "dsServiceName", NULL };
+
+       status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
+       if (!ADS_ERR_OK(status)) {
+               return status;
+       }
+
+       service_name = ads_pull_string(ads, mem_ctx, res, "dsServiceName");
+       if (service_name == NULL) {
+               return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
+       }
+
+       /* go up three levels */
+       dn = ads_parent_dn(ads_parent_dn(ads_parent_dn(service_name)));
+       if (dn == NULL) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       *site_name = talloc_strdup(mem_ctx, dn);
+       if (*site_name == NULL) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       ads_msgfree(ads, res);
+
+       return status;
+       /*
+       dsServiceName: CN=NTDS Settings,CN=W2K3DC,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=ber,DC=suse,DC=de
+       */                                               
+}
+
+/**
+ * find the site dn where a machine resides
+ * @param ads connection to ads server
+ * @param mem_ctx Pointer to talloc context
+ * @param computer_name name of the machine
+ * @param site_name Pointer to the sitename
+ * @return status of search
+ **/
+ADS_STATUS ads_site_dn_for_machine(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char *computer_name, const char **site_dn)
+{
+       ADS_STATUS status;
+       void *res;
+       const char *parent, *config_context, *filter;
+       const char *attrs[] = { "configurationNamingContext", NULL };
+       char *dn;
+
+       /* shortcut a query */
+       if (strequal(computer_name, ads->config.ldap_server_name)) {
+               return ads_site_dn(ads, mem_ctx, site_dn);
+       }
+
+       status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
+       if (!ADS_ERR_OK(status)) {
+               return status;
+       }
+
+       config_context = ads_pull_string(ads, mem_ctx, res, "configurationNamingContext");
+       if (config_context == NULL) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       filter = talloc_asprintf(mem_ctx, "(cn=%s)", computer_name);
+       if (filter == NULL) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       status = ads_do_search(ads, config_context, LDAP_SCOPE_SUBTREE, filter, NULL, &res);
+       if (!ADS_ERR_OK(status)) {
+               return status;
+       }
+
+       if (ads_count_replies(ads, res) != 1) {
+               return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+       }
+
+       dn = ads_get_dn(ads, res);
+       if (dn == NULL) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       /* go up three levels */
+       parent = ads_parent_dn(ads_parent_dn(ads_parent_dn(dn)));
+       if (parent == NULL) {
+               ads_memfree(ads, dn);
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       *site_dn = talloc_strdup(mem_ctx, parent);
+       if (*site_dn == NULL) {
+               ads_memfree(ads, dn);
+               ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       ads_memfree(ads, dn);
+       ads_msgfree(ads, res);
+
+       return status;
+}
+
+/**
+ * get the upn suffixes for a domain
+ * @param ads connection to ads server
+ * @param mem_ctx Pointer to talloc context
+ * @param suffixes Pointer to an array of suffixes
+ * @param site_name Pointer to the number of suffixes
+ * @return status of search
+ **/
+ADS_STATUS ads_upn_suffixes(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **suffixes, size_t *num_suffixes)
+{
+       ADS_STATUS status;
+       void *res;
+       const char *config_context, *base;
+       const char *attrs[] = { "configurationNamingContext", NULL };
+       const char *attrs2[] = { "uPNSuffixes", NULL };
+
+       status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
+       if (!ADS_ERR_OK(status)) {
+               return status;
+       }
+
+       config_context = ads_pull_string(ads, mem_ctx, res, "configurationNamingContext");
+       if (config_context == NULL) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       base = talloc_asprintf(mem_ctx, "cn=Partitions,%s", config_context);
+       if (base == NULL) {
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       status = ads_search_dn(ads, &res, base, attrs2); 
+       if (!ADS_ERR_OK(status)) {
+               return status;
+       }
+
+       if (ads_count_replies(ads, res) != 1) {
+               return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
+       }
+
+       suffixes = ads_pull_strings(ads, mem_ctx, &res, "uPNSuffixes", num_suffixes);
+       if (suffixes == NULL) {
+               ads_msgfree(ads, res);
+               return ADS_ERROR(LDAP_NO_MEMORY);
+       }
+
+       ads_msgfree(ads, res);
+
+       return status;
+}
+
 #endif
index f6adfb51086e03357ff870944e5c979cd1ffd0d7..d8d33a924f2c5b1e186ac25da2d3f844a2362cec 100644 (file)
@@ -294,16 +294,28 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
        /* we need to fetch a service ticket as the ldap user in the
           servers realm, regardless of our realm */
        asprintf(&sname, "ldap/%s@%s", ads->config.ldap_server_name, ads->config.realm);
-       krb5_init_context(&ctx);
-       krb5_set_default_tgs_ktypes(ctx, enc_types);
-       krb5_parse_name(ctx, sname, &principal);
+
+       initialize_krb5_error_table();
+       status = ADS_ERROR_KRB5(krb5_init_context(&ctx));
+       if (!ADS_ERR_OK(status)) {
+               return status;
+       }
+       status = ADS_ERROR_KRB5(krb5_set_default_tgs_ktypes(ctx, enc_types));
+       if (!ADS_ERR_OK(status)) {
+               return status;
+       }
+       status = ADS_ERROR_KRB5(krb5_parse_name(ctx, sname, &principal));
+       if (!ADS_ERR_OK(status)) {
+               return status;
+       }
+
        free(sname);
        krb5_free_context(ctx); 
 
        input_name.value = &principal;
        input_name.length = sizeof(principal);
 
-       gss_rc = gss_import_name(&minor_status,&input_name,&nt_principal, &serv_name);
+       gss_rc = gss_import_name(&minor_status, &input_name, &nt_principal, &serv_name);
        if (gss_rc) {
                return ADS_ERROR_GSS(gss_rc, minor_status);
        }
@@ -375,8 +387,9 @@ static ADS_STATUS ads_sasl_gssapi_bind(ADS_STRUCT *ads)
 
        p = (uint8 *)output_token.value;
 
+#if 0
        file_save("sasl_gssapi.dat", output_token.value, output_token.length);
-
+#endif
        max_msg_size = (p[1]<<16) | (p[2]<<8) | p[3];
        sec_layer = *p;
 
index d2e52f01a4c5f7fc9627518ea9108124a50d3d14..b157f33c69f23fdafc34ae45eed1d27d37250c59 100644 (file)
@@ -298,7 +298,7 @@ int cac_LsaGetSidsFromNames(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Ls
 
    /*now actually lookup the names*/
    hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, num_names,
-                                          (const char **)op->in.names, &sids, &types);
+                                          (const char **)op->in.names, NULL, &sids, &types);
 
    if(NT_STATUS_IS_OK(hnd->status)) {
       /*this is the easy part, just make the out.sids array*/
@@ -577,7 +577,7 @@ int cac_LsaEnumAccountRights(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct L
       uint32 *type;
 
       /*lookup the SID*/
-      hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type);
+      hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), NULL, &user_sid, &type);
 
       if(!NT_STATUS_IS_OK(hnd->status))
          return CAC_FAILURE;
@@ -799,7 +799,7 @@ int cac_LsaOpenAccount(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaOpen
       uint32 *type;
 
       /*lookup the SID*/
-      hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type);
+      hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), NULL, &user_sid, &type);
 
       if(!NT_STATUS_IS_OK(hnd->status))
          return CAC_FAILURE;
@@ -859,7 +859,7 @@ int cac_LsaAddPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaAd
 
    if(op->in.name && !op->in.sid) {
       /*lookup the SID*/
-      hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type);
+      hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), NULL, &user_sid, &type);
 
       if(!NT_STATUS_IS_OK(hnd->status))
          return CAC_FAILURE;
@@ -909,7 +909,7 @@ int cac_LsaRemovePrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Ls
 
    if(op->in.name && !op->in.sid) {
       /*lookup the SID*/
-      hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type);
+      hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), NULL, &user_sid, &type);
 
       if(!NT_STATUS_IS_OK(hnd->status))
          return CAC_FAILURE;
@@ -959,7 +959,7 @@ int cac_LsaClearPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct Lsa
 
    if(op->in.name && !op->in.sid) {
       /*lookup the SID*/
-      hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type);
+      hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), NULL, &user_sid, &type);
 
       if(!NT_STATUS_IS_OK(hnd->status))
          return CAC_FAILURE;
@@ -1008,7 +1008,7 @@ int cac_LsaSetPrivileges(CacServerHandle *hnd, TALLOC_CTX *mem_ctx, struct LsaAd
 
    if(op->in.name && !op->in.sid) {
       /*lookup the SID*/
-      hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), &user_sid, &type);
+      hnd->status = rpccli_lsa_lookup_names( pipe_hnd, mem_ctx, op->in.pol, 1, (const char **)&(op->in.name), NULL, &user_sid, &type);
 
       if(!NT_STATUS_IS_OK(hnd->status))
          return CAC_FAILURE;
index 7c15c8d19f2da4a61b0443d072ecdfd6cbce8672..6f32fb1b5d417daaa7f853decfcadd674ba3f7df 100644 (file)
@@ -756,7 +756,7 @@ ADS_STATUS cli_session_setup_spnego(struct cli_state *cli, const char *user,
                        int ret;
                        
                        use_in_memory_ccache();
-                       ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL, NULL);
+                       ret = kerberos_kinit_password(user, pass, 0 /* no time correction for now */, NULL, NULL, NULL, False, 0);
                        
                        if (ret){
                                SAFE_FREE(principal);
index 51f21397f7c25691c9ff51ced4bbed9e20530ea6..c5cf75783ba36d17b9602dd1ce3598af55ce3373 100644 (file)
@@ -682,12 +682,15 @@ BOOL cli_check_msdfs_proxy( struct cli_state *cli, const char *sharename,
        CLIENT_DFS_REFERRAL *refs = NULL;
        size_t num_refs;
        uint16 consumed;
-       struct cli_state *cli_ipc;
        pstring fullpath;
+       BOOL res;
+       uint16 cnum;
        
        if ( !cli || !sharename )
                return False;
 
+       cnum = cli->cnum;
+
        /* special case.  never check for a referral on the IPC$ share */
 
        if ( strequal( sharename, "IPC$" ) )
@@ -699,12 +702,19 @@ BOOL cli_check_msdfs_proxy( struct cli_state *cli, const char *sharename,
 
        /* check for the referral */
 
-       if ( !(cli_ipc = cli_cm_open( cli->desthost, "IPC$", False )) )
+       if (!cli_send_tconX(cli, "IPC$", "IPC", NULL, 0)) {
                return False;
-       
-       if ( !cli_dfs_get_referral(cli_ipc, fullpath, &refs, &num_refs, &consumed) 
-               || !num_refs )
-       {
+       }
+
+       res = cli_dfs_get_referral(cli, fullpath, &refs, &num_refs, &consumed);
+
+       if (!cli_tdis(cli)) {
+               return False;
+       }
+
+       cli->cnum = cnum;
+               
+       if (!res || !num_refs ) {
                return False;
        }
        
index 2f980adcf8733f4a99005047f5aa0b1a7ec10626..55addd44a61cbafcb9595ad7bd8018ef4804db4e 100644 (file)
@@ -353,11 +353,14 @@ struct cli_state *cli_initialise(struct cli_state *cli)
 /****************************************************************************
  External interface.
  Close an open named pipe over SMB. Free any authentication data.
+ Returns False if the cli_close call failed.
  ****************************************************************************/
 
-void cli_rpc_pipe_close(struct rpc_pipe_client *cli)
+BOOL cli_rpc_pipe_close(struct rpc_pipe_client *cli)
 {
-       if (!cli_close(cli->cli, cli->fnum)) {
+       BOOL ret = cli_close(cli->cli, cli->fnum);
+
+       if (!ret) {
                DEBUG(0,("cli_rpc_pipe_close: cli_close failed on pipe %s, "
                          "fnum 0x%x "
                          "to machine %s.  Error was %s\n",
@@ -376,6 +379,7 @@ void cli_rpc_pipe_close(struct rpc_pipe_client *cli)
 
        DLIST_REMOVE(cli->cli->pipe_list, cli);
        talloc_destroy(cli->mem_ctx);
+       return ret;
 }
 
 /****************************************************************************
index e0dcefeb1d7e682f94f5e5a191b5fd0b50c6a529..55a705d7f0ff71f54c59539938c857dee99a6fa6 100644 (file)
@@ -409,9 +409,10 @@ static BOOL ads_cleanup_expired_creds(krb5_context context,
                                      krb5_creds  *credsp)
 {
        krb5_error_code retval;
+       const char *cc_type = krb5_cc_get_type(context, ccache);
 
-       DEBUG(3, ("Ticket in ccache[%s] expiration %s\n",
-                 krb5_cc_default_name(context),
+       DEBUG(3, ("ads_cleanup_expired_creds: Ticket in ccache[%s:%s] expiration %s\n",
+                 cc_type, krb5_cc_get_name(context, ccache),
                  http_timestring(credsp->times.endtime)));
 
        /* we will probably need new tickets if the current ones
@@ -425,11 +426,11 @@ static BOOL ads_cleanup_expired_creds(krb5_context context,
           use memory ccaches, and a FILE one probably means that
           we're using creds obtained outside of our exectuable
        */
-       if (StrCaseCmp(krb5_cc_get_type(context, ccache), "FILE") == 0) {
-               DEBUG(5, ("ads_cleanup_expired_creds: We do not remove creds from a FILE ccache\n"));
+       if (strequal(cc_type, "KCM") || strequal(cc_type, "FILE")) {
+               DEBUG(5, ("ads_cleanup_expired_creds: We do not remove creds from a %s ccache\n", cc_type));
                return False;
        }
-       
+
        retval = krb5_cc_remove_cred(context, ccache, 0, credsp);
        if (retval) {
                DEBUG(1, ("ads_cleanup_expired_creds: krb5_cc_remove_cred failed, err %s\n",
@@ -467,7 +468,7 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context,
        /* obtain ticket & session key */
        ZERO_STRUCT(creds);
        if ((retval = krb5_copy_principal(context, server, &creds.server))) {
-               DEBUG(1,("krb5_copy_principal failed (%s)\n", 
+               DEBUG(1,("ads_krb5_mk_req: krb5_copy_principal failed (%s)\n", 
                         error_message(retval)));
                goto cleanup_princ;
        }
@@ -502,8 +503,8 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context,
                i++;
        }
 
-       DEBUG(10,("ads_krb5_mk_req: Ticket (%s) in ccache (%s) is valid until: (%s - %u)\n",
-                 principal, krb5_cc_default_name(context),
+       DEBUG(10,("ads_krb5_mk_req: Ticket (%s) in ccache (%s:%s) is valid until: (%s - %u)\n",
+                 principal, krb5_cc_get_type(context, ccache), krb5_cc_get_name(context, ccache),
                  http_timestring((unsigned)credsp->times.endtime), 
                  (unsigned)credsp->times.endtime));
 
@@ -530,7 +531,8 @@ cleanup_princ:
   get a kerberos5 ticket for the given service 
 */
 int cli_krb5_get_ticket(const char *principal, time_t time_offset, 
-                       DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts)
+                       DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, 
+                       uint32 extra_ap_opts, const char *ccname)
 {
        krb5_error_code retval;
        krb5_data packet;
@@ -544,7 +546,7 @@ int cli_krb5_get_ticket(const char *principal, time_t time_offset,
                ENCTYPE_DES_CBC_MD5, 
                ENCTYPE_DES_CBC_CRC, 
                ENCTYPE_NULL};
-       
+
        initialize_krb5_error_table();
        retval = krb5_init_context(&context);
        if (retval) {
@@ -557,7 +559,8 @@ int cli_krb5_get_ticket(const char *principal, time_t time_offset,
                krb5_set_real_time(context, time(NULL) + time_offset, 0);
        }
 
-       if ((retval = krb5_cc_default(context, &ccdef))) {
+       if ((retval = krb5_cc_resolve(context, ccname ?
+                       ccname : krb5_cc_default_name(context), &ccdef))) {
                DEBUG(1,("cli_krb5_get_ticket: krb5_cc_default failed (%s)\n",
                         error_message(retval)));
                goto failed;
@@ -989,12 +992,156 @@ out:
 #else
 #error NO_SUITABLE_PRINCIPAL_COMPARE_FUNCTION
 #endif
+}
+
+ krb5_error_code smb_krb5_renew_ticket(const char *ccache_string,      /* FILE:/tmp/krb5cc_0 */
+                                      const char *client_string,       /* gd@BER.SUSE.DE */
+                                      const char *service_string,      /* krbtgt/BER.SUSE.DE@BER.SUSE.DE */
+                                      time_t *new_start_time)
+{
+       krb5_error_code ret;
+       krb5_context context = NULL;
+       krb5_ccache ccache = NULL;
+       krb5_principal client = NULL;
+
+       initialize_krb5_error_table();
+       ret = krb5_init_context(&context);
+       if (ret) {
+               goto done;
+       }
+
+       if (!ccache_string) {
+               ccache_string = krb5_cc_default_name(context);
+       }
+
+       DEBUG(10,("smb_krb5_renew_ticket: using %s as ccache\n", ccache_string));
+
+       /* FIXME: we should not fall back to defaults */
+       ret = krb5_cc_resolve(context, CONST_DISCARD(char *, ccache_string), &ccache);
+       if (ret) {
+               goto done;
+       }
+
+#ifdef HAVE_KRB5_GET_RENEWED_CREDS     /* MIT */
+       {
+               krb5_creds creds;
+       
+               if (client_string) {
+                       ret = krb5_parse_name(context, client_string, &client);
+                       if (ret) {
+                               goto done;
+                       }
+               } else {
+                       ret = krb5_cc_get_principal(context, ccache, &client);
+                       if (ret) {
+                               goto done;
+                       }
+               }
+       
+               ret = krb5_get_renewed_creds(context, &creds, client, ccache, CONST_DISCARD(char *, service_string));
+               if (ret) {
+                       DEBUG(10,("smb_krb5_renew_ticket: krb5_get_kdc_cred failed: %s\n", error_message(ret)));
+                       goto done;
+               }
+
+               /* hm, doesn't that create a new one if the old one wasn't there? - Guenther */
+               ret = krb5_cc_initialize(context, ccache, client);
+               if (ret) {
+                       goto done;
+               }
+       
+               ret = krb5_cc_store_cred(context, ccache, &creds);
+
+               if (new_start_time) {
+                       *new_start_time = (time_t) creds.times.renew_till;
+               }
+
+               krb5_free_cred_contents(context, &creds);
+       }
+#elif defined(HAVE_KRB5_GET_KDC_CRED)  /* Heimdal */
+       {
+               krb5_kdc_flags flags;
+               krb5_creds creds_in;
+               krb5_realm *client_realm;
+               krb5_creds *creds;
+
+               memset(&creds_in, 0, sizeof(creds_in));
+
+               if (client_string) {
+                       ret = krb5_parse_name(context, client_string, &creds_in.client);
+                       if (ret) {
+                               goto done;
+                       }
+               } else {
+                       ret = krb5_cc_get_principal(context, ccache, &creds_in.client);
+                       if (ret) {
+                               goto done;
+                       }
+               }
+
+               if (service_string) {
+                       ret = krb5_parse_name(context, service_string, &creds_in.server);
+                       if (ret) { 
+                               goto done;
+                       }
+               } else {
+                       /* build tgt service by default */
+                       client_realm = krb5_princ_realm(context, client);
+                       ret = krb5_make_principal(context, &creds_in.server, *client_realm, KRB5_TGS_NAME, *client_realm, NULL);
+                       if (ret) {
+                               goto done;
+                       }
+               }
+
+               flags.i = 0;
+               flags.b.renewable = flags.b.renew = True;
+
+               ret = krb5_get_kdc_cred(context, ccache, flags, NULL, NULL, &creds_in, &creds);
+               if (ret) {
+                       DEBUG(10,("smb_krb5_renew_ticket: krb5_get_kdc_cred failed: %s\n", error_message(ret)));
+                       goto done;
+               }
+               
+               /* hm, doesn't that create a new one if the old one wasn't there? - Guenther */
+               ret = krb5_cc_initialize(context, ccache, creds_in.client);
+               if (ret) {
+                       goto done;
+               }
+       
+               ret = krb5_cc_store_cred(context, ccache, creds);
+
+               if (new_start_time) {
+                       *new_start_time = (time_t) creds->times.renew_till;
+               }
+                                               
+               krb5_free_cred_contents(context, &creds_in);
+               krb5_free_creds(context, creds);
+       }
+#else
+#error No suitable krb5 ticket renew function available
+#endif
+
+
+done:
+       if (client) {
+               krb5_free_principal(context, client);
+       }
+       if (context) {
+               krb5_free_context(context);
+       }
+       if (ccache) {
+               krb5_cc_close(context, ccache);
+       }
+
+       return ret;
+    
 }
 
 #else /* HAVE_KRB5 */
  /* this saves a few linking headaches */
  int cli_krb5_get_ticket(const char *principal, time_t time_offset, 
-                       DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts) 
+                       DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts,
+                       const char *ccname) 
 {
         DEBUG(0,("NO KERBEROS SUPPORT\n"));
         return 1;
index 48780e28dfa9637a870cb8dfd9e61363e13fdf39..252dafcfa8b9b3ae6b5f408fb356b55f8ad6f2b1 100644 (file)
@@ -169,7 +169,11 @@ static size_t interpret_long_filename(struct cli_state *cli, int level,char *p,f
 int cli_list_new(struct cli_state *cli,const char *Mask,uint16 attribute, 
                 void (*fn)(const char *, file_info *, const char *, void *), void *state)
 {
-        int max_matches = 1366;
+#if 1
+       int max_matches = 1366; /* Match W2k - was 512. */
+#else
+       int max_matches = 512;
+#endif
        int info_level;
        char *p, *p2;
        pstring mask;
index cc481a066abc4314f9ee1c15743b6144e2a32c3a..13bf1a866c9af0bfa19a980502dee49ff5ca4194 100644 (file)
@@ -333,7 +333,7 @@ int spnego_gen_negTokenTarg(const char *principal, int time_offset,
 
        /* get a kerberos ticket for the service and extract the session key */
        retval = cli_krb5_get_ticket(principal, time_offset,
-                                       &tkt, session_key_krb5, extra_ap_opts);
+                                       &tkt, session_key_krb5, extra_ap_opts, NULL);
 
        if (retval)
                return retval;
index 2af4d57b804ae0c5f51580f3ca5db0edc01ea620..49512d7a2e58ec24d1eae804add4ad3de90f92de 100644 (file)
@@ -25,8 +25,6 @@
 
 #include "includes.h"
 
-#define FAILED_CONNECTION_CACHE_TIMEOUT 30 /* Seconds between attempts */
-
 #define CONNCACHE_ADDR         1
 #define CONNCACHE_NAME         2
 
@@ -44,10 +42,13 @@ struct failed_connection_cache {
 static struct failed_connection_cache *failed_connection_cache;
 
 /**********************************************************************
- Check for a previously failed connection
+ Check for a previously failed connection.
+ failed_cache_timeout is an a absolute number of seconds after which
+ we should time this out. If failed_cache_timeout == 0 then time out
+ immediately. If failed_cache_timeout == -1 then never time out.
 **********************************************************************/
 
-NTSTATUS check_negative_conn_cache( const char *domain, const char *server )
+NTSTATUS check_negative_conn_cache_timeout( const char *domain, const char *server, unsigned int failed_cache_timeout )
 {
        struct failed_connection_cache *fcc;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
@@ -59,22 +60,24 @@ NTSTATUS check_negative_conn_cache( const char *domain, const char *server )
 
        for (fcc = failed_connection_cache; fcc; fcc = fcc->next) {
        
-               if ( !(strequal(domain, fcc->domain_name) && strequal(server, fcc->controller)) )
+               if (!(strequal(domain, fcc->domain_name) && strequal(server, fcc->controller))) {
                        continue; /* no match; check the next entry */
+               }
                
                /* we have a match so see if it is still current */
+               if (failed_cache_timeout != (unsigned int)-1) {
+                       if (failed_cache_timeout == 0 ||
+                                       (time(NULL) - fcc->lookup_time) > (time_t)failed_cache_timeout) {
+                               /* Cache entry has expired, delete it */
 
-               if ((time(NULL) - fcc->lookup_time) > FAILED_CONNECTION_CACHE_TIMEOUT) 
-               {
-                       /* Cache entry has expired, delete it */
-
-                       DEBUG(10, ("check_negative_conn_cache: cache entry expired for %s, %s\n", 
-                               domain, server ));
+                               DEBUG(10, ("check_negative_conn_cache: cache entry expired for %s, %s\n", 
+                                       domain, server ));
 
-                       DLIST_REMOVE(failed_connection_cache, fcc);
-                       SAFE_FREE(fcc);
+                               DLIST_REMOVE(failed_connection_cache, fcc);
+                               SAFE_FREE(fcc);
 
-                       return NT_STATUS_OK;
+                               return NT_STATUS_OK;
+                       }
                }
 
                /* The timeout hasn't expired yet so return false */
@@ -90,6 +93,11 @@ NTSTATUS check_negative_conn_cache( const char *domain, const char *server )
        return NT_STATUS_OK;
 }
 
+NTSTATUS check_negative_conn_cache( const char *domain, const char *server)
+{
+       return check_negative_conn_cache_timeout(domain, server, FAILED_CONNECTION_CACHE_TIMEOUT);
+}
+
 /**********************************************************************
  Add an entry to the failed conneciton cache (aither a name of dotted 
  decimal IP
index 3c0b13ad6ff565d8fd9654d00f5f6c3698ae2a66..f6b5af068a54a20d62cadf32fbd2dc066ae15040 100644 (file)
@@ -1411,6 +1411,13 @@ static const struct {
        {NT_STATUS(0x80000289), W_ERROR(0x48e)},
        {NT_STATUS_OK, WERR_OK}};
 
+static const struct {
+       WERROR werror;
+       NTSTATUS ntstatus;
+} werror_to_ntstatus_map[] = {
+       { W_ERROR(0x5), NT_STATUS_ACCESS_DENIED },
+       { WERR_OK, NT_STATUS_OK }
+};
 
 /*****************************************************************************
 convert a dos eclas/ecode to a NT status32 code
@@ -1460,6 +1467,14 @@ NTSTATUS werror_to_ntstatus(WERROR error)
 {
        int i;
        if (W_ERROR_IS_OK(error)) return NT_STATUS_OK;
+
+       for (i=0; !W_ERROR_IS_OK(werror_to_ntstatus_map[i].werror); i++) {
+               if (W_ERROR_V(error) == 
+                   W_ERROR_V(werror_to_ntstatus_map[i].werror)) {
+                       return werror_to_ntstatus_map[i].ntstatus;
+               }
+       }
+
        for (i=0; NT_STATUS_V(ntstatus_to_werror_map[i].ntstatus); i++) {
                if (W_ERROR_V(error) == 
                    W_ERROR_V(ntstatus_to_werror_map[i].werror)) {
diff --git a/source3/libsmb/gpo.c b/source3/libsmb/gpo.c
new file mode 100644 (file)
index 0000000..0257138
--- /dev/null
@@ -0,0 +1,167 @@
+/* 
+ *  Unix SMB/CIFS implementation.
+ *  Group Policy Object Support
+ *  Copyright (C) Guenther Deschner 2005
+ *  
+ *  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"
+
+#define GPT_INI_SECTION_GENERAL "General"
+#define GPT_INI_PARAMETER_VERSION "Version"
+#define GPT_INI_PARAMETER_DISPLAYNAME "displayName"
+
+struct gpt_ini {
+       uint32 version;
+       const char *display_name;
+};
+
+static uint32 version;
+
+static BOOL do_section(const char *section)
+{
+       DEBUG(10,("do_section: %s\n", section));
+
+       return True;
+}
+
+static BOOL do_parameter(const char *parameter, const char *value)
+{
+       DEBUG(10,("do_parameter: %s, %s\n", parameter, value));
+       
+       if (strequal(parameter, GPT_INI_PARAMETER_VERSION)) {
+               version = atoi(value);
+       }
+       return True;
+}
+
+NTSTATUS ads_gpo_get_sysvol_gpt_version(ADS_STRUCT *ads, 
+                                       TALLOC_CTX *mem_ctx, 
+                                       const char *filesyspath, 
+                                       uint32 *sysvol_version)
+{
+       NTSTATUS status;
+       const char *path;
+       struct cli_state *cli;
+       int fnum;
+       fstring tok;
+       static int io_bufsize = 64512;
+       int read_size = io_bufsize;
+       char *data = NULL;
+       off_t start = 0;
+       off_t nread = 0;
+       int handle = 0;
+       const char *local_file;
+
+       *sysvol_version = 0;
+
+       next_token(&filesyspath, tok, "\\", sizeof(tok));
+       next_token(&filesyspath, tok, "\\", sizeof(tok));
+
+       path = talloc_asprintf(mem_ctx, "\\%s\\gpt.ini", filesyspath);
+       if (path == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       local_file = talloc_asprintf(mem_ctx, "%s/%s", lock_path("gpo_cache"), "gpt.ini");
+       if (local_file == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* FIXME: walk down the dfs tree instead */
+       status = cli_full_connection(&cli, global_myname(), 
+                                    ads->config.ldap_server_name,
+                                    NULL, 0,
+                                    "SYSVOL", "A:",
+                                    ads->auth.user_name, NULL, ads->auth.password,
+                                    CLI_FULL_CONNECTION_USE_KERBEROS,
+                                    Undefined, NULL);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       fnum = cli_open(cli, path, O_RDONLY, DENY_NONE);
+       if (fnum == -1) {
+               return NT_STATUS_NO_SUCH_FILE;
+       }
+
+
+       data = (char *)SMB_MALLOC(read_size);
+       if (data == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       handle = sys_open(local_file, O_WRONLY|O_CREAT|O_TRUNC, 0644);
+
+       if (handle == -1) {
+               return NT_STATUS_NO_SUCH_FILE;
+       }
+        
+       while (1) {
+
+               int n = cli_read(cli, fnum, data, nread + start, read_size);
+
+               if (n <= 0)
+                       break;
+
+               if (write(handle, data, n) != n) {
+                       break;
+               }
+
+               nread += n;
+       }
+
+       cli_close(cli, fnum);
+
+       if (!pm_process(local_file, do_section, do_parameter)) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       *sysvol_version = version;
+
+       SAFE_FREE(data);
+
+       cli_shutdown(cli);
+
+       return NT_STATUS_OK;
+}
+
+/*
+
+perfectly parseable with pm_process() :))
+
+[Unicode]
+Unicode=yes
+[System Access]
+MinimumPasswordAge = 1
+MaximumPasswordAge = 42
+MinimumPasswordLength = 7
+PasswordComplexity = 1
+PasswordHistorySize = 24
+LockoutBadCount = 0
+RequireLogonToChangePassword = 0
+ForceLogoffWhenHourExpire = 0
+ClearTextPassword = 0
+[Kerberos Policy]
+MaxTicketAge = 10
+MaxRenewAge = 7
+MaxServiceAge = 600
+MaxClockSkew = 5
+TicketValidateClient = 1
+[Version]
+signature="$CHICAGO$"
+Revision=1
+*/
index 44cb43c285eaab55443dee00e7c288b0ca5a2d2d..03dbd71e931c2ed854e2516a9d9fc0b1a182996d 100644 (file)
@@ -3734,7 +3734,7 @@ convert_string_to_sid(struct cli_state *ipc_cli,
         }
 
        if (!NT_STATUS_IS_OK(rpccli_lsa_lookup_names(pipe_hnd, ipc_cli->mem_ctx, 
-                                                 pol, 1, &str, &sids, 
+                                                 pol, 1, &str, NULL, &sids, 
                                                  &types))) {
                result = False;
                goto done;
@@ -5927,22 +5927,14 @@ smbc_free_context(SMBCCTX *context,
 void
 smbc_option_set(SMBCCTX *context,
                 char *option_name,
-                ...)
+                void *option_value)
 {
-        va_list args;
-
-        va_start(args, option_name);
-
         if (strcmp(option_name, "debug_stderr") == 0) {
                 /*
                  * Log to standard error instead of standard output.
-                 *
-                 *  optional parameters: none (it can't be turned off once on)
                  */
                 context->internal->_debug_stderr = True;
         }
-
-        va_end(args);
 }
 
 
@@ -5991,6 +5983,7 @@ smbc_init_context(SMBCCTX *context)
                 DEBUGLEVEL = context->debug;
                 
                 load_case_tables();
+                setup_logging( "libsmbclient", True);
 
                 setup_logging("libsmbclient", True);
                 if (context->internal->_debug_stderr) {
index 8b811b06eadb2b890069543c66a72bdb4de9994d..673671d28db05ba02621562f54e38205d61d50c7 100644 (file)
@@ -24,7 +24,7 @@
  Change a password on a remote machine using IPC calls.
 *************************************************************/
 
-BOOL remote_password_change(const char *remote_machine, const char *user_name, 
+NTSTATUS remote_password_change(const char *remote_machine, const char *user_name, 
                            const char *old_passwd, const char *new_passwd,
                            char *err_str, size_t err_str_len)
 {
@@ -41,7 +41,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
        if(!resolve_name( remote_machine, &ip, 0x20)) {
                slprintf(err_str, err_str_len-1, "unable to find an IP address for machine %s.\n",
                        remote_machine );
-               return False;
+               return NT_STATUS_UNSUCCESSFUL;
        }
  
        ZERO_STRUCT(cli);
@@ -49,7 +49,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
        if (!cli_initialise(&cli) || !cli_connect(&cli, remote_machine, &ip)) {
                slprintf(err_str, err_str_len-1, "unable to connect to SMB server on machine %s. Error was : %s.\n",
                        remote_machine, cli_errstr(&cli) );
-               return False;
+               return NT_STATUS_UNSUCCESSFUL;
        }
   
        make_nmb_name(&calling, global_myname() , 0x0);
@@ -59,7 +59,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
                slprintf(err_str, err_str_len-1, "machine %s rejected the session setup. Error was : %s.\n",
                        remote_machine, cli_errstr(&cli) );
                cli_shutdown(&cli);
-               return False;
+               return NT_STATUS_UNSUCCESSFUL;
        }
   
        cli.protocol = PROTOCOL_NT1;
@@ -67,8 +67,9 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
        if (!cli_negprot(&cli)) {
                slprintf(err_str, err_str_len-1, "machine %s rejected the negotiate protocol. Error was : %s.\n",        
                        remote_machine, cli_errstr(&cli) );
+               result = cli_nt_error(&cli);
                cli_shutdown(&cli);
-               return False;
+               return result;
        }
   
        /* Given things like SMB signing, restrict anonymous and the like, 
@@ -90,7 +91,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
                                         "connect to machine %s: %s\n",
                                         remote_machine, cli_errstr(&cli));
                                cli_shutdown(&cli);
-                               return False;
+                               return result;
                        }
 
                        pass_must_change = True;
@@ -105,8 +106,9 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
                if (!cli_session_setup(&cli, "", "", 0, "", 0, "")) {
                        slprintf(err_str, err_str_len-1, "machine %s rejected the session setup. Error was : %s.\n",        
                                 remote_machine, cli_errstr(&cli) );
+                       result = cli_nt_error(&cli);
                        cli_shutdown(&cli);
-                       return False;
+                       return result;
                }
 
                cli_init_creds(&cli, "", "", NULL);
@@ -117,8 +119,9 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
        if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) {
                slprintf(err_str, err_str_len-1, "machine %s rejected the tconX on the IPC$ share. Error was : %s.\n",
                        remote_machine, cli_errstr(&cli) );
+               result = cli_nt_error(&cli);
                cli_shutdown(&cli);
-               return False;
+               return result;
        }
 
        /* Try not to give the password away too easily */
@@ -149,16 +152,18 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
                        if (!cli_oem_change_password(&cli, user_name, new_passwd, old_passwd)) {
                                slprintf(err_str, err_str_len-1, "machine %s rejected the password change: Error was : %s.\n",
                                         remote_machine, cli_errstr(&cli) );
+                               result = cli_nt_error(&cli);
                                cli_shutdown(&cli);
-                               return False;
+                               return result;
                        }
                } else {
                        slprintf(err_str, err_str_len-1,
                                "SAMR connection to machine %s failed. Error was %s, "
                                "but LANMAN password changed are disabled\n",
                                nt_errstr(result), remote_machine);
+                       result = cli_nt_error(&cli);
                        cli_shutdown(&cli);
-                       return False;
+                       return result;
                }
        }
 
@@ -166,7 +171,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
                                                             new_passwd, old_passwd))) {
                /* Great - it all worked! */
                cli_shutdown(&cli);
-               return True;
+               return NT_STATUS_OK;
 
        } else if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) 
                     || NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) {
@@ -175,7 +180,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
                slprintf(err_str, err_str_len-1, "machine %s rejected the password change: Error was : %s.\n",
                         remote_machine, get_friendly_nt_error_msg(result));
                cli_shutdown(&cli);
-               return False;
+               return result;
        }
 
        /* OK, that failed, so try again... */
@@ -197,7 +202,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
                                                old_passwd)))) {
                /* Great - it all worked! */
                cli_shutdown(&cli);
-               return True;
+               return NT_STATUS_OK;
        } else {
                if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) 
                      || NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) {
@@ -207,7 +212,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
                                 "machine %s rejected the (anonymous) password change: Error was : %s.\n",
                                 remote_machine, get_friendly_nt_error_msg(result));
                        cli_shutdown(&cli);
-                       return False;
+                       return result;
                }
                
                /* We have failed to change the user's password, and we think the server
@@ -219,20 +224,21 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name,
                                /* SAMR failed, but the old LanMan protocol worked! */
 
                                cli_shutdown(&cli);
-                               return True;
+                               return NT_STATUS_OK;
                        }
                        slprintf(err_str, err_str_len-1, 
                                 "machine %s rejected the password change: Error was : %s.\n",
                                 remote_machine, cli_errstr(&cli) );
+                       result = cli_nt_error(&cli);
                        cli_shutdown(&cli);
-                       return False;
+                       return result;
                } else {
                        slprintf(err_str, err_str_len-1,
                                "SAMR connection to machine %s failed. Error was %s, "
                                "but LANMAN password changed are disabled\n",
                                nt_errstr(result), remote_machine);
                        cli_shutdown(&cli);
-                       return False;
+                       return NT_STATUS_UNSUCCESSFUL;
                }
        }
 }
index 61c01daa165e5a507072a5c886c5f79438c2e550..57e05dc4bb035d9c28b415e143e224e2a9012a95 100644 (file)
@@ -3,12 +3,14 @@
    Copyright Andrew Tridgell <tridge@samba.org> 2000
    Copyright Tim Potter <tpot@samba.org> 2000
    Copyright Andrew Bartlett <abartlet@samba.org> 2002
+   Copyright Guenther Deschner <gd@samba.org> 2005-2006
 
    largely based on pam_userdb by Cristian Gafton <gafton@redhat.com> 
    also contains large slabs of code from pam_unix by Elliot Lee <sopwith@redhat.com>
    (see copyright below for full details)
 */
 
+#include "includes.h"
 #include "pam_winbind.h"
 
 /* data tokens */
@@ -27,41 +29,122 @@ static void _pam_log(int err, const char *format, ...)
        closelog();
 }
 
+static void _pam_log_debug(int ctrl, int err, const char *format, ...)
+{
+       va_list args;
+
+       if (!(ctrl & WINBIND_DEBUG_ARG)) {
+               return;
+       }
+
+       va_start(args, format);
+       openlog(MODULE_NAME, LOG_CONS|LOG_PID, LOG_AUTH);
+       vsyslog(err, format, args);
+       va_end(args);
+       closelog();
+}
+
 static int _pam_parse(int argc, const char **argv)
 {
-       int ctrl;
+       int ctrl = 0;
+
+       load_case_tables();
+
+       if (!lp_load(dyn_CONFIGFILE,True,False,False,True)) {
+               return -1;
+       }
+
+       if (lp_parm_bool(-1, "pam_winbind", "cached_login", False)) {
+               ctrl |= WINBIND_CACHED_LOGIN;
+       }
+       if (lp_parm_bool(-1, "pam_winbind", "krb5_auth", False)) {
+               ctrl |= WINBIND_KRB5_AUTH;
+       }
+       if (lp_parm_const_string(-1, "pam_winbind", "krb5_ccache_type", NULL) != NULL) {
+               ctrl |= WINBIND_KRB5_CCACHE_TYPE;
+       }
+       if ((lp_parm_const_string(-1, "pam_winbind", "require-membership-of", NULL) != NULL) || 
+           (lp_parm_const_string(-1, "pam_winbind", "require_membership_of", NULL) != NULL)) { 
+               ctrl |= WINBIND_REQUIRED_MEMBERSHIP;
+       }
+       if (lp_parm_bool(-1, "pam_winbind", "create_homedir", False)) {
+               ctrl |= WINBIND_CREATE_HOMEDIR;
+       }
+
        /* step through arguments */
-       for (ctrl = 0; argc-- > 0; ++argv) {
+       for (; argc-- > 0; ++argv) {
 
                /* generic options */
-               
-               if (!strcmp(*argv,"debug"))
+
+               if (!StrCaseCmp(*argv, "debug"))
                        ctrl |= WINBIND_DEBUG_ARG;
-               else if (!strcasecmp(*argv, "use_authtok"))
+               else if (strequal(*argv, "use_authtok"))
                        ctrl |= WINBIND_USE_AUTHTOK_ARG;
-               else if (!strcasecmp(*argv, "use_first_pass"))
+               else if (strequal(*argv, "use_first_pass"))
                        ctrl |= WINBIND_USE_FIRST_PASS_ARG;
-               else if (!strcasecmp(*argv, "try_first_pass"))
+               else if (strequal(*argv, "try_first_pass"))
                        ctrl |= WINBIND_TRY_FIRST_PASS_ARG;
-               else if (!strcasecmp(*argv, "unknown_ok"))
+               else if (strequal(*argv, "unknown_ok"))
                        ctrl |= WINBIND_UNKNOWN_OK_ARG;
-               else if (!strncasecmp(*argv, "require_membership_of", strlen("require_membership_of")))
+               else if (strnequal(*argv, "require_membership_of", strlen("require_membership_of")))
                        ctrl |= WINBIND_REQUIRED_MEMBERSHIP;
-               else if (!strncasecmp(*argv, "require-membership-of", strlen("require-membership-of")))
+               else if (strnequal(*argv, "require-membership-of", strlen("require-membership-of")))
                        ctrl |= WINBIND_REQUIRED_MEMBERSHIP;
+               else if (strequal(*argv, "krb5_auth"))
+                       ctrl |= WINBIND_KRB5_AUTH;
+               else if (strnequal(*argv, "krb5_ccache_type", strlen("krb5_ccache_type")))
+                       ctrl |= WINBIND_KRB5_CCACHE_TYPE;
+               else if (strequal(*argv, "cached_login"))
+                       ctrl |= WINBIND_CACHED_LOGIN;
+               else if (strequal(*argv, "create_homedir"))
+                       ctrl |= WINBIND_CREATE_HOMEDIR;
                else {
                        _pam_log(LOG_ERR, "pam_parse: unknown option; %s", *argv);
                }
+
        }
-       
        return ctrl;
-}
+};
 
 static void _pam_winbind_cleanup_func(pam_handle_t *pamh, void *data, int error_status)
 {
        SAFE_FREE(data);
 }
 
+static const struct ntstatus_errors {
+       const char *ntstatus_string;
+       const char *error_string;
+} ntstatus_errors[] = {
+       {"NT_STATUS_OK", "Success"},
+       {"NT_STATUS_BACKUP_CONTROLLER", "No primary Domain Controler available"},
+       {"NT_STATUS_PWD_TOO_SHORT", "Password too short"},
+       {"NT_STATUS_PWD_TOO_RECENT", "The password of this user is too recent to change"},
+       {"NT_STATUS_PWD_HISTORY_CONFLICT", "Password is already in password history"},
+       {"NT_STATUS_PASSWORD_EXPIRED", "Your password has expired"},
+       {"NT_STATUS_PASSWORD_MUST_CHANGE", "You need to change your password now"},
+       {"NT_STATUS_INVALID_WORKSTATION", "You are not allowed to logon from this workstation"},
+       {"NT_STATUS_INVALID_LOGON_HOURS", "You are not allowed to logon at this time"},
+       {"NT_STATUS_ACCOUNT_EXPIRED", "Your account has expired. Please contact your System administrator"}, /* SCNR */
+       {"NT_STATUS_ACCOUNT_DISABLED", "Your account is disabled. Please contact your System administrator"}, /* SCNR */
+       {"NT_STATUS_ACCOUNT_LOCKED_OUT", "Your account has been locked. Please contact your System administrator"}, /* SCNR */
+       {"NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT", "Invalid Trust Account"},
+       {"NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT", "Invalid Trust Account"},
+       {"NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT", "Invalid Trust Account"},
+       {"NT_STATUS_ACCESS_DENIED", "Access is denied"},
+       {NULL, NULL}
+};
+
+const char *_get_ntstatus_error_string(const char *nt_status_string) 
+{
+       int i;
+       for (i=0; ntstatus_errors[i].ntstatus_string != NULL; i++) {
+               if (strequal(ntstatus_errors[i].ntstatus_string, nt_status_string)) {
+                       return ntstatus_errors[i].error_string;
+               }
+       }
+       return NULL;
+}
+
 /* --- authentication management functions --- */
 
 /* Attempt a conversation */
@@ -70,16 +153,16 @@ static int converse(pam_handle_t *pamh, int nargs,
                    struct pam_message **message,
                    struct pam_response **response)
 {
-    int retval;
-    struct pam_conv *conv;
-
-    retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv ) ;
-    if (retval == PAM_SUCCESS) {
-       retval = conv->conv(nargs, (const struct pam_message **)message,
-                           response, conv->appdata_ptr);
-    }
+       int retval;
+       struct pam_conv *conv;
+
+       retval = pam_get_item(pamh, PAM_CONV, (const void **) &conv );
+       if (retval == PAM_SUCCESS) {
+               retval = conv->conv(nargs, (const struct pam_message **)message,
+                                   response, conv->appdata_ptr);
+       }
        
-    return retval; /* propagate error status */
+       return retval; /* propagate error status */
 }
 
 
@@ -103,11 +186,23 @@ static int _make_remark(pam_handle_t * pamh, int type, const char *text)
        return retval;
 }
 
-static int pam_winbind_request(enum winbindd_cmd req_type,
+static int _make_remark_format(pam_handle_t * pamh, int type, const char *format, ...)
+{
+       va_list args;
+       char *var;
+
+       va_start(args, format);
+       vasprintf(&var, format, args);
+       va_end(args);
+
+       return _make_remark(pamh, type, var);
+}
+
+static int pam_winbind_request(pam_handle_t * pamh, int ctrl,
+                              enum winbindd_cmd req_type,
                               struct winbindd_request *request,
                               struct winbindd_response *response)
 {
-
        /* Fill in request and send down pipe */
        init_request(request, req_type);
        
@@ -140,19 +235,20 @@ static int pam_winbind_request(enum winbindd_cmd req_type,
                        return PAM_SERVICE_ERR;
                }
        }
-       
+
        return PAM_SUCCESS;
 }
 
-static int pam_winbind_request_log(enum winbindd_cmd req_type,
-                              struct winbindd_request *request,
-                              struct winbindd_response *response,
+static int pam_winbind_request_log(pam_handle_t * pamh, 
                                   int ctrl,
+                                  enum winbindd_cmd req_type,
+                                  struct winbindd_request *request,
+                                  struct winbindd_response *response,
                                   const char *user)
 {
        int retval;
 
-        retval = pam_winbind_request(req_type, request, response);
+       retval = pam_winbind_request(pamh, ctrl, req_type, request, response);
 
        switch (retval) {
        case PAM_AUTH_ERR:
@@ -168,13 +264,12 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type,
                _pam_log(LOG_WARNING, "user `%s' password expired", user);
                return retval;
        case PAM_NEW_AUTHTOK_REQD:
-               /* password expired */
+               /* new password required */
                _pam_log(LOG_WARNING, "user `%s' new password required", user);
                return retval;
        case PAM_USER_UNKNOWN:
                /* the user does not exist */
-               if (ctrl & WINBIND_DEBUG_ARG)
-                       _pam_log(LOG_NOTICE, "user `%s' not found",
+               _pam_log_debug(ctrl, LOG_NOTICE, "user `%s' not found",
                                 user);
                if (ctrl & WINBIND_UNKNOWN_OK_ARG) {
                        return PAM_IGNORE;
@@ -191,6 +286,7 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type,
                        /* Otherwise, the authentication looked good */
                        _pam_log(LOG_NOTICE, "user '%s' OK", user);
                }
+       
                return retval;
        default:
                /* we don't know anything about this return value */
@@ -201,24 +297,67 @@ static int pam_winbind_request_log(enum winbindd_cmd req_type,
 }
 
 /* talk to winbindd */
-static int winbind_auth_request(const char *user, const char *pass, const char *member, int ctrl)
+static int winbind_auth_request(pam_handle_t * pamh, 
+                               int ctrl, 
+                               const char *user, 
+                               const char *pass, 
+                               const char *member, 
+                               const char *cctype,
+                               int process_result)
 {
        struct winbindd_request request;
        struct winbindd_response response;
+       int ret;
 
        ZERO_STRUCT(request);
+       ZERO_STRUCT(response);
 
        strncpy(request.data.auth.user, user, 
-                sizeof(request.data.auth.user)-1);
+               sizeof(request.data.auth.user)-1);
 
        strncpy(request.data.auth.pass, pass, 
-                sizeof(request.data.auth.pass)-1);
+               sizeof(request.data.auth.pass)-1);
+
+       request.data.auth.krb5_cc_type[0] = '\0';
+       request.data.auth.uid = -1;
+       
+       request.flags = WBFLAG_PAM_INFO3_TEXT | WBFLAG_PAM_CONTACT_TRUSTDOM;
+
+       if (ctrl & WINBIND_KRB5_AUTH) {
+
+               struct passwd *pwd = NULL;
+
+               _pam_log_debug(ctrl, LOG_DEBUG, "enabling krb5 login flag\n"); 
+
+               request.flags |= WBFLAG_PAM_KRB5 | WBFLAG_PAM_FALLBACK_AFTER_KRB5;
+
+               pwd = getpwnam(user);
+               if (pwd == NULL) {
+                       return PAM_USER_UNKNOWN;
+               }
+               request.data.auth.uid = pwd->pw_uid;
+       }
 
-       if (member == NULL )
-               return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user);
+       if (ctrl & WINBIND_CACHED_LOGIN) {
+               _pam_log_debug(ctrl, LOG_DEBUG, "enabling cached login flag\n"); 
+               request.flags |= WBFLAG_PAM_CACHED_LOGIN;
+       }
+
+       if (cctype != NULL) {
+               strncpy(request.data.auth.krb5_cc_type, cctype, 
+                       sizeof(request.data.auth.krb5_cc_type) - 1);
+               _pam_log_debug(ctrl, LOG_DEBUG, "enabling request for a %s krb5 ccache\n", cctype); 
+       }
+
+       request.data.auth.require_membership_of_sid[0] = '\0';
+
+       if (member != NULL) {
+               strncpy(request.data.auth.require_membership_of_sid, member, 
+                       sizeof(request.data.auth.require_membership_of_sid)-1);
+       }
 
        /* lookup name? */ 
-       if (!strncmp("S-", member, 2) == 0) {
+       if ( (member != NULL) && (strncmp("S-", member, 2) != 0) ) {
                
                struct winbindd_request sid_request;
                struct winbindd_response sid_response;
@@ -226,55 +365,195 @@ static int winbind_auth_request(const char *user, const char *pass, const char *
                ZERO_STRUCT(sid_request);
                ZERO_STRUCT(sid_response);
 
-               if (ctrl & WINBIND_DEBUG_ARG)
-                       _pam_log(LOG_DEBUG, "no sid given, looking up: %s\n", member);
+               _pam_log_debug(ctrl, LOG_DEBUG, "no sid given, looking up: %s\n", member);
 
                /* fortunatly winbindd can handle non-separated names */
-               strcpy(sid_request.data.name.name, member);
+               fstrcpy(sid_request.data.name.name, member);
 
-               if (pam_winbind_request_log(WINBINDD_LOOKUPNAME, &sid_request, &sid_response, ctrl, user)) {
+               if (pam_winbind_request_log(pamh, ctrl, WINBINDD_LOOKUPNAME, &sid_request, &sid_response, user)) {
                        _pam_log(LOG_INFO, "could not lookup name: %s\n", member); 
                        return PAM_AUTH_ERR;
                }
 
                member = sid_response.data.sid.sid;
+
+               strncpy(request.data.auth.require_membership_of_sid, member, 
+                       sizeof(request.data.auth.require_membership_of_sid)-1);
        }
+       
+       ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_AUTH, &request, &response, user);
 
-       strncpy(request.data.auth.require_membership_of_sid, member, 
-               sizeof(request.data.auth.require_membership_of_sid)-1);
+       if ((ctrl & WINBIND_KRB5_AUTH) && 
+           response.data.auth.krb5ccname[0] != '\0') {
+
+               char var[PATH_MAX];
+
+               _pam_log_debug(ctrl, LOG_DEBUG, "request returned KRB5CCNAME: %s", 
+                              response.data.auth.krb5ccname);
        
-        return pam_winbind_request_log(WINBINDD_PAM_AUTH, &request, &response, ctrl, user);
+               snprintf(var, sizeof(var), "KRB5CCNAME=%s", response.data.auth.krb5ccname);
+       
+               ret = pam_putenv(pamh, var);
+               if (ret != PAM_SUCCESS) {
+                       _pam_log(LOG_ERR, "failed to set KRB5CCNAME to %s", var);
+                       return ret;
+               }
+       }
+
+       if (!process_result) {
+               return ret;
+       }
+
+       if (ret) {
+               PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PASSWORD_EXPIRED");
+               PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PASSWORD_MUST_CHANGE");
+               PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_INVALID_WORKSTATION");
+               PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_INVALID_LOGON_HOURS");
+               PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_ACCOUNT_EXPIRED");
+               PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_ACCOUNT_DISABLED");
+               PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_ACCOUNT_LOCKED_OUT");
+               PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT");
+               PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT");
+               PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT");
+       }
+
+       /* handle the case where the auth was ok, but the password must expire right now */
+       /* good catch from Ralf Haferkamp: an expiry of "never" is translated to -1 */
+       if ((response.data.auth.policy.expire > 0) && 
+           (response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire < time(NULL))) {
+
+               ret = PAM_AUTHTOK_EXPIRED;
+
+               _pam_log_debug(ctrl, LOG_DEBUG,"Password has expired (Password was last set: %d, "
+                              "the policy says it should expire here %d (now it's: %d)\n",
+                              response.data.auth.info3.pass_last_set_time,
+                              response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire,
+                              time(NULL));
+
+               PAM_WB_REMARK_DIRECT_RET(pamh, "NT_STATUS_PASSWORD_EXPIRED");
+
+       }
+
+       /* warn a user if the password is about to expire soon */
+       if ((response.data.auth.policy.expire) && 
+           (response.data.auth.info3.pass_last_set_time + response.data.auth.policy.expire > time(NULL) ) ) {
+
+               int days = response.data.auth.policy.expire / SECONDS_PER_DAY;
+               if (days <= DAYS_TO_WARN_BEFORE_PWD_EXPIRES) {
+                       _make_remark_format(pamh, PAM_TEXT_INFO, "Your password will expire in %d days", days);
+               }
+       }
+
+       if (response.data.auth.info3.user_flgs & LOGON_CACHED_ACCOUNT) {
+               _make_remark(pamh, PAM_ERROR_MSG, "Logging on using cached account. Network ressources can be unavailable");
+       }
+
+       /* save the CIFS homedir for pam_cifs / pam_mount */
+       if (response.data.auth.info3.home_dir[0] != '\0') {
+               char *buf;
+
+               if (!asprintf(&buf, "%s", response.data.auth.info3.home_dir)) {
+                       return PAM_BUF_ERR;
+               }
+
+               pam_set_data( pamh, PAM_WINBIND_HOMEDIR, (void *)buf, _pam_winbind_cleanup_func);
+       }
+
+       return ret;
 }
 
 /* talk to winbindd */
-static int winbind_chauthtok_request(const char *user, const char *oldpass,
-                                     const char *newpass, int ctrl)
+static int winbind_chauthtok_request(pam_handle_t * pamh,
+                                    int ctrl,
+                                    const char *user, 
+                                    const char *oldpass,
+                                    const char *newpass) 
 {
        struct winbindd_request request;
        struct winbindd_response response;
+       int ret;
 
        ZERO_STRUCT(request);
+       ZERO_STRUCT(response);
 
-        if (request.data.chauthtok.user == NULL) return -2;
+       if (request.data.chauthtok.user == NULL) return -2;
 
        strncpy(request.data.chauthtok.user, user, 
-                sizeof(request.data.chauthtok.user) - 1);
-
-        if (oldpass != NULL) {
-            strncpy(request.data.chauthtok.oldpass, oldpass, 
-                    sizeof(request.data.chauthtok.oldpass) - 1);
-        } else {
-            request.data.chauthtok.oldpass[0] = '\0';
-        }
-       
-        if (newpass != NULL) {
-            strncpy(request.data.chauthtok.newpass, newpass, 
-                    sizeof(request.data.chauthtok.newpass) - 1);
-        } else {
-            request.data.chauthtok.newpass[0] = '\0';
-        }
+               sizeof(request.data.chauthtok.user) - 1);
+
+       if (oldpass != NULL) {
+               strncpy(request.data.chauthtok.oldpass, oldpass, 
+                       sizeof(request.data.chauthtok.oldpass) - 1);
+       } else {
+               request.data.chauthtok.oldpass[0] = '\0';
+       }
        
-        return pam_winbind_request_log(WINBINDD_PAM_CHAUTHTOK, &request, &response, ctrl, user);
+       if (newpass != NULL) {
+               strncpy(request.data.chauthtok.newpass, newpass, 
+                       sizeof(request.data.chauthtok.newpass) - 1);
+       } else {
+               request.data.chauthtok.newpass[0] = '\0';
+       }
+
+       if (ctrl & WINBIND_KRB5_AUTH) {
+               request.flags = WBFLAG_PAM_KRB5 | WBFLAG_PAM_CONTACT_TRUSTDOM;
+       }
+
+       ret = pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_CHAUTHTOK, &request, &response, user);
+
+       if (ret == PAM_SUCCESS) {
+               return ret;
+       }
+
+       PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_BACKUP_CONTROLLER");
+       PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_ACCESS_DENIED");
+
+       /* TODO: tell the min pwd length ? */
+       PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PWD_TOO_SHORT");
+
+       /* TODO: tell the minage ? */
+       PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PWD_TOO_RECENT");
+
+       /* TODO: tell the history length ? */
+       PAM_WB_REMARK_CHECK_RESPONSE_RET(pamh, response, "NT_STATUS_PWD_HISTORY_CONFLICT");
+
+       if (strequal(response.data.auth.nt_status_string, "NT_STATUS_PASSWORD_RESTRICTION")) {
+
+               /* FIXME: avoid to send multiple PAM messages after another */
+               switch (response.data.auth.reject_reason) {
+                       case 0:
+                               break;
+                       case REJECT_REASON_TOO_SHORT:
+                               PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_TOO_SHORT");
+                               break;
+                       case REJECT_REASON_IN_HISTORY:
+                               PAM_WB_REMARK_DIRECT(pamh, "NT_STATUS_PWD_HISTORY_CONFLICT");
+                               break;
+                       case REJECT_REASON_NOT_COMPLEX:
+                               _make_remark(pamh, PAM_ERROR_MSG, "Password does not meet complexity requirements");
+                               break;
+                       default:
+                               _pam_log_debug(ctrl, LOG_DEBUG,
+                                              "unknown password change reject reason: %d", 
+                                              response.data.auth.reject_reason);
+                               break;
+               }
+
+               _make_remark_format(pamh, PAM_ERROR_MSG,  
+                       "Your password must be at least %d characters; "
+                       "cannot repeat any of the your previous %d passwords"
+                       "%s. "
+                       "Please type a different password. "
+                       "Type a password which meets these requirements in both text boxes.",
+                       response.data.auth.policy.min_length_password,
+                       response.data.auth.policy.password_history,
+                       (response.data.auth.policy.password_properties & DOMAIN_PASSWORD_COMPLEX) ? 
+                               "; must contain capitals, numerals or punctuation; and cannot contain your account or full name" : 
+                               "");
+
+       }
+
+       return ret;
 }
 
 /*
@@ -293,21 +572,21 @@ static int valid_user(const char *user)
 
 static char *_pam_delete(register char *xx)
 {
-    _pam_overwrite(xx);
-    _pam_drop(xx);
-    return NULL;
+       _pam_overwrite(xx);
+       _pam_drop(xx);
+       return NULL;
 }
 
 /*
  * obtain a password from the user
  */
 
-static int _winbind_read_password(pam_handle_t * pamh
-                                 ,unsigned int ctrl
-                                 ,const char *comment
-                                 ,const char *prompt1
-                                 ,const char *prompt2
-                                 ,const char **pass)
+static int _winbind_read_password(pam_handle_t * pamh,
+                                 unsigned int ctrl,
+                                 const char *comment,
+                                 const char *prompt1,
+                                 const char *prompt2,
+                                 const char **pass)
 {
        int authtok_flag;
        int retval;
@@ -391,16 +670,15 @@ static int _winbind_read_password(pam_handle_t * pamh
 
                        if (retval == PAM_SUCCESS) {    /* a good conversation */
 
-                               token = x_strdup(resp[i - replies].resp);
+                               token = SMB_STRDUP(resp[i - replies].resp);
                                if (token != NULL) {
                                        if (replies == 2) {
-
                                                /* verify that password entered correctly */
                                                if (!resp[i - 1].resp
-                                                   || strcmp(token, resp[i - 1].resp)) {
+                                                   || StrCaseCmp(token, resp[i - 1].resp)) {
                                                        _pam_delete(token);     /* mistyped */
                                                        retval = PAM_AUTHTOK_RECOVER_ERR;
-                                                       _make_remark(pamh                                                                   ,PAM_ERROR_MSG, MISTYPED_PASS);
+                                                       _make_remark(pamhPAM_ERROR_MSG, MISTYPED_PASS);
                                                }
                                        }
                                } else {
@@ -423,8 +701,7 @@ static int _winbind_read_password(pam_handle_t * pamh
        }
 
        if (retval != PAM_SUCCESS) {
-               if (on(WINBIND_DEBUG_ARG, ctrl))
-                       _pam_log(LOG_DEBUG,
+               _pam_log_debug(ctrl, LOG_DEBUG,
                                 "unable to obtain a password");
                return retval;
        }
@@ -434,10 +711,8 @@ static int _winbind_read_password(pam_handle_t * pamh
        
        retval = pam_set_item(pamh, authtok_flag, token);
        _pam_delete(token);     /* clean it up */
-       if (retval != PAM_SUCCESS
-           || (retval = pam_get_item(pamh, authtok_flag
-                                     ,(const void **) &item))
-           != PAM_SUCCESS) {
+       if (retval != PAM_SUCCESS || 
+           (retval = pam_get_item(pamh, authtok_flag, (const void **) &item)) != PAM_SUCCESS) {
                
                _pam_log(LOG_CRIT, "error manipulating password");
                return retval;
@@ -450,92 +725,145 @@ static int _winbind_read_password(pam_handle_t * pamh
        return PAM_SUCCESS;
 }
 
+const char *get_conf_item_string(int argc, 
+                                const char **argv, 
+                                int ctrl, 
+                                const char *item, 
+                                int flag)
+{
+       int i = 0;
+       char *parm = NULL;
+       const char *parm_opt = NULL;
+
+       if (!(ctrl & flag)) {
+               goto out;
+       }
+
+       /* let the pam opt take precedence over the smb.conf option */
+       parm_opt = lp_parm_const_string(-1, "pam_winbind", item, NULL);
+
+       for ( i=0; i<argc; i++ ) {
+
+               if ((strncmp(argv[i], item, strlen(item)) == 0)) {
+                       char *p;
+
+                       parm = SMB_STRDUP(argv[i]);
+
+                       if ( (p = strchr( parm, '=' )) == NULL) {
+                               _pam_log(LOG_INFO, "no \"=\" delimiter for \"%s\" found\n", item);
+                               goto out;
+                       }
+                       SAFE_FREE(parm);
+                       _pam_log_debug(ctrl, LOG_INFO, "PAM config: %s '%s'\n", item, p+1);
+                       return p + 1;
+               }
+       }
+
+       _pam_log_debug(ctrl, LOG_INFO, "CONFIG file: %s '%s'\n", item, parm_opt);
+out:
+       SAFE_FREE(parm);
+       return parm_opt;
+}
+
+const char *get_krb5_cc_type_from_config(int argc, const char **argv, int ctrl)
+{
+       return get_conf_item_string(argc, argv, ctrl, "krb5_ccache_type", WINBIND_KRB5_CCACHE_TYPE);
+}
+
+const char *get_member_from_config(int argc, const char **argv, int ctrl)
+{
+       const char *ret = NULL;
+       ret = get_conf_item_string(argc, argv, ctrl, "require_membership_of", WINBIND_REQUIRED_MEMBERSHIP);
+       if (ret) {
+               return ret;
+       }
+       return get_conf_item_string(argc, argv, ctrl, "require-membership-of", WINBIND_REQUIRED_MEMBERSHIP);
+}
+
 PAM_EXTERN
 int pam_sm_authenticate(pam_handle_t *pamh, int flags,
                        int argc, const char **argv)
 {
-     const char *username;
-     const char *password;
-     const char *member = NULL;
-     int retval = PAM_AUTH_ERR;
-     int i;
-    
-     /* parse arguments */
-     int ctrl = _pam_parse(argc, argv);
-
-     /* Get the username */
-     retval = pam_get_user(pamh, &username, NULL);
-     if ((retval != PAM_SUCCESS) || (!username)) {
-        if (ctrl & WINBIND_DEBUG_ARG)
-            _pam_log(LOG_DEBUG,"can not get the username");
-        return PAM_SERVICE_ERR;
-     }
-     
-     retval = _winbind_read_password(pamh, ctrl, NULL, 
-                                    "Password: ", NULL,
-                                    &password);
-     
-     if (retval != PAM_SUCCESS) {
-        _pam_log(LOG_ERR, "Could not retrieve user's password");
-        return PAM_AUTHTOK_ERR;
-     }
-     
-     if (ctrl & WINBIND_DEBUG_ARG) {
-
-            /* Let's not give too much away in the log file */
+       const char *username;
+       const char *password;
+       const char *member = NULL;
+       const char *cctype = NULL;
+       int retval = PAM_AUTH_ERR;
+
+       /* parse arguments */
+       int ctrl = _pam_parse(argc, argv);
+       if (ctrl == -1) {
+               return PAM_SYSTEM_ERR;
+       }
+
+       _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_authenticate");
+
+       /* Get the username */
+       retval = pam_get_user(pamh, &username, NULL);
+       if ((retval != PAM_SUCCESS) || (!username)) {
+               _pam_log_debug(ctrl, LOG_DEBUG, "can not get the username");
+               return PAM_SERVICE_ERR;
+       }
+
+       retval = _winbind_read_password(pamh, ctrl, NULL, 
+                                       "Password: ", NULL,
+                                       &password);
+
+       if (retval != PAM_SUCCESS) {
+               _pam_log(LOG_ERR, "Could not retrieve user's password");
+               return PAM_AUTHTOK_ERR;
+       }
+
+       /* Let's not give too much away in the log file */
 
 #ifdef DEBUG_PASSWORD
-        _pam_log(LOG_INFO, "Verify user `%s' with password `%s'",
-                 username, password);
+       _pam_log_debug(ctrl, LOG_INFO, "Verify user `%s' with password `%s'", 
+                      username, password);
 #else
-        _pam_log(LOG_INFO, "Verify user `%s'", username);
+       _pam_log_debug(ctrl, LOG_INFO, "Verify user `%s'", username);
 #endif
-     }
 
-     if (ctrl & WINBIND_REQUIRED_MEMBERSHIP) {
-            
-         for ( i=0; i<argc; i++ ) {
+       member = get_member_from_config(argc, argv, ctrl);
 
-            if ((strncmp(argv[i], "require_membership_of", strlen("require_membership_of")) == 0) ||
-                (strncmp(argv[i], "require-membership-of", strlen("require-membership-of")) == 0)) {
+       cctype = get_krb5_cc_type_from_config(argc, argv, ctrl);
 
-               char *p;
-               char *parm = strdup(argv[i]);
+       /* Now use the username to look up password */
+       retval = winbind_auth_request(pamh, ctrl, username, password, member, cctype, True);
 
-               if ( (p = strchr( parm, '=' )) == NULL) {
-                  _pam_log(LOG_INFO, "no \"=\" delimiter for \"require_membership_of\" found\n");
-                  break;
-               }
+       if (retval == PAM_NEW_AUTHTOK_REQD ||
+           retval == PAM_AUTHTOK_EXPIRED) {
 
-               member = strdup(p+1);
-            }
-         }
-     }
+               char *buf;
 
-     /* Now use the username to look up password */
-     retval = winbind_auth_request(username, password, member, ctrl);
-     if (retval == PAM_NEW_AUTHTOK_REQD ||
-        retval == PAM_AUTHTOK_EXPIRED) {
-       
-       char *buf;
-                       
-       if (!asprintf(&buf, "%d", retval)) {
-               return PAM_BUF_ERR;
-       }
+               if (!asprintf(&buf, "%d", retval)) {
+                       return PAM_BUF_ERR;
+               }
 
-       pam_set_data( pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, (void *)buf, _pam_winbind_cleanup_func);
+               pam_set_data( pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, (void *)buf, _pam_winbind_cleanup_func);
 
-       return PAM_SUCCESS;
-     }
-     
-     return retval;
+               return PAM_SUCCESS;
+       }
+
+       return retval;
 }
 
 PAM_EXTERN
 int pam_sm_setcred(pam_handle_t *pamh, int flags,
                   int argc, const char **argv)
 {
-    return PAM_SUCCESS;
+       /* parse arguments */
+       int ctrl = _pam_parse(argc, argv);
+       if (ctrl == -1) {
+               return PAM_SYSTEM_ERR;
+       }
+
+       _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_setcred");
+
+       if (flags & PAM_DELETE_CRED) {
+               return pam_sm_close_session(pamh, flags, argc, argv);
+       }
+
+       return PAM_SUCCESS;
 }
 
 /*
@@ -546,110 +874,234 @@ PAM_EXTERN
 int pam_sm_acct_mgmt(pam_handle_t *pamh, int flags,
                   int argc, const char **argv)
 {
-    const char *username;
-    void *tmp = NULL;
+       const char *username;
+       int retval = PAM_USER_UNKNOWN;
+       void *tmp = NULL;
+
+       /* parse arguments */
+       int ctrl = _pam_parse(argc, argv);
+       if (ctrl == -1) {
+               return PAM_SYSTEM_ERR;
+       }
 
-    int retval = PAM_USER_UNKNOWN;
+       _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_acct_mgmt");
 
-    /* parse arguments */
-    int ctrl = _pam_parse(argc, argv);
 
-    /* Get the username */
-    retval = pam_get_user(pamh, &username, NULL);
-    if ((retval != PAM_SUCCESS) || (!username)) {
-       if (ctrl & WINBIND_DEBUG_ARG)
-           _pam_log(LOG_DEBUG,"can not get the username");
-       return PAM_SERVICE_ERR;
-    }
+       /* Get the username */
+       retval = pam_get_user(pamh, &username, NULL);
+       if ((retval != PAM_SUCCESS) || (!username)) {
+               _pam_log_debug(ctrl, LOG_DEBUG,"can not get the username");
+               return PAM_SERVICE_ERR;
+       }
 
-    /* Verify the username */
-    retval = valid_user(username);
-    switch (retval) {
+       /* Verify the username */
+       retval = valid_user(username);
+       switch (retval) {
        case -1:
-           /* some sort of system error. The log was already printed */
-           return PAM_SERVICE_ERR;
+               /* some sort of system error. The log was already printed */
+               return PAM_SERVICE_ERR;
        case 1:
-           /* the user does not exist */
-           if (ctrl & WINBIND_DEBUG_ARG)
-               _pam_log(LOG_NOTICE, "user `%s' not found",
-                        username);
-           if (ctrl & WINBIND_UNKNOWN_OK_ARG)
-               return PAM_IGNORE;
-           return PAM_USER_UNKNOWN;
+               /* the user does not exist */
+               _pam_log_debug(ctrl, LOG_NOTICE, "user `%s' not found", username);
+               if (ctrl & WINBIND_UNKNOWN_OK_ARG) {
+                       return PAM_IGNORE;
+               }
+               return PAM_USER_UNKNOWN;
        case 0:
-           pam_get_data( pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, (const void **)&tmp);
-
-           if (tmp != NULL) {
-               retval = atoi(tmp);
-               switch (retval) {
-               case PAM_AUTHTOK_EXPIRED:
-                    /* fall through, since new token is required in this case */
-               case PAM_NEW_AUTHTOK_REQD:
-                    _pam_log(LOG_WARNING, "pam_sm_acct_mgmt success but %s is set",
-                             PAM_WINBIND_NEW_AUTHTOK_REQD);
-                    _pam_log(LOG_NOTICE, "user '%s' needs new password", username);
-                    /* PAM_AUTHTOKEN_REQD does not exist, but is documented in the manpage */
-                    return PAM_NEW_AUTHTOK_REQD;
-               default:
-                    _pam_log(LOG_WARNING, "pam_sm_acct_mgmt success");
-                    _pam_log(LOG_NOTICE, "user '%s' granted access", username);
-                    return PAM_SUCCESS;
-               }
-           }
-
-           /* Otherwise, the authentication looked good */
-           _pam_log(LOG_NOTICE, "user '%s' granted access", username);
-           return PAM_SUCCESS;
+               pam_get_data( pamh, PAM_WINBIND_NEW_AUTHTOK_REQD, (const void **)&tmp);
+               if (tmp != NULL) {
+                       retval = atoi(tmp);
+                       switch (retval) {
+                       case PAM_AUTHTOK_EXPIRED:
+                               /* fall through, since new token is required in this case */
+                       case PAM_NEW_AUTHTOK_REQD:
+                               _pam_log(LOG_WARNING, "pam_sm_acct_mgmt success but %s is set", 
+                                        PAM_WINBIND_NEW_AUTHTOK_REQD);
+                               _pam_log(LOG_NOTICE, "user '%s' needs new password", username);
+                               /* PAM_AUTHTOKEN_REQD does not exist, but is documented in the manpage */
+                               return PAM_NEW_AUTHTOK_REQD; 
+                       default:
+                               _pam_log(LOG_WARNING, "pam_sm_acct_mgmt success");
+                               _pam_log(LOG_NOTICE, "user '%s' granted access", username);
+                               return PAM_SUCCESS;
+                       }
+               }
+
+               /* Otherwise, the authentication looked good */
+               _pam_log(LOG_NOTICE, "user '%s' granted access", username);
+               return PAM_SUCCESS;
        default:
-           /* we don't know anything about this return value */
-           _pam_log(LOG_ERR, "internal module error (retval = %d, user = `%s'",
-                    retval, username);
-           return PAM_SERVICE_ERR;
-    }
-    
-    /* should not be reached */
-    return PAM_IGNORE;
+               /* we don't know anything about this return value */
+               _pam_log(LOG_ERR, "internal module error (retval = %d, user = `%s')", 
+                        retval, username);
+               return PAM_SERVICE_ERR;
+       }
+
+       /* should not be reached */
+       return PAM_IGNORE;
 }
+
 PAM_EXTERN
 int pam_sm_open_session(pam_handle_t *pamh, int flags,
-                int argc, const char **argv)
+                       int argc, const char **argv)
 {
-        /* parse arguments */
-        int ctrl = _pam_parse(argc, argv);
-        if (ctrl & WINBIND_DEBUG_ARG)
-              _pam_log(LOG_DEBUG,"libpam_winbind:pam_sm_open_session handler");
-        return PAM_SUCCESS;
+       /* parse arguments */
+       int ctrl = _pam_parse(argc, argv);
+       if (ctrl == -1) {
+               return PAM_SYSTEM_ERR;
+       }
+
+       _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_open_session handler");
+
+
+       if (ctrl & WINBIND_CREATE_HOMEDIR) {
+
+               struct passwd *pwd = NULL;
+               const char *username;
+               int ret;
+               fstring tok;
+               fstring create_dir;
+               SMB_STRUCT_STAT sbuf;
+
+               /* Get the username */
+               ret = pam_get_user(pamh, &username, NULL);
+               if ((ret != PAM_SUCCESS) || (!username)) {
+                       _pam_log_debug(ctrl, LOG_DEBUG, "can not get the username");
+                       return PAM_SERVICE_ERR;
+               }
+
+               pwd = getpwnam(username);
+               if (pwd == NULL) {
+                       _pam_log_debug(ctrl, LOG_DEBUG, "can not get the username");
+                       return PAM_SERVICE_ERR;
+               }
+
+               _pam_log_debug(ctrl, LOG_DEBUG, "homedir is: %s", pwd->pw_dir);
+
+               if (directory_exist(pwd->pw_dir, &sbuf)) {
+                       return PAM_SUCCESS;
+               }
+
+               fstrcpy(create_dir, "/");
+               while (next_token((const char **)&pwd->pw_dir, tok, "/", sizeof(tok))) {
+                       
+                       mode_t mode = 0755;
+
+                       fstrcat(create_dir, tok);
+                       fstrcat(create_dir, "/");
+
+                       if (!directory_exist(create_dir, &sbuf)) {
+                               if (mkdir(create_dir, mode) != 0) {
+                                       _pam_log(LOG_ERR, "could not create dir: %s (%s)", 
+                                                create_dir, strerror(errno));
+                                       return PAM_SERVICE_ERR;
+                               }
+                       } 
+               }
+
+               if (sys_chown(create_dir, pwd->pw_uid, pwd->pw_gid) != 0) {
+                       _pam_log(LOG_ERR, "failed to chown user homedir: %s (%s)", 
+                                create_dir, strerror(errno));
+                       return PAM_SERVICE_ERR;
+               }
+       }
+
+       return PAM_SUCCESS;
 }
+
 PAM_EXTERN
 int pam_sm_close_session(pam_handle_t *pamh, int flags,
-                int argc, const char **argv)
+                        int argc, const char **argv)
 {
-        /* parse arguments */
-        int ctrl = _pam_parse(argc, argv);
-        if (ctrl & WINBIND_DEBUG_ARG)
-              _pam_log(LOG_DEBUG,"libpam_winbind:pam_sm_close_session handler");
-        return PAM_SUCCESS;
+       /* parse arguments */
+       int ctrl = _pam_parse(argc, argv);
+       if (ctrl == -1) {
+               return PAM_SYSTEM_ERR;
+       }
+
+       _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_close_session handler");
+
+       if (!(flags & PAM_DELETE_CRED)) {
+               return PAM_SUCCESS;
+       }
+
+       if (ctrl & WINBIND_KRB5_AUTH) {
+
+               /* destroy the ccache here */
+               struct winbindd_request request;
+               struct winbindd_response response;
+               const char *user;
+               const char *ccname = NULL;
+               struct passwd *pwd = NULL;
+
+               int retval;
+
+               ZERO_STRUCT(request);
+               ZERO_STRUCT(response);
+
+               retval = pam_get_user(pamh, &user, "Username: ");
+               if (retval == PAM_SUCCESS) {
+                       if (user == NULL) {
+                               _pam_log(LOG_ERR, "username was NULL!");
+                               return PAM_USER_UNKNOWN;
+                       }
+                       if (retval == PAM_SUCCESS) {
+                               _pam_log_debug(ctrl, LOG_DEBUG, "username [%s] obtained", user);
+                       }
+               } else {
+                       _pam_log_debug(ctrl, LOG_DEBUG, "could not identify user");
+                       return retval;
+               }
+
+               ccname = pam_getenv(pamh, "KRB5CCNAME");
+               if (ccname == NULL) {
+                       _pam_log_debug(ctrl, LOG_DEBUG, "user has no KRB5CCNAME environment");
+                       return PAM_BUF_ERR;
+               }
+
+               fstrcpy(request.data.logoff.user, user);
+               fstrcpy(request.data.logoff.krb5ccname, ccname);
+
+               pwd = getpwnam(user);
+               if (pwd == NULL) {
+                       return PAM_USER_UNKNOWN;
+               }
+               request.data.logoff.uid = pwd->pw_uid;
+
+               request.flags = WBFLAG_PAM_KRB5 | WBFLAG_PAM_CONTACT_TRUSTDOM;
+
+               return pam_winbind_request_log(pamh, ctrl, WINBINDD_PAM_LOGOFF, &request, &response, user);
+       }
+       
+       return PAM_SUCCESS;
 }
 
 
 
-PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
-                               int argc, const char **argv)
+PAM_EXTERN 
+int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
+                    int argc, const char **argv)
 {
        unsigned int lctrl;
        int retval;
-       unsigned int ctrl = _pam_parse(argc, argv);
+       unsigned int ctrl;
 
        /* <DO NOT free() THESE> */
        const char *user;
-       const char *member = NULL;
        char *pass_old, *pass_new;
        /* </DO NOT free() THESE> */
 
-       char *Announce;
+       fstring Announce;
        
        int retry = 0;
 
+       ctrl = _pam_parse(argc, argv);
+       if (ctrl == -1) {
+               return PAM_SYSTEM_ERR;
+       }
+
+       _pam_log_debug(ctrl, LOG_DEBUG,"pam_winbind: pam_sm_chauthtok");
+
        /*
         * First get the name of a user
         */
@@ -659,13 +1111,13 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
                        _pam_log(LOG_ERR, "username was NULL!");
                        return PAM_USER_UNKNOWN;
                }
-               if (retval == PAM_SUCCESS && on(WINBIND_DEBUG_ARG, ctrl))
-                       _pam_log(LOG_DEBUG, "username [%s] obtained",
+               if (retval == PAM_SUCCESS) {
+                       _pam_log_debug(ctrl, LOG_DEBUG, "username [%s] obtained",
                                 user);
+               }
        } else {
-               if (on(WINBIND_DEBUG_ARG, ctrl))
-                       _pam_log(LOG_DEBUG,
-                                "password - could not identify user");
+               _pam_log_debug(ctrl, LOG_DEBUG,
+                        "password - could not identify user");
                return retval;
        }
 
@@ -678,33 +1130,24 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
                
                /* instruct user what is happening */
 #define greeting "Changing password for "
-               Announce = (char *) malloc(sizeof(greeting) + strlen(user));
-               if (Announce == NULL) {
-               _pam_log(LOG_CRIT, 
-                        "password - out of memory");
-               return PAM_BUF_ERR;
-               }
-               (void) strcpy(Announce, greeting);
-               (void) strcpy(Announce + sizeof(greeting) - 1, user);
+               fstrcpy(Announce, greeting);
+               fstrcat(Announce, user);
 #undef greeting
                
                lctrl = ctrl | WINBIND__OLD_PASSWORD;
-               retval = _winbind_read_password(pamh, lctrl
-                                               ,Announce
-                                               ,"(current) NT password: "
-                                               ,NULL
-                                               ,(const char **) &pass_old);
-               free(Announce);
-               
+               retval = _winbind_read_password(pamh, lctrl,
+                                               Announce,
+                                               "(current) NT password: ",
+                                               NULL,
+                                               (const char **) &pass_old);
                if (retval != PAM_SUCCESS) {
-                       _pam_log(LOG_NOTICE
-                                ,"password - (old) token not obtained");
+                       _pam_log(LOG_NOTICE, "password - (old) token not obtained");
                        return retval;
                }
                /* verify that this is the password for this user */
                
-               retval = winbind_auth_request(user, pass_old, member, ctrl);
-               
+               retval = winbind_auth_request(pamh, ctrl, user, pass_old, NULL, NULL, False);
+
                if (retval != PAM_ACCT_EXPIRED 
                    && retval != PAM_AUTHTOK_EXPIRED
                    && retval != PAM_NEW_AUTHTOK_REQD 
@@ -716,8 +1159,7 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
                retval = pam_set_item(pamh, PAM_OLDAUTHTOK, (const void *) pass_old);
                pass_old = NULL;
                if (retval != PAM_SUCCESS) {
-                       _pam_log(LOG_CRIT, 
-                                "failed to set PAM_OLDAUTHTOK");
+                       _pam_log(LOG_CRIT, "failed to set PAM_OLDAUTHTOK");
                }
        } else if (flags & PAM_UPDATE_AUTHTOK) {
        
@@ -729,8 +1171,8 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
                 * get the old token back. 
                 */
                
-               retval = pam_get_item(pamh, PAM_OLDAUTHTOK
-                                     ,(const void **) &pass_old);
+               retval = pam_get_item(pamh, PAM_OLDAUTHTOK,
+                                     (const void **) &pass_old);
                
                if (retval != PAM_SUCCESS) {
                        _pam_log(LOG_NOTICE, "user not authenticated");
@@ -750,17 +1192,15 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
                         * password -- needed for pluggable password strength checking
                         */
                        
-                       retval = _winbind_read_password(pamh, lctrl
-                                                       ,NULL
-                                                       ,"Enter new NT password: "
-                                                       ,"Retype new NT password: "
-                                                       ,(const char **) &pass_new);
+                       retval = _winbind_read_password(pamh, lctrl,
+                                                       NULL,
+                                                       "Enter new NT password: ",
+                                                       "Retype new NT password: ",
+                                                       (const char **) &pass_new);
                        
                        if (retval != PAM_SUCCESS) {
-                               if (on(WINBIND_DEBUG_ARG, ctrl)) {
-                                       _pam_log(LOG_ALERT
-                                                ,"password - new password not obtained");
-                               }
+                               _pam_log_debug(ctrl, LOG_ALERT
+                                        ,"password - new password not obtained");
                                pass_old = NULL;/* tidy up */
                                return retval;
                        }
@@ -781,14 +1221,30 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
                 * rebuild the password database file.
                 */
 
-               retval = winbind_chauthtok_request(user, pass_old, pass_new, ctrl);
-               _pam_overwrite(pass_new);
-               _pam_overwrite(pass_old);
-               pass_old = pass_new = NULL;
+               retval = winbind_chauthtok_request(pamh, ctrl, user, pass_old, pass_new);
+               if (retval) {
+                       _pam_overwrite(pass_new);
+                       _pam_overwrite(pass_old);
+                       pass_old = pass_new = NULL;
+                       return retval;
+               }
+
+               /* just in case we need krb5 creds after a password change over msrpc */
+
+               if (ctrl & WINBIND_KRB5_AUTH) {
+
+                       const char *member = get_member_from_config(argc, argv, ctrl);
+                       const char *cctype = get_krb5_cc_type_from_config(argc, argv, ctrl);
+
+                       retval = winbind_auth_request(pamh, ctrl, user, pass_new, member, cctype, False);
+                       _pam_overwrite(pass_new);
+                       _pam_overwrite(pass_old);
+                       pass_old = pass_new = NULL;
+               }
        } else {
                retval = PAM_SERVICE_ERR;
        }
-       
+
        return retval;
 }
 
@@ -797,13 +1253,13 @@ PAM_EXTERN int pam_sm_chauthtok(pam_handle_t * pamh, int flags,
 /* static module data */
 
 struct pam_module _pam_winbind_modstruct = {
-     MODULE_NAME,
-     pam_sm_authenticate,
-     pam_sm_setcred,
-     pam_sm_acct_mgmt,
-     pam_sm_open_session,
-     pam_sm_close_session,
-     pam_sm_chauthtok
+       MODULE_NAME,
+       pam_sm_authenticate,
+       pam_sm_setcred,
+       pam_sm_acct_mgmt,
+       pam_sm_open_session,
+       pam_sm_close_session,
+       pam_sm_chauthtok
 };
 
 #endif
@@ -812,6 +1268,7 @@ struct pam_module _pam_winbind_modstruct = {
  * Copyright (c) Andrew Tridgell  <tridge@samba.org>   2000
  * Copyright (c) Tim Potter       <tpot@samba.org>     2000
  * Copyright (c) Andrew Bartlettt <abartlet@samba.org> 2002
+ * Copyright (c) Guenther Deschner <gd@samba.org>      2005-2006
  * Copyright (c) Jan Rêkorajski 1999.
  * Copyright (c) Andrew G. Morgan 1996-8.
  * Copyright (c) Alex O. Yuriev, 1996.
index 86ba9772879f177c9cea2659c14813ced6e99d4e..1e38269e0eebe12ccd00ebdc8b19700d24f7c2d6 100644 (file)
@@ -17,6 +17,7 @@
 #include <sys/stat.h>
 #include <fcntl.h>
 #include <errno.h>
+#include <time.h>
 
 #include <config.h>
 
@@ -83,8 +84,10 @@ do {                             \
 #define WINBIND_USE_FIRST_PASS_ARG (1<<4)
 #define WINBIND__OLD_PASSWORD (1<<5)
 #define WINBIND_REQUIRED_MEMBERSHIP (1<<6)
-
-#define PAM_WINBIND_NEW_AUTHTOK_REQD "PAM_WINBIND_NEW_AUTHTOK_REQD"
+#define WINBIND_KRB5_AUTH (1<<7)
+#define WINBIND_KRB5_CCACHE_TYPE (1<<8)
+#define WINBIND_CACHED_LOGIN (1<<9)
+#define WINBIND_CREATE_HOMEDIR (1<<10)
 
 /*
  * here is the string to inform the user that the new passwords they
@@ -96,4 +99,53 @@ do {                             \
 #define on(x, y) (x & y)
 #define off(x, y) (!(x & y))
 
+#define PAM_WINBIND_NEW_AUTHTOK_REQD "PAM_WINBIND_NEW_AUTHTOK_REQD"
+#define PAM_WINBIND_HOMEDIR "PAM_WINBIND_HOMEDIR"
+
+#define SECONDS_PER_DAY 86400
+
+#define DAYS_TO_WARN_BEFORE_PWD_EXPIRES 5
+
 #include "winbind_client.h"
+
+#define PAM_WB_REMARK_DIRECT(h,x)\
+{\
+       const char *error_string = NULL; \
+       error_string = _get_ntstatus_error_string(x);\
+       if (error_string != NULL) {\
+               _make_remark(h, PAM_ERROR_MSG, error_string);\
+       } else {\
+               _make_remark(h, PAM_ERROR_MSG, x);\
+       };\
+};
+
+#define PAM_WB_REMARK_DIRECT_RET(h,x)\
+{\
+       const char *error_string = NULL; \
+       error_string = _get_ntstatus_error_string(x);\
+       if (error_string != NULL) {\
+               _make_remark(h, PAM_ERROR_MSG, error_string);\
+               return ret;\
+       };\
+       _make_remark(h, PAM_ERROR_MSG, x);\
+       return ret;\
+};
+       
+#define PAM_WB_REMARK_CHECK_RESPONSE_RET(h,x,y)\
+{\
+       const char *ntstatus = x.data.auth.nt_status_string; \
+       const char *error_string = NULL; \
+       if (strequal(ntstatus,y)) {\
+               error_string = _get_ntstatus_error_string(y);\
+               if (error_string != NULL) {\
+                       _make_remark(h, PAM_ERROR_MSG, error_string);\
+                       return ret;\
+               };\
+               if (x.data.auth.error_string[0] != '\0') {\
+                       _make_remark(h, PAM_ERROR_MSG, x.data.auth.error_string);\
+                       return ret;\
+               };\
+               _make_remark(h, PAM_ERROR_MSG, y);\
+               return ret;\
+       };\
+};
index fcab76b033ac19fbf1b7db8c22d0963d46d86fc9..ff0f15a1224b7fe27dd6a343738ae8906471ef0f 100644 (file)
@@ -247,7 +247,7 @@ BOOL winbind_gid_to_sid(DOM_SID *sid, gid_t gid)
        return (result == NSS_STATUS_SUCCESS);
 }
 
-BOOL winbind_allocate_rid(uint32 *rid)
+BOOL winbind_allocate_uid(uid_t *uid)
 {
        struct winbindd_request request;
        struct winbindd_response response;
@@ -260,18 +260,19 @@ BOOL winbind_allocate_rid(uint32 *rid)
 
        /* Make request */
 
-       result = winbindd_request_response(WINBINDD_ALLOCATE_RID, &request, &response);
+       result = winbindd_request_response(WINBINDD_ALLOCATE_UID,
+                                          &request, &response);
 
        if (result != NSS_STATUS_SUCCESS)
                return False;
 
        /* Copy out result */
-       *rid = response.data.rid;
+       *uid = response.data.uid;
 
        return True;
 }
 
-BOOL winbind_allocate_rid_and_gid(uint32 *rid, gid_t *gid)
+BOOL winbind_allocate_gid(gid_t *gid)
 {
        struct winbindd_request request;
        struct winbindd_response response;
@@ -284,15 +285,14 @@ BOOL winbind_allocate_rid_and_gid(uint32 *rid, gid_t *gid)
 
        /* Make request */
 
-       result = winbindd_request_response(WINBINDD_ALLOCATE_RID_AND_GID, &request,
-                                 &response);
+       result = winbindd_request_response(WINBINDD_ALLOCATE_GID,
+                                          &request, &response);
 
        if (result != NSS_STATUS_SUCCESS)
                return False;
 
        /* Copy out result */
-       *rid = response.data.rid_and_gid.rid;
-       *gid = response.data.rid_and_gid.gid;
+       *gid = response.data.gid;
 
        return True;
 }
index 793a05f1790e095b210e4d16a7a7e0eb90843b90..571a1b3e19f4c94b52bc17bb188717d126d0d081 100644 (file)
@@ -199,7 +199,7 @@ static BOOL wbinfo_get_userdomgroups(const char *user_sid)
                return False;
 
        if (response.data.num_entries != 0)
-               d_printf("%s", (char *)response.extra_data);
+               printf("%s", (char *)response.extra_data);
        
        SAFE_FREE(response.extra_data);
 
@@ -260,15 +260,19 @@ static BOOL wbinfo_wins_byip(char *ip)
 
 /* List trusted domains */
 
-static BOOL wbinfo_list_domains(void)
+static BOOL wbinfo_list_domains(BOOL list_all_domains)
 {
+       struct winbindd_request request;
        struct winbindd_response response;
 
+       ZERO_STRUCT(request);
        ZERO_STRUCT(response);
 
        /* Send request */
 
-       if (winbindd_request_response(WINBINDD_LIST_TRUSTDOM, NULL, &response) !=
+       request.data.list_all_domains = list_all_domains;
+
+       if (winbindd_request_response(WINBINDD_LIST_TRUSTDOM, &request, &response) !=
            NSS_STATUS_SUCCESS)
                return False;
 
@@ -510,14 +514,26 @@ static BOOL wbinfo_sid_to_gid(char *sid)
        return True;
 }
 
-static BOOL wbinfo_allocate_rid(void)
+static BOOL wbinfo_allocate_uid(void)
 {
-       uint32 rid;
+       uid_t uid;
 
-       if (!winbind_allocate_rid(&rid))
+       if (!winbind_allocate_uid(&uid))
                return False;
 
-       d_printf("New rid: %d\n", rid);
+       d_printf("New uid: %d\n", uid);
+
+       return True;
+}
+
+static BOOL wbinfo_allocate_gid(void)
+{
+       gid_t gid;
+
+       if (!winbind_allocate_gid(&gid))
+               return False;
+
+       d_printf("New gid: %d\n", gid);
 
        return True;
 }
@@ -577,6 +593,67 @@ static BOOL wbinfo_lookupname(char *name)
 
 /* Authenticate a user with a plaintext password */
 
+static BOOL wbinfo_auth_krb5(char *username, const char *cctype, uint32 flags)
+{
+       struct winbindd_request request;
+       struct winbindd_response response;
+       NSS_STATUS result;
+       char *p;
+
+       /* Send off request */
+
+       ZERO_STRUCT(request);
+       ZERO_STRUCT(response);
+
+       p = strchr(username, '%');
+
+       if (p) {
+               *p = 0;
+               fstrcpy(request.data.auth.user, username);
+               fstrcpy(request.data.auth.pass, p + 1);
+               *p = '%';
+       } else
+               fstrcpy(request.data.auth.user, username);
+
+       request.flags = flags;
+
+       fstrcpy(request.data.auth.krb5_cc_type, cctype);
+
+       request.data.auth.uid = geteuid();
+
+       result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response);
+
+       /* Display response */
+
+       d_printf("plaintext kerberos password authentication for [%s] %s (requesting cctype: %s)\n", 
+               username, (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", cctype);
+
+       if (response.data.auth.nt_status)
+               d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n", 
+                        response.data.auth.nt_status_string, 
+                        response.data.auth.nt_status,
+                        response.data.auth.error_string);
+
+       if (result == NSS_STATUS_SUCCESS) {
+
+               if (request.flags & WBFLAG_PAM_INFO3_TEXT) {
+                       if (response.data.auth.info3.user_flgs & LOGON_CACHED_ACCOUNT) {
+                               d_printf("user_flgs: LOGON_CACHED_ACCOUNT\n");
+                       }
+               }
+
+               if (response.data.auth.krb5ccname[0] != '\0') {
+                       d_printf("credentials were put in: %s\n", response.data.auth.krb5ccname);
+               } else {
+                       d_printf("no credentials cached\n");
+               }
+       }
+
+       return result == NSS_STATUS_SUCCESS;
+}
+
+/* Authenticate a user with a plaintext password */
+
 static BOOL wbinfo_auth(char *username)
 {
        struct winbindd_request request;
@@ -968,7 +1045,10 @@ enum {
        OPT_GETDCNAME,
        OPT_USERDOMGROUPS,
        OPT_USERSIDS,
-       OPT_SEPARATOR
+       OPT_ALLOCATE_UID,
+       OPT_ALLOCATE_GID,
+       OPT_SEPARATOR,
+       OPT_LIST_ALL_DOMAINS
 };
 
 int main(int argc, char **argv)
@@ -997,9 +1077,13 @@ int main(int argc, char **argv)
                { "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" },
                { "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" },
                { "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y', "Converts sid to gid", "SID" },
-               { "allocate-rid", 'A', POPT_ARG_NONE, 0, 'A', "Get a new RID out of idmap" },
+               { "allocate-uid", 0, POPT_ARG_NONE, 0, OPT_ALLOCATE_UID,
+                 "Get a new UID out of idmap" },
+               { "allocate-gid", 0, POPT_ARG_NONE, 0, OPT_ALLOCATE_GID,
+                 "Get a new GID out of idmap" },
                { "check-secret", 't', POPT_ARG_NONE, 0, 't', "Check shared secret" },
                { "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm', "List trusted domains" },
+               { "all-domains", 0, POPT_ARG_NONE, 0, OPT_LIST_ALL_DOMAINS, "List all domains (trusted and own domain)" },
                { "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "Show sequence numbers of all domains" },
                { "domain-info", 'D', POPT_ARG_STRING, &string_arg, 'D', "Show most of the info we have about the domain" },
                { "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" },
@@ -1015,6 +1099,11 @@ int main(int argc, char **argv)
                { "domain", 0, POPT_ARG_STRING, &opt_domain_name, OPT_DOMAIN_NAME, "Define to the domain to restrict operation", "domain" },
 #ifdef WITH_FAKE_KASERVER
                { "klog", 'k', POPT_ARG_STRING, &string_arg, 'k', "set an AFS token from winbind", "user%password" },
+#endif
+#ifdef HAVE_KRB5
+               { "krb5auth", 'K', POPT_ARG_STRING, &string_arg, 'K', "authenticate user using Kerberos", "user%password" },
+                       /* destroys wbinfo --help output */
+                       /* "user%password,DOM\\user%password,user@EXAMPLE.COM,EXAMPLE.COM\\user%password" }, */
 #endif
                { "separator", 0, POPT_ARG_NONE, 0, OPT_SEPARATOR, "Get the active winbind separator", NULL },
                POPT_COMMON_VERSION
@@ -1120,9 +1209,15 @@ int main(int argc, char **argv)
                                goto done;
                        }
                        break;
-               case 'A':
-                       if (!wbinfo_allocate_rid()) {
-                               d_fprintf(stderr, "Could not allocate a RID\n");
+               case OPT_ALLOCATE_UID:
+                       if (!wbinfo_allocate_uid()) {
+                               d_fprintf(stderr, "Could not allocate a uid\n");
+                               goto done;
+                       }
+                       break;
+               case OPT_ALLOCATE_GID:
+                       if (!wbinfo_allocate_gid()) {
+                               d_fprintf(stderr, "Could not allocate a gid\n");
                                goto done;
                        }
                        break;
@@ -1133,7 +1228,7 @@ int main(int argc, char **argv)
                        }
                        break;
                case 'm':
-                       if (!wbinfo_list_domains()) {
+                       if (!wbinfo_list_domains(False)) {
                                d_fprintf(stderr, "Could not list trusted domains\n");
                                goto done;
                        }
@@ -1190,6 +1285,38 @@ int main(int argc, char **argv)
                                        goto done;
                                break;
                        }
+               case 'K': {
+                               BOOL got_error = False;
+                               uint32 flags =  WBFLAG_PAM_KRB5 |
+                                               WBFLAG_PAM_CACHED_LOGIN |
+                                               WBFLAG_PAM_FALLBACK_AFTER_KRB5 |
+                                               WBFLAG_PAM_INFO3_TEXT;
+                               fstring tok;
+                               int i;
+                               const char *arg[] = { string_arg, NULL };
+                               const char *cctypes[] = { "FILE", 
+                                                         "KCM", 
+                                                         "KCM:0", 
+                                                         "Garbage", 
+                                                         NULL, 
+                                                         "0"};
+
+                               while (next_token(arg, tok, LIST_SEP, sizeof(tok))) {
+
+                                       for (i=0; i < ARRAY_SIZE(cctypes); i++) {
+                                               if (!wbinfo_auth_krb5(tok, cctypes[i], flags)) {
+                                                       d_fprintf(stderr, "Could not authenticate user [%s] with "
+                                                               "Kerberos (ccache: %s)\n", tok, cctypes[i]);
+                                                       got_error = True;
+                                               }
+                                       }
+                               }
+
+                               if (got_error)
+                                       goto done;
+
+                               break;
+                       }
                case 'k':
                        if (!wbinfo_klog(string_arg)) {
                                d_fprintf(stderr, "Could not klog user\n");
@@ -1198,7 +1325,7 @@ int main(int argc, char **argv)
                        break;
                case 'p':
                        if (!wbinfo_ping()) {
-                               d_fprintf(stderr, "Could not ping winbindd!\n");
+                               d_fprintf(stderr, "could not ping winbindd!\n");
                                goto done;
                        }
                        break;
@@ -1223,6 +1350,10 @@ int main(int argc, char **argv)
                        d_printf("%c\n", sep);
                        break;
                }
+               case OPT_LIST_ALL_DOMAINS:
+                       if (!wbinfo_list_domains(True)) {
+                               goto done;
+                       }
                /* generic configuration options */
                case OPT_DOMAIN_NAME:
                        break;
index bbcf2b5e887ab0bf5378d4913705f484c0e8efa7..4a269bac17ae1dba4c1de01998b993a82521dec2 100644 (file)
@@ -120,7 +120,7 @@ static void winbindd_status(void)
        if (DEBUGLEVEL >= 2 && winbindd_num_clients()) {
                DEBUG(2, ("\tclient list:\n"));
                for(tmp = winbindd_client_list(); tmp; tmp = tmp->next) {
-                       DEBUG(2, ("\t\tpid %lu, sock %d\n",
+                       DEBUGADD(2, ("\t\tpid %lu, sock %d\n",
                                  (unsigned long)tmp->pid, tmp->sock));
                }
        }
@@ -250,6 +250,7 @@ static struct winbindd_dispatch_table {
        { WINBINDD_PAM_AUTH, winbindd_pam_auth, "PAM_AUTH" },
        { WINBINDD_PAM_AUTH_CRAP, winbindd_pam_auth_crap, "AUTH_CRAP" },
        { WINBINDD_PAM_CHAUTHTOK, winbindd_pam_chauthtok, "CHAUTHTOK" },
+       { WINBINDD_PAM_LOGOFF, winbindd_pam_logoff, "PAM_LOGOFF" },
 
        /* Enumeration functions */
 
@@ -270,9 +271,8 @@ static struct winbindd_dispatch_table {
        { WINBINDD_SID_TO_GID, winbindd_sid_to_gid, "SID_TO_GID" },
        { WINBINDD_UID_TO_SID, winbindd_uid_to_sid, "UID_TO_SID" },
        { WINBINDD_GID_TO_SID, winbindd_gid_to_sid, "GID_TO_SID" },
-       { WINBINDD_ALLOCATE_RID, winbindd_allocate_rid, "ALLOCATE_RID" },
-       { WINBINDD_ALLOCATE_RID_AND_GID, winbindd_allocate_rid_and_gid,
-         "ALLOCATE_RID_AND_GID" },
+       { WINBINDD_ALLOCATE_UID, winbindd_allocate_uid, "ALLOCATE_UID" },
+       { WINBINDD_ALLOCATE_GID, winbindd_allocate_uid, "ALLOCATE_GID" },
 
        /* Miscellaneous */
 
@@ -1062,7 +1062,11 @@ int main(int argc, char **argv)
           as to SIGHUP signal */
        message_register(MSG_SMB_CONF_UPDATED, msg_reload_services);
        message_register(MSG_SHUTDOWN, msg_shutdown);
-       
+
+       /* Handle online/offline messages. */
+       message_register(MSG_WINBIND_OFFLINE,winbind_msg_offline);
+       message_register(MSG_WINBIND_ONLINE,winbind_msg_online);
+
        poptFreeContext(pc);
 
        netsamlogon_cache_init(); /* Non-critical */
index 00a023305590558b02b01365ac2b23f44f97b3fb..e81102571c922c57f8f005cd85fa5b07050c5147 100644 (file)
@@ -143,7 +143,9 @@ struct winbindd_child {
        struct winbindd_domain *domain;
        pstring logfilename;
 
+       TALLOC_CTX *mem_ctx;
        struct fd_event event;
+       struct timed_event *timed_event;
        struct winbindd_async_request *requests;
 };
 
@@ -157,7 +159,8 @@ struct winbindd_domain {
        BOOL native_mode;                      /* is this a win2k domain in native mode ? */
        BOOL active_directory;                 /* is this a win2k active directory ? */
        BOOL primary;                          /* is this our primary domain ? */
-       BOOL internal;          /* BUILTIN and member SAM */
+       BOOL internal;                         /* BUILTIN and member SAM */
+       BOOL online;                           /* is this domain available ? */
 
        /* Lookup methods for this domain (LDAP or RPC) */
        struct winbindd_methods *methods;
@@ -268,6 +271,16 @@ struct winbindd_methods {
        /* return the current global sequence number */
        NTSTATUS (*sequence_number)(struct winbindd_domain *domain, uint32 *seq);
 
+       /* return the lockout policy */
+       NTSTATUS (*lockout_policy)(struct winbindd_domain *domain, 
+                                  TALLOC_CTX *mem_ctx,
+                                  SAM_UNK_INFO_12 *lockout_policy);
+       /* return the lockout policy */
+       NTSTATUS (*password_policy)(struct winbindd_domain *domain, 
+                                   TALLOC_CTX *mem_ctx,
+                                   SAM_UNK_INFO_1 *password_policy);
        /* enumerate trusted domains */
        NTSTATUS (*trusted_domains)(struct winbindd_domain *domain,
                                    TALLOC_CTX *mem_ctx,
@@ -305,7 +318,7 @@ struct winbindd_idmap_methods {
 
 #define WINBINDD_ESTABLISH_LOOP 30
 #define WINBINDD_RESCAN_FREQ 300
-
+#define WINBINDD_PAM_AUTH_KRB5_RENEW_TIME 2592000 /* one month */
 #define DOM_SEQUENCE_NONE ((uint32)-1)
 
 #endif /* _WINBINDD_H */
index 29129e823a25c4dc9e15e8d3fc4b5bbbff844a5f..a86636504237048489c45d89bbe0390a16815411 100644 (file)
@@ -102,6 +102,8 @@ static ADS_STRUCT *ads_cached_connection(struct winbindd_domain *domain)
                        ads->auth.realm = SMB_STRDUP( lp_realm() );
        }
 
+       ads->auth.renewable = 1;
+
        status = ads_connect(ads);
        if (!ADS_ERR_OK(status) || !ads->config.realm) {
                extern struct winbindd_methods msrpc_methods, cache_methods;
@@ -206,8 +208,10 @@ static NTSTATUS query_user_list(struct winbindd_domain *domain,
                name = ads_pull_username(ads, mem_ctx, msg);
                gecos = ads_pull_string(ads, mem_ctx, msg, "name");
                if (use_nss_info("sfu")) {
-                       homedir = ads_pull_string(ads, mem_ctx, msg, ads->schema.sfu_homedir_attr);
-                       shell = ads_pull_string(ads, mem_ctx, msg, ads->schema.sfu_shell_attr);
+                       homedir = ads_pull_string(ads, mem_ctx, msg, 
+                                                 ads->schema.sfu_homedir_attr);
+                       shell = ads_pull_string(ads, mem_ctx, msg, 
+                                               ads->schema.sfu_shell_attr);
                }
        
                if (!ads_pull_sid(ads, msg, "objectSid",
@@ -474,8 +478,10 @@ static NTSTATUS query_user(struct winbindd_domain *domain,
        info->full_name = ads_pull_string(ads, mem_ctx, msg, "name");
 
        if (use_nss_info("sfu")) {
-               info->homedir = ads_pull_string(ads, mem_ctx, msg, ads->schema.sfu_homedir_attr);
-               info->shell = ads_pull_string(ads, mem_ctx, msg, ads->schema.sfu_shell_attr);
+               info->homedir = ads_pull_string(ads, mem_ctx, msg, 
+                                               ads->schema.sfu_homedir_attr);
+               info->shell = ads_pull_string(ads, mem_ctx, msg, 
+                                             ads->schema.sfu_shell_attr);
        }
 
        if (!ads_pull_uint32(ads, msg, "primaryGroupID", &group_rid)) {
@@ -872,8 +878,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
        struct ds_domain_trust  *domains = NULL;
        int                     count = 0;
        int                     i;
-                               /* i think we only need our forest and downlevel trusted domains */
-       uint32                  flags = DS_DOMAIN_IN_FOREST | DS_DOMAIN_DIRECT_OUTBOUND;
+       uint32                  flags = DS_DOMAIN_DIRECT_OUTBOUND;
        struct rpc_pipe_client *cli;
 
        DEBUG(3,("ads: trusted_domains\n"));
@@ -946,6 +951,8 @@ struct winbindd_methods ads_methods = {
        msrpc_lookup_useraliases,
        lookup_groupmem,
        sequence_number,
+       msrpc_lockout_policy,
+       msrpc_password_policy,
        trusted_domains,
 };
 
index 9ecfb1ff6ed7ccf3cc06d2411e01b3b0f86ccff0..28633757c09fbe2ed602e6e98657d82e5ff44082 100644 (file)
@@ -6,7 +6,7 @@
    Copyright (C) Andrew Tridgell 2001
    Copyright (C) Gerald Carter   2003
    Copyright (C) Volker Lendecke 2005
-   
+   Copyright (C) Guenther Deschner 2005
    
    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
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 
+/* Global online/offline state - False when online. winbindd starts up online
+   and sets this to true if the first query fails and there's an entry in
+   the cache tdb telling us to stay offline. */
+
+static BOOL global_winbindd_offline_state;
+
 struct winbind_cache {
        TDB_CONTEXT *tdb;
 };
@@ -44,29 +50,6 @@ struct cache_entry {
 
 static struct winbind_cache *wcache;
 
-/* flush the cache */
-void wcache_flush_cache(void)
-{
-       extern BOOL opt_nocache;
-
-       if (!wcache)
-               return;
-       if (wcache->tdb) {
-               tdb_close(wcache->tdb);
-               wcache->tdb = NULL;
-       }
-       if (opt_nocache)
-               return;
-
-       wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 5000, 
-                                  TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0600);
-
-       if (!wcache->tdb) {
-               DEBUG(0,("Failed to open winbindd_cache.tdb!\n"));
-       }
-       DEBUG(10,("wcache_flush_cache success\n"));
-}
-
 void winbindd_check_cache_size(time_t t)
 {
        static time_t last_check_time;
@@ -187,6 +170,22 @@ static uint32 centry_uint32(struct cache_entry *centry)
        return ret;
 }
 
+/*
+  pull a uint16 from a cache entry 
+*/
+static uint16 centry_uint16(struct cache_entry *centry)
+{
+       uint16 ret;
+       if (centry->len - centry->ofs < 2) {
+               DEBUG(0,("centry corruption? needed 2 bytes, have %d\n", 
+                        centry->len - centry->ofs));
+               smb_panic("centry_uint16");
+       }
+       ret = CVAL(centry->data, centry->ofs);
+       centry->ofs += 2;
+       return ret;
+}
+
 /*
   pull a uint8 from a cache entry 
 */
@@ -203,6 +202,40 @@ static uint8 centry_uint8(struct cache_entry *centry)
        return ret;
 }
 
+/*
+  pull a NTTIME from a cache entry 
+*/
+static NTTIME centry_nttime(struct cache_entry *centry)
+{
+       NTTIME ret;
+       if (centry->len - centry->ofs < 8) {
+               DEBUG(0,("centry corruption? needed 8 bytes, have %d\n", 
+                        centry->len - centry->ofs));
+               smb_panic("centry_nttime");
+       }
+       ret.low = IVAL(centry->data, centry->ofs);
+       centry->ofs += 4;
+       ret.high = IVAL(centry->data, centry->ofs);
+       centry->ofs += 4;
+       return ret;
+}
+
+/*
+  pull a time_t from a cache entry 
+*/
+static time_t centry_time(struct cache_entry *centry)
+{
+       time_t ret;
+       if (centry->len - centry->ofs < sizeof(time_t)) {
+               DEBUG(0,("centry corruption? needed %d bytes, have %d\n", 
+                        sizeof(time_t), centry->len - centry->ofs));
+               smb_panic("centry_time");
+       }
+       ret = IVAL(centry->data, centry->ofs); /* FIXME: correct ? */
+       centry->ofs += sizeof(time_t);
+       return ret;
+}
+
 /* pull a string from a cache entry, using the supplied
    talloc context 
 */
@@ -403,10 +436,28 @@ done:
 */
 static BOOL centry_expired(struct winbindd_domain *domain, const char *keystr, struct cache_entry *centry)
 {
+       /* If we've been told to be offline - stay in that state... */
+       if (lp_winbind_offline_logon() && global_winbindd_offline_state) {
+               DEBUG(10,("centry_expired: Key %s for domain %s valid as winbindd is globally offline.\n",
+                       keystr, domain->name ));
+               return False;
+       }
+
+       /* when the domain is offline and we havent checked in the last 30
+        * seconds if it has become online again, return the cached entry.
+        * This deals with transient offline states... */
+
+       if (!domain->online && 
+           !NT_STATUS_IS_OK(check_negative_conn_cache(domain->name, domain->dcname))) {
+               DEBUG(10,("centry_expired: Key %s for domain %s valid as domain is offline.\n",
+                       keystr, domain->name ));
+               return False;
+       }
+
        /* if the server is OK and our cache entry came from when it was down then
           the entry is invalid */
-       if (domain->sequence_number != DOM_SEQUENCE_NONE && 
-           centry->sequence_number == DOM_SEQUENCE_NONE) {
+       if ((domain->sequence_number != DOM_SEQUENCE_NONE) &&  
+           (centry->sequence_number == DOM_SEQUENCE_NONE)) {
                DEBUG(10,("centry_expired: Key %s for domain %s invalid sequence.\n",
                        keystr, domain->name ));
                return True;
@@ -428,35 +479,17 @@ static BOOL centry_expired(struct winbindd_domain *domain, const char *keystr, s
        return True;
 }
 
-/*
-  fetch an entry from the cache, with a varargs key. auto-fetch the sequence
-  number and return status
-*/
-static struct cache_entry *wcache_fetch(struct winbind_cache *cache, 
-                                       struct winbindd_domain *domain,
-                                       const char *format, ...) PRINTF_ATTRIBUTE(3,4);
-static struct cache_entry *wcache_fetch(struct winbind_cache *cache, 
-                                       struct winbindd_domain *domain,
-                                       const char *format, ...)
+static struct cache_entry *wcache_fetch_raw(char *kstr)
 {
-       va_list ap;
-       char *kstr;
        TDB_DATA data;
        struct cache_entry *centry;
        TDB_DATA key;
 
-       refresh_sequence_number(domain, False);
-
-       va_start(ap, format);
-       smb_xvasprintf(&kstr, format, ap);
-       va_end(ap);
-       
        key.dptr = kstr;
        key.dsize = strlen(kstr);
        data = tdb_fetch(wcache->tdb, key);
        if (!data.dptr) {
                /* a cache miss */
-               free(kstr);
                return NULL;
        }
 
@@ -467,16 +500,44 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
 
        if (centry->len < 8) {
                /* huh? corrupt cache? */
-               DEBUG(10,("wcache_fetch: Corrupt cache for key %s domain %s (len < 8) ?\n",
-                       kstr, domain->name ));
+               DEBUG(10,("wcache_fetch_raw: Corrupt cache for key %s (len < 8) ?\n", kstr));
                centry_free(centry);
-               free(kstr);
                return NULL;
        }
        
        centry->status = NT_STATUS(centry_uint32(centry));
        centry->sequence_number = centry_uint32(centry);
 
+       return centry;
+}
+
+/*
+  fetch an entry from the cache, with a varargs key. auto-fetch the sequence
+  number and return status
+*/
+static struct cache_entry *wcache_fetch(struct winbind_cache *cache, 
+                                       struct winbindd_domain *domain,
+                                       const char *format, ...) PRINTF_ATTRIBUTE(3,4);
+static struct cache_entry *wcache_fetch(struct winbind_cache *cache, 
+                                       struct winbindd_domain *domain,
+                                       const char *format, ...)
+{
+       va_list ap;
+       char *kstr;
+       struct cache_entry *centry;
+
+       refresh_sequence_number(domain, False);
+
+       va_start(ap, format);
+       smb_xvasprintf(&kstr, format, ap);
+       va_end(ap);
+
+       centry = wcache_fetch_raw(kstr);
+       if (centry == NULL) {
+               free(kstr);
+               return NULL;
+       }
+
        if (centry_expired(domain, kstr, centry)) {
 
                DEBUG(10,("wcache_fetch: entry %s expired for domain %s\n",
@@ -521,6 +582,16 @@ static void centry_put_uint32(struct cache_entry *centry, uint32 v)
        centry->ofs += 4;
 }
 
+/*
+  push a uint16 into a centry 
+*/
+static void centry_put_uint16(struct cache_entry *centry, uint16 v)
+{
+       centry_expand(centry, 2);
+       SIVAL(centry->data, centry->ofs, v);
+       centry->ofs += 2;
+}
+
 /*
   push a uint8 into a centry 
 */
@@ -562,6 +633,28 @@ static void centry_put_sid(struct cache_entry *centry, const DOM_SID *sid)
        centry_put_string(centry, sid_to_string(sid_string, sid));
 }
 
+/*
+  push a NTTIME into a centry 
+*/
+static void centry_put_nttime(struct cache_entry *centry, NTTIME nt)
+{
+       centry_expand(centry, 8);
+       SIVAL(centry->data, centry->ofs, nt.low);
+       centry->ofs += 4;
+       SIVAL(centry->data, centry->ofs, nt.high);
+       centry->ofs += 4;
+}
+
+/*
+  push a time_t into a centry 
+*/
+static void centry_put_time(struct cache_entry *centry, time_t t)
+{
+       centry_expand(centry, sizeof(time_t));
+       SIVAL(centry->data, centry->ofs, t); /* FIXME: is this correct ?? */
+       centry->ofs += sizeof(time_t);
+}
+
 /*
   start a centry for output. When finished, call centry_end()
 */
@@ -666,6 +759,129 @@ static void wcache_save_user(struct winbindd_domain *domain, NTSTATUS status, WI
        centry_free(centry);
 }
 
+static void wcache_save_lockout_policy(struct winbindd_domain *domain, NTSTATUS status, SAM_UNK_INFO_12 *lockout_policy)
+{
+       struct cache_entry *centry;
+
+       centry = centry_start(domain, status);
+       if (!centry)
+               return;
+
+       centry_put_nttime(centry, lockout_policy->duration);
+       centry_put_nttime(centry, lockout_policy->reset_count);
+       centry_put_uint16(centry, lockout_policy->bad_attempt_lockout);
+
+       centry_end(centry, "LOC_POL/%s", domain->name);
+       
+       DEBUG(10,("wcache_save_lockout_policy: %s\n", domain->name));
+
+       centry_free(centry);
+}
+
+static void wcache_save_password_policy(struct winbindd_domain *domain, NTSTATUS status, SAM_UNK_INFO_1 *password_policy)
+{
+       struct cache_entry *centry;
+
+       centry = centry_start(domain, status);
+       if (!centry)
+               return;
+
+       centry_put_uint16(centry, password_policy->min_length_password);
+       centry_put_uint16(centry, password_policy->password_history);
+       centry_put_uint32(centry, password_policy->password_properties);
+       centry_put_nttime(centry, password_policy->expire);
+       centry_put_nttime(centry, password_policy->min_passwordage);
+
+       centry_end(centry, "PWD_POL/%s", domain->name);
+       
+       DEBUG(10,("wcache_save_password_policy: %s\n", domain->name));
+
+       centry_free(centry);
+}
+
+NTSTATUS wcache_cached_creds_exist(struct winbindd_domain *domain, const DOM_SID *sid)
+{
+       struct winbind_cache *cache = get_cache(domain);
+       TDB_DATA data;
+       fstring key_str;
+
+       if (!cache->tdb) {
+               return NT_STATUS_INTERNAL_DB_ERROR;
+       }
+
+       fstr_sprintf(key_str, "CRED/%s", sid_string_static(sid));
+
+       data = tdb_fetch(cache->tdb, make_tdb_data(key_str, strlen(key_str)));
+       if (!data.dptr) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       return NT_STATUS_OK;
+}
+
+/* Lookup creds for a SID */
+NTSTATUS wcache_get_creds(struct winbindd_domain *domain, 
+                         TALLOC_CTX *mem_ctx, 
+                         const DOM_SID *sid,
+                         const uint8 **cached_nt_pass)
+{
+       struct winbind_cache *cache = get_cache(domain);
+       struct cache_entry *centry = NULL;
+       NTSTATUS status;
+       time_t t;
+
+       if (!cache->tdb) {
+               return NT_STATUS_INTERNAL_DB_ERROR;
+       }
+
+       centry = wcache_fetch(cache, domain, "CRED/%s", sid_string_static(sid));
+       
+       if (!centry) {
+               DEBUG(10,("wcache_get_creds: entry for [CRED/%s] not found\n", 
+                       sid_string_static(sid)));
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       t = centry_time(centry);
+       *cached_nt_pass = (const uint8 *)centry_string(centry, mem_ctx);
+
+       dump_data(10, (const char *)cached_nt_pass, NT_HASH_LEN);
+       status = centry->status;
+
+       DEBUG(10,("wcache_get_creds: [Cached] - cached creds for user %s status %s\n",
+               sid_string_static(sid), get_friendly_nt_error_msg(status) ));
+
+       centry_free(centry);
+       return status;
+}
+
+NTSTATUS wcache_save_creds(struct winbindd_domain *domain, 
+                          TALLOC_CTX *mem_ctx, 
+                          const DOM_SID *sid, 
+                          const uint8 nt_pass[NT_HASH_LEN])
+{
+       struct cache_entry *centry;
+       fstring sid_string;
+       NTSTATUS status = NT_STATUS_OK; /* ??? */
+
+       centry = centry_start(domain, status);
+       if (!centry) {
+               return NT_STATUS_INTERNAL_DB_ERROR;
+       }
+
+       dump_data(100, (const char *)nt_pass, NT_HASH_LEN);
+
+       centry_put_time(centry, time(NULL));
+       centry_put_string(centry, (const char *)nt_pass);
+       centry_end(centry, "CRED/%s", sid_to_string(sid_string, sid));
+
+       DEBUG(10,("wcache_save_creds: %s\n", sid_string));
+
+       centry_free(centry);
+
+       return NT_STATUS_OK;
+}
+
 
 /* Query display info. This is the basic user list fn */
 static NTSTATUS query_user_list(struct winbindd_domain *domain,
@@ -991,7 +1207,9 @@ do_query:
        status = domain->backend->name_to_sid(domain, mem_ctx, domain_name, name, sid, type);
 
        /* and save it */
-       wcache_save_name_to_sid(domain, status, domain_name, name, sid, *type);
+       if (domain->online || !is_null_sid(sid)) {
+               wcache_save_name_to_sid(domain, status, domain_name, name, sid, *type);
+       }
 
        if (NT_STATUS_IS_OK(status)) {
                strupper_m(CONST_DISCARD(char *,domain_name));
@@ -1390,7 +1608,9 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
        return NT_STATUS_OK;
 }
 
-/* enumerate trusted domains */
+/* enumerate trusted domains 
+ * (we need to have the list of trustdoms in the cache when we go offline) -
+ * Guenther */
 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
                                TALLOC_CTX *mem_ctx,
                                uint32 *num_domains,
@@ -1398,16 +1618,184 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
                                char ***alt_names,
                                DOM_SID **dom_sids)
 {
-       get_cache(domain);
+       struct winbind_cache *cache = get_cache(domain);
+       struct cache_entry *centry = NULL;
+       NTSTATUS status;
+       int i;
+       if (!cache->tdb)
+               goto do_query;
+       centry = wcache_fetch(cache, domain, "TRUSTDOMS/%s", domain->name);
+       
+       if (!centry) {
+               goto do_query;
+       }
+       *num_domains = centry_uint32(centry);
+       
+       (*names)        = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
+       (*alt_names)    = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
+       (*dom_sids)     = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_domains);
+       if (! (*dom_sids) || ! (*names) || ! (*alt_names)) {
+               smb_panic("trusted_domains out of memory");
+       }
+       for (i=0; i<(*num_domains); i++) {
+               (*names)[i] = centry_string(centry, mem_ctx);
+               (*alt_names)[i] = centry_string(centry, mem_ctx);
+               centry_sid(centry, &(*dom_sids)[i]);
+       }
 
+       status = centry->status;
+       DEBUG(10,("trusted_domains: [Cached] - cached info for domain %s status %s\n",
+               domain->name, get_friendly_nt_error_msg(status) ));
+       centry_free(centry);
+       return status;
+do_query:
+       (*num_domains) = 0;
+       (*dom_sids) = NULL;
+       (*names) = NULL;
+       (*alt_names) = NULL;
+       /* Return status value returned by seq number check */
+
+       if (!NT_STATUS_IS_OK(domain->last_status))
+               return domain->last_status;
+       
        DEBUG(10,("trusted_domains: [Cached] - doing backend query for info for domain %s\n",
                domain->name ));
+       status = domain->backend->trusted_domains(domain, mem_ctx, num_domains,
+                                               names, alt_names, dom_sids);
+       /* and save it */
+       refresh_sequence_number(domain, False);
+       centry = centry_start(domain, status);
+       if (!centry)
+               goto skip_save;
+
+       centry_put_uint32(centry, *num_domains);
+
+       for (i=0; i<(*num_domains); i++) {
+               centry_put_string(centry, (*names)[i]);
+               centry_put_string(centry, (*alt_names)[i]);
+               centry_put_sid(centry, &(*dom_sids)[i]);
+       }
+       
+       centry_end(centry, "TRUSTDOMS/%s", domain->name);
+       centry_free(centry);
+skip_save:
+       return status;
+}      
+
+/* get lockout policy */
+static NTSTATUS lockout_policy(struct winbindd_domain *domain,
+                              TALLOC_CTX *mem_ctx,
+                              SAM_UNK_INFO_12 *lockout_policy){
+       struct winbind_cache *cache = get_cache(domain);
+       struct cache_entry *centry = NULL;
+       NTSTATUS status;
+       if (!cache->tdb)
+               goto do_query;
+       centry = wcache_fetch(cache, domain, "LOC_POL/%s", domain->name);
+       
+       if (!centry)
+               goto do_query;
+       lockout_policy->duration = centry_nttime(centry);
+       lockout_policy->reset_count = centry_nttime(centry);
+       lockout_policy->bad_attempt_lockout = centry_uint16(centry);
+       status = centry->status;
+       DEBUG(10,("lockout_policy: [Cached] - cached info for domain %s status %s\n",
+               domain->name, get_friendly_nt_error_msg(status) ));
+       centry_free(centry);
+       return status;
+do_query:
+       ZERO_STRUCTP(lockout_policy);
+       /* Return status value returned by seq number check */
+
+       if (!NT_STATUS_IS_OK(domain->last_status))
+               return domain->last_status;
+       
+       DEBUG(10,("lockout_policy: [Cached] - doing backend query for info for domain %s\n",
+               domain->name ));
+       status = domain->backend->lockout_policy(domain, mem_ctx, lockout_policy); 
+       /* and save it */
+       refresh_sequence_number(domain, False);
+       wcache_save_lockout_policy(domain, status, lockout_policy);
+       return status;
+}
+/* get password policy */
+static NTSTATUS password_policy(struct winbindd_domain *domain,
+                               TALLOC_CTX *mem_ctx,
+                               SAM_UNK_INFO_1 *password_policy)
+{
+       struct winbind_cache *cache = get_cache(domain);
+       struct cache_entry *centry = NULL;
+       NTSTATUS status;
+
+       if (!cache->tdb)
+               goto do_query;
+       centry = wcache_fetch(cache, domain, "PWD_POL/%s", domain->name);
+       
+       if (!centry)
+               goto do_query;
+
+       password_policy->min_length_password = centry_uint16(centry);
+       password_policy->password_history = centry_uint16(centry);
+       password_policy->password_properties = centry_uint32(centry);
+       password_policy->expire = centry_nttime(centry);
+       password_policy->min_passwordage = centry_nttime(centry);
+
+       status = centry->status;
+
+       DEBUG(10,("lockout_policy: [Cached] - cached info for domain %s status %s\n",
+               domain->name, get_friendly_nt_error_msg(status) ));
+
+       centry_free(centry);
+       return status;
+
+do_query:
+       ZERO_STRUCTP(password_policy);
+
+       /* Return status value returned by seq number check */
+
+       if (!NT_STATUS_IS_OK(domain->last_status))
+               return domain->last_status;
+       
+       DEBUG(10,("password_policy: [Cached] - doing backend query for info for domain %s\n",
+               domain->name ));
+
+       status = domain->backend->password_policy(domain, mem_ctx, password_policy); 
+
+       /* and save it */
+       refresh_sequence_number(domain, False);
+       wcache_save_password_policy(domain, status, password_policy);
 
-       /* we don't cache this call */
-       return domain->backend->trusted_domains(domain, mem_ctx, num_domains, 
-                                              names, alt_names, dom_sids);
+       return status;
 }
 
+
 /* Invalidate cached user and group lists coherently */
 
 static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, 
@@ -1448,22 +1836,6 @@ void wcache_invalidate_cache(void)
        }
 }
 
-/* the ADS backend methods are exposed via this structure */
-struct winbindd_methods cache_methods = {
-       True,
-       query_user_list,
-       enum_dom_groups,
-       enum_local_groups,
-       name_to_sid,
-       sid_to_name,
-       query_user,
-       lookup_usergroups,
-       lookup_useraliases,
-       lookup_groupmem,
-       sequence_number,
-       trusted_domains,
-};
-
 static BOOL init_wcache(void)
 {
        if (wcache == NULL) {
@@ -1474,8 +1846,10 @@ static BOOL init_wcache(void)
        if (wcache->tdb != NULL)
                return True;
 
-       wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 5000, 
-                                  TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0600);
+       /* when working offline we must not clear the cache on restart */
+       wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
+                               WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE, 
+                               TDB_DEFAULT /*TDB_CLEAR_IF_FIRST*/, O_RDWR|O_CREAT, 0600);
 
        if (wcache->tdb == NULL) {
                DEBUG(0,("Failed to open winbindd_cache.tdb!\n"));
@@ -1577,6 +1951,25 @@ BOOL cache_retrieve_response(pid_t pid, struct winbindd_response * response)
        return True;
 }
 
+void cache_cleanup_response(pid_t pid)
+{
+       fstring key_str;
+
+       if (!init_wcache())
+               return;
+
+       DEBUG(10,("Cleaning up response for pid %d\n", pid));
+
+       fstr_sprintf(key_str, "DR/%d", pid);
+       tdb_delete(wcache->tdb, string_tdb_data(key_str));
+
+       fstr_sprintf(key_str, "DE/%d", pid);
+       tdb_delete(wcache->tdb, string_tdb_data(key_str));
+
+       return;
+}
+
+
 BOOL lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
                       const char **domain_name, const char **name,
                       enum SID_NAME_USE *type)
@@ -1613,6 +2006,48 @@ BOOL lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
        return NT_STATUS_IS_OK(status);
 }
 
+BOOL lookup_cached_name(TALLOC_CTX *mem_ctx,
+                       const char *domain_name,
+                       const char *name,
+                       DOM_SID *sid,
+                       enum SID_NAME_USE *type)
+{
+       struct winbindd_domain *domain;
+       struct winbind_cache *cache;
+       struct cache_entry *centry = NULL;
+       NTSTATUS status;
+       fstring uname;
+
+       domain = find_lookup_domain_from_name(domain_name);
+       if (domain == NULL) {
+               return False;
+       }
+
+       cache = get_cache(domain);
+
+       if (cache->tdb == NULL) {
+               return False;
+       }
+
+       fstrcpy(uname, name);
+       strupper_m(uname);
+       
+       centry = wcache_fetch(cache, domain, "NS/%s/%s", domain_name, uname);
+       if (centry == NULL) {
+               return False;
+       }
+
+       if (NT_STATUS_IS_OK(centry->status)) {
+               *type = (enum SID_NAME_USE)centry_uint32(centry);
+               centry_sid(centry, sid);
+       }
+
+       status = centry->status;
+       centry_free(centry);
+       
+       return NT_STATUS_IS_OK(status);
+}
+
 void cache_sid2name(struct winbindd_domain *domain, const DOM_SID *sid,
                    const char *domain_name, const char *name,
                    enum SID_NAME_USE type)
@@ -1620,3 +2055,282 @@ void cache_sid2name(struct winbindd_domain *domain, const DOM_SID *sid,
        wcache_save_sid_to_name(domain, NT_STATUS_OK, sid, domain_name,
                                name, type);
 }
+
+/* delete all centries that don't have NT_STATUS_OK set */
+static int traverse_fn_cleanup(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, 
+                              TDB_DATA dbuf, void *state)
+{
+       struct cache_entry *centry;
+       char buf[1024];
+
+       if (!snprintf(buf, kbuf.dsize + 1, "%s", kbuf.dptr)) {
+               return 1;
+       }
+
+       centry = wcache_fetch_raw(buf);
+       if (!centry) {
+               return 0;
+       }
+
+       if (!NT_STATUS_IS_OK(centry->status)) {
+               DEBUG(10,("deleting centry %s\n", buf));
+               tdb_delete(the_tdb, kbuf);
+       }
+
+       centry_free(centry);
+       return 0;
+}
+
+/* flush the cache */
+void wcache_flush_cache(void)
+{
+       extern BOOL opt_nocache;
+
+       if (!wcache)
+               return;
+       if (wcache->tdb) {
+               tdb_close(wcache->tdb);
+               wcache->tdb = NULL;
+       }
+       if (opt_nocache)
+               return;
+
+       /* when working offline we must not clear the cache on restart */
+       wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
+                               WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE, 
+                               TDB_DEFAULT /* TDB_CLEAR_IF_FIRST */, O_RDWR|O_CREAT, 0600);
+
+       if (!wcache->tdb) {
+               DEBUG(0,("Failed to open winbindd_cache.tdb!\n"));
+       }
+
+       tdb_traverse(wcache->tdb, traverse_fn_cleanup, NULL);
+
+       DEBUG(10,("wcache_flush_cache success\n"));
+}
+
+/* Count cached creds */
+
+static int traverse_fn_cached_creds(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, 
+                                   void *state)
+{
+       int *cred_count = (int*)state;
+       if (strncmp(kbuf.dptr, "CRED/", 5) == 0) {
+               (*cred_count)++;
+       }
+       return 0;
+}
+
+NTSTATUS wcache_count_cached_creds(struct winbindd_domain *domain, int *count)
+{
+       struct winbind_cache *cache = get_cache(domain);
+
+       *count = 0;
+
+       if (!cache->tdb) {
+               return NT_STATUS_INTERNAL_DB_ERROR;
+       }
+       tdb_traverse(cache->tdb, traverse_fn_cached_creds, (void *)count);
+
+       return NT_STATUS_OK;
+}
+
+struct cred_list {
+       struct cred_list *prev, *next;
+       TDB_DATA key;
+       fstring name;
+       time_t created;
+};
+static struct cred_list *wcache_cred_list;
+
+static int traverse_fn_get_credlist(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, 
+                                   void *state)
+{
+       struct cred_list *cred;
+
+       if (strncmp(kbuf.dptr, "CRED/", 5) == 0) {
+
+               cred = SMB_MALLOC_P(struct cred_list);
+               if (cred == NULL) {
+                       DEBUG(0,("traverse_fn_remove_first_creds: failed to malloc new entry for list\n"));
+                       return -1;
+               }
+
+               ZERO_STRUCTP(cred);
+               
+               /* save a copy of the key */
+               
+               fstrcpy(cred->name, kbuf.dptr);         
+               DLIST_ADD(wcache_cred_list, cred);
+       }
+       
+       return 0;
+}
+
+NTSTATUS wcache_remove_oldest_cached_creds(struct winbindd_domain *domain, const DOM_SID *sid) 
+{
+       struct winbind_cache *cache = get_cache(domain);
+       NTSTATUS status;
+       int ret;
+       struct cred_list *cred, *oldest = NULL;
+
+       if (!cache->tdb) {
+               return NT_STATUS_INTERNAL_DB_ERROR;
+       }
+
+       /* we possibly already have an entry */
+       if (sid && NT_STATUS_IS_OK(wcache_cached_creds_exist(domain, sid))) {
+       
+               fstring key_str;
+
+               DEBUG(11,("we already have an entry, deleting that\n"));
+
+               fstr_sprintf(key_str, "CRED/%s", sid_string_static(sid));
+
+               tdb_delete(cache->tdb, string_tdb_data(key_str));
+
+               return NT_STATUS_OK;
+       }
+
+       ret = tdb_traverse(cache->tdb, traverse_fn_get_credlist, NULL);
+       if (ret == 0) {
+               return NT_STATUS_OK;
+       } else if (ret == -1) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       ZERO_STRUCTP(oldest);
+
+       for (cred = wcache_cred_list; cred; cred = cred->next) {
+
+               TDB_DATA data;
+               time_t t;
+
+               data = tdb_fetch(cache->tdb, make_tdb_data(cred->name, strlen(cred->name)));
+               if (!data.dptr) {
+                       DEBUG(10,("wcache_remove_oldest_cached_creds: entry for [%s] not found\n", 
+                               cred->name));
+                       status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
+                       goto done;
+               }
+       
+               t = IVAL(data.dptr, 0);
+               SAFE_FREE(data.dptr);
+
+               if (!oldest) {
+                       oldest = SMB_MALLOC_P(struct cred_list);
+                       if (oldest == NULL) {
+                               status = NT_STATUS_NO_MEMORY;
+                               goto done;
+                       }
+
+                       fstrcpy(oldest->name, cred->name);
+                       oldest->created = t;
+                       continue;
+               }
+
+               if (t < oldest->created) {
+                       fstrcpy(oldest->name, cred->name);
+                       oldest->created = t;
+               }
+       }
+
+       if (tdb_delete(cache->tdb, string_tdb_data(oldest->name)) == 0) {
+               status = NT_STATUS_OK;
+       } else {
+               status = NT_STATUS_UNSUCCESSFUL;
+       }
+done:
+       SAFE_FREE(wcache_cred_list);
+       SAFE_FREE(oldest);
+       
+       return status;
+}
+
+/* Change the global online/offline state. */
+BOOL set_global_winbindd_state_offline(void)
+{
+       TDB_DATA data;
+       int err;
+
+       DEBUG(10,("set_global_winbindd_state_offline: offline requested.\n"));
+
+       /* Only go offline if someone has created
+          the key "WINBINDD_OFFLINE" in the cache tdb. */
+
+       if (wcache == NULL || wcache->tdb == NULL) {
+               DEBUG(10,("set_global_winbindd_state_offline: wcache not open yet.\n"));
+               return False;
+       }
+
+       if (!lp_winbind_offline_logon()) {
+               DEBUG(10,("set_global_winbindd_state_offline: rejecting.\n"));
+               return False;
+       }
+
+       if (global_winbindd_offline_state) {
+               /* Already offline. */
+               return True;
+       }
+
+       wcache->tdb->ecode = 0;
+
+       data = tdb_fetch_bystring( wcache->tdb, "WINBINDD_OFFLINE" );
+
+       /* As this is a key with no data we don't need to free, we
+          check for existence by looking at tdb_err. */
+
+       err = tdb_error(wcache->tdb);
+
+       if (err == TDB_ERR_NOEXIST) {
+               DEBUG(10,("set_global_winbindd_state_offline: offline state not set.\n"));
+               return False;
+       } else {
+               DEBUG(10,("set_global_winbindd_state_offline: offline state set.\n"));
+               global_winbindd_offline_state = True;
+               return True;
+       }
+}
+
+void set_global_winbindd_state_online(void)
+{
+       DEBUG(10,("set_global_winbindd_state_online: online requested.\n"));
+
+       if (!lp_winbind_offline_logon()) {
+               DEBUG(10,("set_global_winbindd_state_online: rejecting.\n"));
+               return;
+       }
+
+       if (!global_winbindd_offline_state) {
+               /* Already online. */
+               return;
+       }
+       global_winbindd_offline_state = False;
+
+       if (!wcache->tdb) {
+               return;
+       }
+
+       /* Ensure there is no key "WINBINDD_OFFLINE" in the cache tdb. */
+       tdb_delete_bystring(wcache->tdb, "WINBINDD_OFFLINE");
+}
+
+/* the cache backend methods are exposed via this structure */
+struct winbindd_methods cache_methods = {
+       True,
+       query_user_list,
+       enum_dom_groups,
+       enum_local_groups,
+       name_to_sid,
+       sid_to_name,
+       query_user,
+       lookup_usergroups,
+       lookup_useraliases,
+       lookup_groupmem,
+       sequence_number,
+       lockout_policy,
+       password_policy,
+       trusted_domains
+};
index 177ac54d3ed93fa6c44f2026bbc8164d2e64e115..568078f86e538968b4369c9f3c89602619fad73e 100644 (file)
@@ -784,26 +784,32 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
 
                result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND;
 
-               if ((strlen(domain->dcname) > 0) 
-                       && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname)) 
-                       && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20))) 
+               if ((strlen(domain->dcname) > 0)
+                       && NT_STATUS_IS_OK(check_negative_conn_cache( domain->name, domain->dcname))
+                       && (resolve_name(domain->dcname, &domain->dcaddr.sin_addr, 0x20)))
                {
                        struct sockaddr_in *addrs = NULL;
                        int num_addrs = 0;
                        int dummy = 0;
 
-
                        add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 445, &addrs, &num_addrs);
                        add_sockaddr_to_array(mem_ctx, domain->dcaddr.sin_addr, 139, &addrs, &num_addrs);
 
                        if (!open_any_socket_out(addrs, num_addrs, 10000, &dummy, &fd)) {
+                               domain->online = False;
                                fd = -1;
                        }
                }
 
                if ((fd == -1) 
-                       && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd)) 
+                       && !find_new_dc(mem_ctx, domain, domain->dcname, &domain->dcaddr, &fd))
                {
+                       /* This is the one place where we will
+                          set the global winbindd offline state
+                          to true, if a "WINBINDD_OFFLINE" entry
+                          is found in the winbindd cache. */
+                       set_global_winbindd_state_offline();
+                       domain->online = False;
                        break;
                }
 
@@ -816,11 +822,19 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
                        break;
        }
 
+       if (NT_STATUS_IS_OK(result)) {
+               if (domain->online == False) {
+                       /* We're changing state from offline to online. */
+                       set_global_winbindd_state_online();
+               }
+               domain->online = True;
+       }
+
        talloc_destroy(mem_ctx);
        return result;
 }
 
-/* Return true if a connection is still alive */
+/* Close down all open pipes on a connection. */
 
 void invalidate_cm_connection(struct winbindd_cm_conn *conn)
 {
diff --git a/source3/nsswitch/winbindd_cred_cache.c b/source3/nsswitch/winbindd_cred_cache.c
new file mode 100644 (file)
index 0000000..a8aab04
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Winbind daemon - krb5 credential cache funcions
+
+   Copyright (C) Guenther Deschner 2005
+   
+   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"
+#include "winbindd.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
+#define MAX_CCACHES 100 
+
+static struct WINBINDD_CCACHE_ENTRY *ccache_list;
+
+static TALLOC_CTX *mem_ctx;
+
+const char *get_ccache_name_by_username(const char *username) 
+{
+       struct WINBINDD_CCACHE_ENTRY *entry;
+
+       for (entry = ccache_list; entry; entry = entry->next) {
+               if (strequal(entry->username, username)) {
+                       return entry->ccname;
+               }
+       }
+       return NULL;
+}
+
+struct WINBINDD_CCACHE_ENTRY *get_ccache_by_username(const char *username)
+{
+       struct WINBINDD_CCACHE_ENTRY *entry;
+
+       for (entry = ccache_list; entry; entry = entry->next) {
+               if (strequal(entry->username, username)) {
+                       return entry;
+               }
+       }
+       return NULL;
+}
+
+static int ccache_entry_count(void)
+{
+       struct WINBINDD_CCACHE_ENTRY *entry;
+       int i = 0;
+
+       for (entry = ccache_list; entry; entry = entry->next) {
+               i++;
+       }
+       return i;
+}
+
+NTSTATUS remove_ccache_by_ccname(const char *ccname)
+{
+       struct WINBINDD_CCACHE_ENTRY *entry;
+
+       for (entry = ccache_list; entry; entry = entry->next) {
+               if (strequal(entry->ccname, ccname)) {
+                       DLIST_REMOVE(ccache_list, entry);
+                       talloc_free(entry->event); /* unregisters events */
+                       return talloc_free(entry) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+               }
+       }
+       return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+}
+
+static void krb5_ticket_refresh_handler(struct timed_event *te,
+                                       const struct timeval *now,
+                                       void *private_data)
+{
+       struct WINBINDD_CCACHE_ENTRY *entry =
+               talloc_get_type_abort(private_data, struct WINBINDD_CCACHE_ENTRY);
+       int ret;
+       time_t new_start;
+       struct timeval t;
+
+
+       DEBUG(10,("krb5_ticket_refresh_handler called\n"));
+       DEBUGADD(10,("event called for: %s, %s\n", entry->ccname, entry->username));
+
+       talloc_free(entry->event);
+
+#ifdef HAVE_KRB5
+
+       /* Kinit again if we have the user password and we can't renew the old
+        * tgt anymore */
+
+       if ((entry->renew_until < time(NULL)) && (entry->pass != NULL)) {
+            
+               seteuid(entry->uid);
+
+               ret = kerberos_kinit_password(entry->principal_name,
+                                             entry->pass,
+                                             0, /* hm, can we do time correction here ? */
+                                             &entry->refresh_time,
+                                             &entry->renew_until,
+                                             entry->ccname,
+                                             False, /* no PAC required anymore */
+                                             WINBINDD_PAM_AUTH_KRB5_RENEW_TIME);
+               seteuid(0);
+
+               if (ret) {
+                       DEBUG(3,("could not re-kinit: %s\n", error_message(ret)));
+                       talloc_free(entry->event);
+                       return;
+               }
+
+               DEBUG(10,("successful re-kinit for: %s in ccache: %s\n", 
+                       entry->principal_name, entry->ccname));
+
+               new_start = entry->refresh_time;
+
+               goto done;
+       }
+
+       seteuid(entry->uid);
+
+       ret = smb_krb5_renew_ticket(entry->ccname, 
+                                   entry->principal_name,
+                                   entry->service,
+                                   &new_start);
+       seteuid(0);
+
+       if (ret) {
+               DEBUG(3,("could not renew tickets: %s\n", error_message(ret)));
+               /* maybe we are beyond the renewing window */
+               return;
+       }
+
+done:
+
+       t = timeval_set(new_start, 0);
+
+       entry->event = add_timed_event(mem_ctx, 
+                                      t,
+                                      "krb5_ticket_refresh_handler",
+                                      krb5_ticket_refresh_handler,
+                                      entry);
+
+#endif
+}
+
+NTSTATUS add_ccache_to_list(const char *princ_name,
+                           const char *ccname,
+                           const char *service,
+                           const char *username, 
+                           const char *sid_string,
+                           const char *pass,
+                           uid_t uid,
+                           time_t create_time, 
+                           time_t ticket_end, 
+                           time_t renew_until, 
+                           BOOL schedule_refresh_event)
+{
+       struct WINBINDD_CCACHE_ENTRY *new_entry = NULL;
+       NTSTATUS status;
+
+       if ((username == NULL && sid_string == NULL && princ_name == NULL) || 
+           ccname == NULL) {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       status = init_ccache_list();
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       if (mem_ctx == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       if (ccache_entry_count() + 1 > MAX_CCACHES) {
+               DEBUG(10,("add_ccache_to_list: max number of ccaches reached\n"));
+               return NT_STATUS_NO_MORE_ENTRIES;
+       }
+
+       new_entry = TALLOC_P(mem_ctx, struct WINBINDD_CCACHE_ENTRY);
+       if (new_entry == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       ZERO_STRUCTP(new_entry);
+
+       if (username) {
+               new_entry->username = talloc_strdup(mem_ctx, username);
+               NT_STATUS_HAVE_NO_MEMORY(new_entry->username);
+       }
+       if (sid_string) {
+               new_entry->sid_string = talloc_strdup(mem_ctx, sid_string);
+               NT_STATUS_HAVE_NO_MEMORY(new_entry->sid_string);
+       }
+       if (princ_name) {
+               new_entry->principal_name = talloc_strdup(mem_ctx, princ_name);
+               NT_STATUS_HAVE_NO_MEMORY(new_entry->principal_name);
+       }
+       if (service) {
+               new_entry->service = talloc_strdup(mem_ctx, service);
+               NT_STATUS_HAVE_NO_MEMORY(new_entry->service);
+       }
+       if (pass) {
+               new_entry->pass = talloc_strdup(mem_ctx, pass);
+               NT_STATUS_HAVE_NO_MEMORY(new_entry->pass);
+       }
+
+       new_entry->create_time = create_time;
+       new_entry->renew_until = renew_until;
+       new_entry->ccname = talloc_strdup(mem_ctx, ccname);
+       if (new_entry->ccname == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       new_entry->uid = uid;
+
+
+#ifndef WITH_KCM /* no point in doing the refresh in KCM and by ourself */
+
+       if (schedule_refresh_event && renew_until > 0) {
+
+               struct timeval t = timeval_set((ticket_end -1 ), 0);
+
+               new_entry->event = add_timed_event(mem_ctx, 
+                                                  t,
+                                                  "krb5_ticket_refresh_handler",
+                                                  krb5_ticket_refresh_handler,
+                                                  new_entry);
+       }
+#endif /* WITH_KCM */
+
+       DLIST_ADD(ccache_list, new_entry);
+
+       DEBUG(10,("add_ccache_to_list: added ccache [%s] for user [%s] to the list\n", ccname, username));
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS destroy_ccache_list(void)
+{
+       return talloc_destroy(mem_ctx) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+}
+
+NTSTATUS init_ccache_list(void)
+{
+       if (ccache_list) {
+               return NT_STATUS_OK;
+       }
+
+       mem_ctx = talloc_init("winbindd_ccache_krb5_handling");
+       if (mem_ctx == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       ZERO_STRUCTP(ccache_list);
+
+       return NT_STATUS_OK;
+}
diff --git a/source3/nsswitch/winbindd_creds.c b/source3/nsswitch/winbindd_creds.c
new file mode 100644 (file)
index 0000000..d37e901
--- /dev/null
@@ -0,0 +1,162 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Winbind daemon - cached credentials funcions
+
+   Copyright (C) Guenther Deschner 2005
+   
+   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"
+#include "winbindd.h"
+#undef DBGC_CLASS
+#define DBGC_CLASS DBGC_WINBIND
+
+#define MAX_CACHED_LOGINS 10
+
+NTSTATUS winbindd_get_creds(struct winbindd_domain *domain,
+                           TALLOC_CTX *mem_ctx,
+                           const DOM_SID *sid,
+                           NET_USER_INFO_3 **info3,
+                           const uint8 *cached_nt_pass[NT_HASH_LEN])
+{
+       NET_USER_INFO_3 *info;
+       NTSTATUS status;
+
+       status = wcache_get_creds(domain, mem_ctx, sid, cached_nt_pass);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       info = netsamlogon_cache_get(mem_ctx, sid);
+       if (info == NULL) {
+               return NT_STATUS_OBJECT_NAME_NOT_FOUND;
+       }
+
+       *info3 = info;
+
+       return NT_STATUS_OK;
+}
+
+
+NTSTATUS winbindd_store_creds(struct winbindd_domain *domain,
+                             TALLOC_CTX *mem_ctx, 
+                             const char *user, 
+                             const char *pass, 
+                             NET_USER_INFO_3 *info3,
+                             const DOM_SID *user_sid)
+{
+       NTSTATUS status;
+       uchar nt_pass[NT_HASH_LEN];
+       DOM_SID cred_sid;
+
+       if (info3 != NULL) {
+       
+               DOM_SID sid;
+               sid_copy(&sid, &(info3->dom_sid.sid));
+               sid_append_rid(&sid, info3->user_rid);
+               sid_copy(&cred_sid, &sid);
+               info3->user_flgs |= LOGON_CACHED_ACCOUNT;
+               
+       } else if (user_sid != NULL) {
+       
+               sid_copy(&cred_sid, user_sid);
+               
+       } else if (user != NULL) {
+       
+               /* do lookup ourself */
+
+               enum SID_NAME_USE type;
+               
+               if (!lookup_cached_name(mem_ctx,
+                                       domain->name,
+                                       user,
+                                       &cred_sid,
+                                       &type)) {
+                       return NT_STATUS_NO_SUCH_USER;
+               }
+       } else {
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+               
+       if (pass) {
+
+               int count = 0;
+
+               status = wcache_count_cached_creds(domain, &count);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+
+               DEBUG(11,("we have %d cached creds\n", count));
+
+               if (count + 1 > MAX_CACHED_LOGINS) {
+
+                       DEBUG(10,("need to delete the oldest cached login\n"));
+
+                       status = wcache_remove_oldest_cached_creds(domain, &cred_sid);
+                       if (!NT_STATUS_IS_OK(status)) {
+                               DEBUG(10,("failed to remove oldest cached cred: %s\n", 
+                                       nt_errstr(status)));
+                               return status;
+                       }
+               }
+
+               E_md4hash(pass, nt_pass);
+
+               dump_data(100, (const char *)nt_pass, NT_HASH_LEN);
+
+               status = wcache_save_creds(domain, mem_ctx, &cred_sid, nt_pass);
+               if (!NT_STATUS_IS_OK(status)) {
+                       return status;
+               }
+       }
+
+       if (info3 != NULL && user != NULL) {
+               if (!netsamlogon_cache_store(user, info3)) {
+                       return NT_STATUS_ACCESS_DENIED;
+               }
+       }
+
+       return NT_STATUS_OK;
+}
+
+NTSTATUS winbindd_update_creds_by_info3(struct winbindd_domain *domain,
+                                       TALLOC_CTX *mem_ctx,
+                                       const char *user,
+                                       const char *pass,
+                                       NET_USER_INFO_3 *info3)
+{
+       return winbindd_store_creds(domain, mem_ctx, user, pass, info3, NULL);
+}
+
+NTSTATUS winbindd_update_creds_by_sid(struct winbindd_domain *domain,
+                                     TALLOC_CTX *mem_ctx,
+                                     const DOM_SID *sid,
+                                     const char *pass)
+{
+       return winbindd_store_creds(domain, mem_ctx, NULL, pass, NULL, sid);
+}
+
+NTSTATUS winbindd_update_creds_by_name(struct winbindd_domain *domain,
+                                      TALLOC_CTX *mem_ctx,
+                                      const char *user,
+                                      const char *pass)
+{
+       return winbindd_store_creds(domain, mem_ctx, user, pass, NULL, NULL);
+}
+
+
index 38030ee9ac89746260c931ea1235c0bf897771d3..1988f36b51d193b60fa96f4b4026f5d18cb96ba9 100644 (file)
@@ -197,6 +197,8 @@ static void async_reply_recv(void *private_data, BOOL success)
        SMB_ASSERT(cache_retrieve_response(child->pid,
                                           state->response));
 
+       cache_cleanup_response(child->pid);
+       
        DLIST_REMOVE(child->requests, state);
 
        schedule_async_request(child);
@@ -233,6 +235,8 @@ static void schedule_async_request(struct winbindd_child *child)
        setup_async_write(&child->event, request->request,
                          sizeof(*request->request),
                          async_main_request_sent, request);
+
+       talloc_destroy(child->mem_ctx);
        return;
 }
 
@@ -347,6 +351,7 @@ static struct winbindd_child_dispatch_table child_dispatch_table[] = {
        { WINBINDD_SHOW_SEQUENCE,        winbindd_dual_show_sequence,         "SHOW_SEQUENCE" },
        { WINBINDD_PAM_AUTH,             winbindd_dual_pam_auth,              "PAM_AUTH" },
        { WINBINDD_PAM_AUTH_CRAP,        winbindd_dual_pam_auth_crap,         "AUTH_CRAP" },
+       { WINBINDD_PAM_LOGOFF,           winbindd_dual_pam_logoff,            "PAM_LOGOFF" },
        { WINBINDD_CHECK_MACHACC,        winbindd_dual_check_machine_acct,    "CHECK_MACHACC" },
        { WINBINDD_DUAL_SID2UID,         winbindd_dual_sid2uid,               "DUAL_SID2UID" },
        { WINBINDD_DUAL_SID2GID,         winbindd_dual_sid2gid,               "DUAL_SID2GID" },
@@ -356,8 +361,8 @@ static struct winbindd_child_dispatch_table child_dispatch_table[] = {
        { WINBINDD_DUAL_NAME2GID,        winbindd_dual_name2gid,              "DUAL_NAME2GID" },
        { WINBINDD_DUAL_IDMAPSET,        winbindd_dual_idmapset,              "DUAL_IDMAPSET" },
        { WINBINDD_DUAL_USERINFO,        winbindd_dual_userinfo,              "DUAL_USERINFO" },
-       { WINBINDD_ALLOCATE_RID,         winbindd_dual_allocate_rid,          "ALLOCATE_RID" },
-       { WINBINDD_ALLOCATE_RID_AND_GID, winbindd_dual_allocate_rid_and_gid,  "ALLOCATE_RID_AND_GID" },
+       { WINBINDD_ALLOCATE_UID,         winbindd_dual_allocate_uid,          "ALLOCATE_UID" },
+       { WINBINDD_ALLOCATE_GID,         winbindd_dual_allocate_gid,          "ALLOCATE_GID" },
        { WINBINDD_GETUSERDOMGROUPS,     winbindd_dual_getuserdomgroups,      "GETUSERDOMGROUPS" },
        { WINBINDD_DUAL_GETSIDALIASES,   winbindd_dual_getsidaliases,         "GETSIDALIASES" },
        /* End of list */
@@ -444,6 +449,137 @@ void winbind_child_died(pid_t pid)
        schedule_async_request(child);
 }
 
+/* Forward the online/offline messages to our children. */
+void winbind_msg_offline(int msg_type, struct process_id src, void *buf, size_t len)
+{
+       struct winbindd_child *child;
+
+       DEBUG(10,("winbind_msg_offline: got offline message.\n"));
+
+       if (!lp_winbind_offline_logon()) {
+               DEBUG(10,("winbind_msg_offline: rejecting offline message.\n"));
+               return;
+       }
+
+       /* Set our global state as offline. */
+       if (!set_global_winbindd_state_offline()) {
+               DEBUG(10,("winbind_msg_offline: offline request failed.\n"));
+               return;
+       }
+
+       for (child = children; child != NULL; child = child->next) {
+               DEBUG(10,("winbind_msg_offline: sending message to pid %u.\n",
+                       (unsigned int)child->pid ));
+               message_send_pid(pid_to_procid(child->pid), MSG_WINBIND_OFFLINE, NULL, 0, False);
+       }
+}
+
+/* Forward the online/offline messages to our children. */
+void winbind_msg_online(int msg_type, struct process_id src, void *buf, size_t len)
+{
+       struct winbindd_child *child;
+
+       DEBUG(10,("winbind_msg_online: got online message.\n"));
+
+       if (!lp_winbind_offline_logon()) {
+               DEBUG(10,("winbind_msg_online: rejecting online message.\n"));
+               return;
+       }
+
+       /* Set our global state as online. */
+       set_global_winbindd_state_online();
+
+       for (child = children; child != NULL; child = child->next) {
+               DEBUG(10,("winbind_msg_online: sending message to pid %u.\n",
+                       (unsigned int)child->pid ));
+               message_send_pid(pid_to_procid(child->pid), MSG_WINBIND_ONLINE, NULL, 0, False);
+       }
+}
+
+static void account_lockout_policy_handler(struct timed_event *te,
+                                          const struct timeval *now,
+                                          void *private_data)
+{
+       struct winbindd_child *child = private_data;
+
+       struct winbindd_methods *methods;
+       SAM_UNK_INFO_12 lockout_policy;
+       NTSTATUS result;
+
+       DEBUG(10,("account_lockout_policy_handler called\n"));
+
+       if (child->timed_event) {
+               talloc_free(child->timed_event);
+       }
+
+       methods = child->domain->methods;
+
+       result = methods->lockout_policy(child->domain, child->mem_ctx, &lockout_policy);
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(10,("account_lockout_policy_handler: failed to call lockout_policy\n"));
+               return;
+       }
+
+       child->timed_event = add_timed_event(child->mem_ctx, 
+                                            timeval_current_ofs(3600, 0),
+                                            "account_lockout_policy_handler",
+                                            account_lockout_policy_handler,
+                                            child);
+}
+
+/* Deal with a request to go offline. */
+
+static void child_msg_offline(int msg_type, struct process_id src, void *buf, size_t len)
+{
+       struct winbindd_domain *domain;
+
+       DEBUG(5,("child_msg_offline received.\n"));
+
+       if (!lp_winbind_offline_logon()) {
+               DEBUG(10,("child_msg_offline: rejecting offline message.\n"));
+               return;
+       }
+
+       /* Set our global state as offline. */
+       if (!set_global_winbindd_state_offline()) {
+               DEBUG(10,("child_msg_offline: offline request failed.\n"));
+               return;
+       }
+
+       /* Mark all our domains as offline. */
+
+       for (domain = domain_list(); domain; domain = domain->next) {
+               DEBUG(5,("child_msg_offline: marking %s offline.\n", domain->name));
+               domain->online = False;
+       }
+}
+
+/* Deal with a request to go online. */
+
+static void child_msg_online(int msg_type, struct process_id src, void *buf, size_t len)
+{
+       struct winbindd_domain *domain;
+
+       DEBUG(5,("child_msg_online received.\n"));
+
+       if (!lp_winbind_offline_logon()) {
+               DEBUG(10,("child_msg_online: rejecting online message.\n"));
+               return;
+       }
+
+       /* Set our global state as online. */
+       set_global_winbindd_state_online();
+
+       /* Mark everything online - delete any negative cache entries
+          to force an immediate reconnect. */
+
+       for (domain = domain_list(); domain; domain = domain->next) {
+               DEBUG(5,("child_msg_online: marking %s online.\n", domain->name));
+               domain->online = True;
+               check_negative_conn_cache_timeout(domain->name, domain->dcname, 0);
+       }
+}
+
 static BOOL fork_domain_child(struct winbindd_child *child)
 {
        int fdpair[2];
@@ -459,10 +595,15 @@ static BOOL fork_domain_child(struct winbindd_child *child)
        ZERO_STRUCT(state);
        state.pid = getpid();
 
+       /* Ensure we don't process messages whilst we're
+          changing the disposition for the child. */
+       message_block();
+
        child->pid = sys_fork();
 
        if (child->pid == -1) {
                DEBUG(0, ("Could not fork: %s\n", strerror(errno)));
+               message_unblock();
                return False;
        }
 
@@ -475,6 +616,8 @@ static BOOL fork_domain_child(struct winbindd_child *child)
                child->event.flags = 0;
                child->requests = NULL;
                add_fd_event(&child->event);
+               /* We're ok with online/offline messages now. */
+               message_unblock();
                return True;
        }
 
@@ -495,12 +638,80 @@ static BOOL fork_domain_child(struct winbindd_child *child)
                lp_set_logfile(child->logfilename);
                reopen_logs();
        }
-       
+
+       /* Don't handle the same messages as our parent. */
+       message_deregister(MSG_SMB_CONF_UPDATED);
+       message_deregister(MSG_SHUTDOWN);
+       message_deregister(MSG_WINBIND_OFFLINE);
+       message_deregister(MSG_WINBIND_ONLINE);
+
+       /* The child is ok with online/offline messages now. */
+       message_unblock();
+
+       child->mem_ctx = talloc_init("child_mem_ctx");
+       if (child->mem_ctx == NULL) {
+               return False;
+       }
+
+       if (child->domain != NULL) {
+               /* We might be in the idmap child...*/
+               child->timed_event = add_timed_event(
+                       child->mem_ctx, timeval_zero(),
+                       "account_lockout_policy_handler",
+                       account_lockout_policy_handler,
+                       child);
+       }
+
+       /* Handle online/offline messages. */
+       message_register(MSG_WINBIND_OFFLINE,child_msg_offline);
+       message_register(MSG_WINBIND_ONLINE,child_msg_online);
+
        while (1) {
+
+               int ret;
+               fd_set read_fds;
+               struct timeval t;
+               struct timeval *tp;
+               struct timeval now;
+
                /* free up any talloc memory */
                lp_talloc_free();
                main_loop_talloc_free();
 
+               run_events();
+
+               GetTimeOfDay(&now);
+
+               tp = get_timed_events_timeout(&t, (time_t)-1);
+               if (tp) {
+                       DEBUG(11,("select will use timeout of %d seconds\n", (int)tp->tv_sec));
+               }
+
+               /* Handle messages */
+
+               message_dispatch();
+
+               FD_ZERO(&read_fds);
+               FD_SET(state.sock, &read_fds);
+
+               ret = sys_select(state.sock + 1, &read_fds, NULL, NULL, tp);
+
+               if (ret == 0) {
+                       DEBUG(10,("nothing is ready yet, continue\n"));
+                       continue;
+               }
+
+               if (ret == -1 && errno == EINTR) {
+                       /* We got a signal - continue. */
+                       continue;
+               }
+
+               if (ret == -1 && errno != EINTR) {
+                       DEBUG(0,("select error occured\n"));
+                       perror("select");
+                       return False;
+               }
+
                /* fetch a request from the main daemon */
                child_read_request(&state);
 
index ff2d19f5fc895f3800127323a4bcbd65d99b1c0d..a328cebac4f0fe3852a75cc73d1029aa83b21628 100644 (file)
@@ -140,7 +140,7 @@ static BOOL fill_grent_mem(struct winbindd_domain *domain,
                /* make sure to allow machine accounts */
 
                if (name_types[i] != SID_NAME_USER && name_types[i] != SID_NAME_COMPUTER) {
-                       DEBUG(3, ("name %s isn't a domain user\n", the_name));
+                       DEBUG(3, ("name %s isn't a domain user (%s)\n", the_name, sid_type_lookup(name_types[i])));
                        continue;
                }
 
@@ -208,6 +208,8 @@ void winbindd_getgrnam(struct winbindd_cli_state *state)
        char *tmp, *gr_mem;
        size_t gr_mem_len;
        gid_t gid;
+       union unid_t id;
+       NTSTATUS status;
        
        /* Ensure null termination */
        state->request.data.groupname[sizeof(state->request.data.groupname)-1]='\0';
@@ -241,8 +243,8 @@ void winbindd_getgrnam(struct winbindd_cli_state *state)
        /* should we deal with users for our domain? */
        
        if ( lp_winbind_trusted_domains_only() && domain->primary) {
-               DEBUG(7,("winbindd_getgrnam: My domain -- rejecting getgrnam() for %s\\%s.\n", 
-                       name_domain, name_group));
+               DEBUG(7,("winbindd_getgrnam: My domain -- rejecting "
+                        "getgrnam() for %s\\%s.\n", name_domain, name_group));
                request_error(state);
                return;
        }
@@ -262,18 +264,35 @@ void winbindd_getgrnam(struct winbindd_cli_state *state)
               ((name_type==SID_NAME_ALIAS) && domain->internal) ||
               ((name_type==SID_NAME_WKN_GRP) && domain->internal)) )
        {
-               DEBUG(1, ("name '%s' is not a local, domain or builtin group: %d\n", 
-                         name_group, name_type));
+               DEBUG(1, ("name '%s' is not a local, domain or builtin "
+                         "group: %d\n", name_group, name_type));
                request_error(state);
                return;
        }
 
-       if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid, &gid, 0))) {
-               DEBUG(1, ("error converting unix gid to sid\n"));
-               request_error(state);
-               return;
+       /* Try to get the GID */
+
+       status = idmap_sid_to_gid(&group_sid, &gid, 0);
+
+       if (NT_STATUS_IS_OK(status)) {
+               goto got_gid;
+       }
+
+       /* Maybe it's one of our aliases in passdb */
+
+       if (pdb_sid_to_id(&group_sid, &id, &name_type) &&
+           ((name_type == SID_NAME_ALIAS) ||
+            (name_type == SID_NAME_WKN_GRP))) {
+               gid = id.gid;
+               goto got_gid;
        }
 
+       DEBUG(1, ("error converting unix gid to sid\n"));
+       request_error(state);
+       return;
+
+ got_gid:
+
        if (!fill_grent(&state->response.data.gr, name_domain,
                        name_group, gid) ||
            !fill_grent_mem(domain, &group_sid, name_type,
@@ -303,6 +322,7 @@ void winbindd_getgrgid(struct winbindd_cli_state *state)
        fstring group_name;
        size_t gr_mem_len;
        char *gr_mem;
+       NTSTATUS status;
 
        DEBUG(3, ("[%5lu]: getgrgid %lu\n", (unsigned long)state->pid, 
                  (unsigned long)state->request.data.gid));
@@ -315,14 +335,29 @@ void winbindd_getgrgid(struct winbindd_cli_state *state)
                return;
        }
 
-       /* Get rid from gid */
-       if (!NT_STATUS_IS_OK(idmap_gid_to_sid(&group_sid, state->request.data.gid, 0))) {
-               DEBUG(1, ("could not convert gid %lu to rid\n", 
-                         (unsigned long)state->request.data.gid));
-               request_error(state);
-               return;
+       /* Get sid from gid */
+
+       status = idmap_gid_to_sid(&group_sid, state->request.data.gid, 0);
+       if (NT_STATUS_IS_OK(status)) {
+               /* This is a remote one */
+               goto got_sid;
        }
 
+       /* Ok, this might be "ours", i.e. an alias */
+
+       if (pdb_gid_to_sid(state->request.data.gid, &group_sid) &&
+           lookup_sid(state->mem_ctx, &group_sid, NULL, NULL, &name_type) &&
+           (name_type == SID_NAME_ALIAS)) {
+               /* Hey, got an alias */
+               goto got_sid;
+       }
+
+       DEBUG(1, ("could not convert gid %lu to sid\n", 
+                 (unsigned long)state->request.data.gid));
+       request_error(state);
+       return;
+
+ got_sid:
        /* Get name from sid */
 
        if (!winbindd_lookup_name_by_sid(state->mem_ctx, &group_sid, dom_name,
@@ -665,13 +700,32 @@ void winbindd_getgrent(struct winbindd_cli_state *state)
                sid_copy(&group_sid, &domain->sid);
                sid_append_rid(&group_sid, name_list[ent->sam_entry_index].rid);
 
-               if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid, &group_gid, 0))) {
-                       
-                       DEBUG(1, ("could not look up gid for group %s\n", 
-                                 name_list[ent->sam_entry_index].acct_name));
-                       
-                       ent->sam_entry_index++;
-                       goto tryagain;
+               if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid,
+                                                    &group_gid, 0))) {
+                       union unid_t id;
+                       enum SID_NAME_USE type;
+
+                       DEBUG(10, ("SID %s not in idmap\n",
+                                  sid_string_static(&group_sid)));
+
+                       if (!pdb_sid_to_id(&group_sid, &id, &type)) {
+                               DEBUG(1, ("could not look up gid for group "
+                                         "%s\n", 
+                                         name_list[ent->sam_entry_index].acct_name));
+                               ent->sam_entry_index++;
+                               goto tryagain;
+                       }
+
+                       if ((type != SID_NAME_DOM_GRP) &&
+                           (type != SID_NAME_ALIAS) &&
+                           (type != SID_NAME_WKN_GRP)) {
+                               DEBUG(1, ("Group %s is a %s, not a group\n",
+                                         sid_type_lookup(type),
+                                         name_list[ent->sam_entry_index].acct_name));
+                               ent->sam_entry_index++;
+                               goto tryagain;
+                       }
+                       group_gid = id.gid;
                }
 
                DEBUG(10, ("got gid %lu for group %lu\n", (unsigned long)group_gid,
@@ -1187,4 +1241,3 @@ enum winbindd_result winbindd_dual_getuserdomgroups(struct winbindd_domain *doma
 
        return WINBINDD_OK;
 }
-
index 1fbf4b33df2dc83096f97b281e1090ef0f78440a..b6aecae393013d25bdd1f0451f0971f97e454dec 100644 (file)
@@ -115,6 +115,7 @@ enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *
        int extra_data_len = 0;
        char *extra_data;
        NTSTATUS result;
+       BOOL have_own_domain = False;
 
        DEBUG(3, ("[%5lu]: list trusted domains\n",
                  (unsigned long)state->pid));
@@ -137,6 +138,22 @@ enum winbindd_result winbindd_dual_list_trusted_domains(struct winbindd_domain *
                                             names[i],
                                             alt_names[i] ? alt_names[i] : names[i],
                                             sid_string_static(&sids[i]));
+       /* add our primary domain */
+       
+       for (i=0; i<num_domains; i++) {
+               if (strequal(names[i], domain->name)) {
+                       have_own_domain = True;
+                       break;
+               }
+       }
+
+       if (state->request.data.list_all_domains && !have_own_domain) {
+               extra_data = talloc_asprintf(state->mem_ctx, "%s\n%s\\%s\\%s",
+                                            extra_data,
+                                            domain->name,
+                                            domain->alt_name ? domain->alt_name : domain->name,
+                                            sid_string_static(&domain->sid));
+       }
 
        /* This is a bit excessive, but the extra data sooner or later will be
           talloc'ed */
index eda68ae5c71237df03d7f0da5fba3ae67c944e26..033e51d794396f5325ff8e89f1c56538b035f316 100644 (file)
@@ -34,7 +34,7 @@
 
 /* Update this when you change the interface.  */
 
-#define WINBIND_INTERFACE_VERSION 11
+#define WINBIND_INTERFACE_VERSION 14
 
 /* Socket commands */
 
@@ -64,6 +64,7 @@ enum winbindd_cmd {
        WINBINDD_PAM_AUTH,
        WINBINDD_PAM_AUTH_CRAP,
        WINBINDD_PAM_CHAUTHTOK,
+       WINBINDD_PAM_LOGOFF,
 
        /* List various things */
 
@@ -82,8 +83,9 @@ enum winbindd_cmd {
        WINBINDD_SID_TO_GID,
        WINBINDD_UID_TO_SID,
        WINBINDD_GID_TO_SID,
-       WINBINDD_ALLOCATE_RID,
-       WINBINDD_ALLOCATE_RID_AND_GID,
+
+       WINBINDD_ALLOCATE_UID,
+       WINBINDD_ALLOCATE_GID,
 
        /* Miscellaneous other stuff */
 
@@ -114,7 +116,7 @@ enum winbindd_cmd {
        /* return a list of group sids for a user sid */
        WINBINDD_GETUSERSIDS,
 
-       /* Return the domain groups a user is in */
+       /* Various group queries */
        WINBINDD_GETUSERDOMGROUPS,
 
        /* Initialize connection in a child */
@@ -165,7 +167,6 @@ typedef struct winbindd_gr {
 #define WBFLAG_PAM_LMKEY               0x0008
 #define WBFLAG_PAM_CONTACT_TRUSTDOM    0x0010
 #define WBFLAG_QUERY_ONLY              0x0020
-#define WBFLAG_ALLOCATE_RID            0x0040
 #define WBFLAG_PAM_UNIX_NAME            0x0080
 #define WBFLAG_PAM_AFS_TOKEN            0x0100
 #define WBFLAG_PAM_NT_STATUS_SQUASH     0x0200
@@ -175,6 +176,10 @@ typedef struct winbindd_gr {
 /* Flag to say this is a winbindd internal send - don't recurse. */
 #define WBFLAG_RECURSE                 0x0800
 
+#define WBFLAG_PAM_KRB5                        0x1000
+#define WBFLAG_PAM_FALLBACK_AFTER_KRB5 0x2000
+#define WBFLAG_PAM_CACHED_LOGIN                0x4000
+
 #define WINBINDD_MAX_EXTRA_DATA (128*1024)
 
 /* Winbind request structure */
@@ -199,6 +204,8 @@ struct winbindd_request {
                        fstring user;
                        fstring pass;
                        fstring require_membership_of_sid;
+                       fstring krb5_cc_type;
+                       uid_t uid;
                } auth;              /* pam_winbind auth module */
                 struct {
                         unsigned char chal[8];
@@ -217,6 +224,11 @@ struct winbindd_request {
                     fstring oldpass;
                     fstring newpass;
                 } chauthtok;         /* pam_winbind passwd module */
+               struct {
+                       fstring user;
+                       fstring krb5ccname;
+                       uid_t uid;
+               } logoff;              /* pam_winbind session module */
                fstring sid;         /* lookupsid, sid_to_[ug]id */
                struct {
                        fstring dom_name;       /* lookupname */
@@ -242,6 +254,7 @@ struct winbindd_request {
                        gid_t gid;
                        fstring sid;
                } dual_idmapset;
+               BOOL list_all_domains;
        } data;
        char *extra_data;
        size_t extra_len;
@@ -307,12 +320,41 @@ struct winbindd_response {
                        int pam_error;
                        char user_session_key[16];
                        char first_8_lm_hash[8];
+                       fstring krb5ccname;
+                       struct policy_settings {
+                               uint16 min_length_password;
+                               uint16 password_history;
+                               uint32 password_properties;
+                               time_t expire;
+                               time_t min_passwordage;
+                       } policy;
+                       uint32 reject_reason;
+                       struct info3_text {
+                               time_t logon_time;
+                               time_t logoff_time;
+                               time_t kickoff_time;
+                               time_t pass_last_set_time;
+                               time_t pass_can_change_time;
+                               time_t pass_must_change_time;
+                               uint16 logon_count;
+                               uint16 bad_pw_count;
+                               fstring user_sid;
+                               fstring group_sid;
+                               fstring dom_sid;
+                               uint32 num_groups;
+                               uint32 user_flgs;
+                               uint32 acct_flags;
+                               uint32 num_other_sids;
+                               fstring user_name;
+                               fstring full_name;
+                               fstring logon_script;
+                               fstring profile_path;
+                               fstring home_dir;
+                               fstring dir_drive;
+                               fstring logon_srv;
+                               fstring logon_dom;
+                       } info3;
                } auth;
-               uint32 rid;     /* create user or group or allocate rid */
-               struct {
-                       uint32 rid;
-                       gid_t gid;
-               } rid_and_gid;
                struct {
                        fstring name;
                        fstring alt_name;
@@ -336,4 +378,20 @@ struct winbindd_response {
        void *extra_data;               /* getgrnam, getgrgid, getgrent */
 };
 
+struct WINBINDD_CCACHE_ENTRY {
+       const char *principal_name;
+       const char *ccname;
+       const char *service;
+       const char *username;
+       const char *sid_string;
+       const char *pass;
+       uid_t uid;
+       time_t create_time;
+       time_t renew_until;
+       BOOL refresh_tgt;
+       time_t refresh_time;
+       struct timed_event *event;
+       struct WINBINDD_CCACHE_ENTRY *next, *prev;
+};
+
 #endif
index 890007ae38941dd82e6f19858aa4d51654f9562d..ab20102f79f6e6219455f4e1fb892c56ee618cd3 100644 (file)
@@ -6,6 +6,7 @@
    Copyright (C) Andrew Tridgell 2000
    Copyright (C) Tim Potter 2001
    Copyright (C) Andrew Bartlett 2001-2002
+   Copyright (C) Guenther Deschner 2005
    
    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
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_WINBIND
 
+static NTSTATUS append_info3_as_txt(TALLOC_CTX *mem_ctx, 
+                                   struct winbindd_cli_state *state, 
+                                   NET_USER_INFO_3 *info3) 
+{
+       DOM_SID user_sid, group_sid;
+       fstring str_sid;
+
+       state->response.data.auth.info3.logon_time = 
+               nt_time_to_unix(&(info3->logon_time));
+       state->response.data.auth.info3.logoff_time = 
+               nt_time_to_unix(&(info3->logoff_time));
+       state->response.data.auth.info3.kickoff_time = 
+               nt_time_to_unix(&(info3->kickoff_time));
+       state->response.data.auth.info3.pass_last_set_time = 
+               nt_time_to_unix(&(info3->pass_last_set_time));
+       state->response.data.auth.info3.pass_can_change_time = 
+               nt_time_to_unix(&(info3->pass_can_change_time));
+       state->response.data.auth.info3.pass_must_change_time = 
+               nt_time_to_unix(&(info3->pass_must_change_time));
+
+       state->response.data.auth.info3.logon_count = info3->logon_count;
+       state->response.data.auth.info3.bad_pw_count = info3->bad_pw_count;
+
+       sid_copy(&user_sid, &(info3->dom_sid.sid));
+       sid_append_rid(&user_sid, info3->user_rid);
+
+       sid_to_string(str_sid, &user_sid);
+       fstrcpy(state->response.data.auth.info3.user_sid, str_sid);
+
+       sid_copy(&group_sid, &(info3->dom_sid.sid));
+       sid_append_rid(&group_sid, info3->group_rid);
+
+       sid_to_string(str_sid, &group_sid);
+       fstrcpy(state->response.data.auth.info3.group_sid, str_sid);
+
+       sid_to_string(str_sid, &(info3->dom_sid.sid));
+       fstrcpy(state->response.data.auth.info3.dom_sid, str_sid);
+
+       state->response.data.auth.info3.num_groups = info3->num_groups;
+       state->response.data.auth.info3.user_flgs = info3->user_flgs;
+
+       state->response.data.auth.info3.acct_flags = info3->acct_flags;
+       state->response.data.auth.info3.num_other_sids = info3->num_other_sids;
+
+       unistr2_to_ascii(state->response.data.auth.info3.user_name, 
+               &info3->uni_user_name, -1);
+       unistr2_to_ascii(state->response.data.auth.info3.full_name, 
+               &info3->uni_full_name, -1);
+       unistr2_to_ascii(state->response.data.auth.info3.logon_script, 
+               &info3->uni_logon_script, -1);
+       unistr2_to_ascii(state->response.data.auth.info3.profile_path, 
+               &info3->uni_profile_path, -1);
+       unistr2_to_ascii(state->response.data.auth.info3.home_dir, 
+               &info3->uni_home_dir, -1);
+       unistr2_to_ascii(state->response.data.auth.info3.dir_drive, 
+               &info3->uni_dir_drive, -1);
+
+       unistr2_to_ascii(state->response.data.auth.info3.logon_srv, 
+               &info3->uni_logon_srv, -1);
+       unistr2_to_ascii(state->response.data.auth.info3.logon_dom, 
+               &info3->uni_logon_dom, -1);
+
+       return NT_STATUS_OK;
+}
 
 static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, 
                                    struct winbindd_cli_state *state, 
@@ -145,14 +210,15 @@ static NTSTATUS check_info3_in_group(TALLOC_CTX *mem_ctx,
        return NT_STATUS_LOGON_FAILURE;
 }
 
-static struct winbindd_domain *find_auth_domain(const char *domain_name)
+static struct winbindd_domain *find_auth_domain(struct winbindd_cli_state *state, 
+                                               const char *domain_name)
 {
        struct winbindd_domain *domain;
 
        if (IS_DC) {
                domain = find_domain_from_name_noinit(domain_name);
                if (domain == NULL) {
-                       DEBUG(3, ("Authentication for domain [%s] "
+                       DEBUG(3, ("Authentication for domain [%s] refused"
                                  "as it is not a trusted domain\n", 
                                  domain_name));
                }
@@ -166,6 +232,18 @@ static struct winbindd_domain *find_auth_domain(const char *domain_name)
                return NULL;
        }
 
+       /* we can auth against trusted domains */
+       if (state->request.flags & WBFLAG_PAM_CONTACT_TRUSTDOM) {
+               domain = find_domain_from_name_noinit(domain_name);
+               if (domain == NULL) {
+                       DEBUG(3, ("Authentication for domain [%s] skipped " 
+                                 "as it is not a trusted domain\n", 
+                                 domain_name));
+               } else {
+                       return domain;
+               }
+       }
+
        return find_our_domain();
 }
 
@@ -181,9 +259,372 @@ static void set_auth_errors(struct winbindd_response *resp, NTSTATUS result)
        resp->data.auth.pam_error = nt_status_to_pam(result);
 }
 
+static NTSTATUS fillup_password_policy(struct winbindd_domain *domain,
+                                      struct winbindd_cli_state *state)
+{
+       struct winbindd_methods *methods;
+       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+       SAM_UNK_INFO_1 password_policy;
+
+       methods = domain->methods;
+
+       status = methods->password_policy(domain, state->mem_ctx, &password_policy);
+       if (NT_STATUS_IS_ERR(status)) {
+               return status;
+       }
+
+       state->response.data.auth.policy.min_length_password =
+               password_policy.min_length_password;
+       state->response.data.auth.policy.password_history =
+               password_policy.password_history;
+       state->response.data.auth.policy.password_properties =
+               password_policy.password_properties;
+       state->response.data.auth.policy.expire =
+               nt_time_to_unix_abs(&(password_policy.expire));
+       state->response.data.auth.policy.min_passwordage = 
+               nt_time_to_unix_abs(&(password_policy.min_passwordage));
+
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS get_max_bad_attempts_from_lockout_policy(struct winbindd_domain *domain, 
+                                                        TALLOC_CTX *mem_ctx, 
+                                                        uint16 *max_allowed_bad_attempts)
+{
+       struct winbindd_methods *methods;
+       NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
+       SAM_UNK_INFO_12 lockout_policy;
+
+       *max_allowed_bad_attempts = 0;
+
+       methods = domain->methods;
+
+       status = methods->lockout_policy(domain, mem_ctx, &lockout_policy);
+       if (NT_STATUS_IS_ERR(status)) {
+               return status;
+       }
+
+       *max_allowed_bad_attempts = lockout_policy.bad_attempt_lockout;
+
+       return NT_STATUS_OK;
+}
+
+
+static const char *generate_krb5_ccache(TALLOC_CTX *mem_ctx, 
+                                       const char *type,
+                                       uid_t uid,
+                                       BOOL *internal_ccache)
+{
+       /* accept KCM, FILE and WRFILE as krb5_cc_type from the client and then
+        * build the full ccname string based on the user's uid here -
+        * Guenther*/
+
+       const char *gen_cc = NULL;
+
+       *internal_ccache = True;
+
+       if (uid == -1) {
+               goto memory_ccache;
+       }
+
+       if (!type || type[0] == '\0') {
+               goto memory_ccache;
+       }
+
+       if (strequal(type, "FILE")) {
+               gen_cc = talloc_asprintf(mem_ctx, "FILE:/tmp/krb5cc_%d", uid);
+       } else if (strequal(type, "WRFILE")) {
+               gen_cc = talloc_asprintf(mem_ctx, "WRFILE:/tmp/krb5cc_%d", uid);
+#ifdef WITH_KCM
+       } else if (strequal(type, "KCM")) {
+               gen_cc = talloc_asprintf(mem_ctx, "KCM:%d", uid);
+#endif
+       } else {
+               DEBUG(10,("we don't allow to set a %s type ccache\n", type));
+               goto memory_ccache;
+       }
+
+       *internal_ccache = False;
+       goto done;
+
+  memory_ccache:
+       gen_cc = talloc_strdup(mem_ctx, "MEMORY:winbind_cache");
+
+  done:
+       if (gen_cc == NULL) {
+               DEBUG(0,("out of memory\n"));
+               return NULL;
+       }
+
+       DEBUG(10,("using ccache: %s %s\n", gen_cc, *internal_ccache ? "(internal)":""));
+
+       return gen_cc;
+}
+
+static uid_t get_uid_from_state(struct winbindd_cli_state *state)
+{
+       uid_t uid = -1;
+
+       uid = state->request.data.auth.uid;
+
+       if (uid < 0) {
+               DEBUG(1,("invalid uid: '%d'\n", uid));
+               return -1;
+       }
+       return uid;
+}
+
+static void setup_return_cc_name(struct winbindd_cli_state *state, const char *cc)
+{
+       const char *type = state->request.data.auth.krb5_cc_type;
+
+       state->response.data.auth.krb5ccname[0] = '\0';
+
+       if (type[0] == '\0') {
+               return;
+       }
+
+       if (!strequal(type, "FILE") &&
+#ifdef WITH_KCM
+           !strequal(type, "KCM") &&
+#endif
+           !strequal(type, "WRFILE")) {
+               DEBUG(10,("won't return krbccname for a %s type ccache\n", 
+                       type));
+               return;
+       }
+       
+       fstrcpy(state->response.data.auth.krb5ccname, cc);
+}
+
 /**********************************************************************
- Authenticate a user with a clear text password
-**********************************************************************/
+ Authenticate a user with a clear text password using Kerberos and fill up
+ ccache if required
+ **********************************************************************/
+static NTSTATUS winbindd_raw_kerberos_login(struct winbindd_domain *domain,
+                                           struct winbindd_cli_state *state,
+                                           NET_USER_INFO_3 **info3)
+{
+#ifdef HAVE_KRB5
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       krb5_error_code krb5_ret;
+       DATA_BLOB tkt, session_key_krb5;
+       DATA_BLOB ap_rep, session_key;
+       PAC_DATA *pac_data = NULL;
+       PAC_LOGON_INFO *logon_info = NULL;
+       char *client_princ = NULL;
+       char *client_princ_out = NULL;
+       char *local_service = NULL;
+       const char *cc = NULL;
+       const char *principal_s = NULL;
+       const char *service = NULL;
+       char *realm = NULL;
+       fstring name_domain, name_user;
+       time_t ticket_lifetime = 0;
+       time_t renewal_until = 0;
+       uid_t uid = -1;
+       ADS_STRUCT *ads;
+       time_t time_offset = 0;
+       BOOL internal_ccache = True;
+
+       ZERO_STRUCT(session_key);
+       ZERO_STRUCT(session_key_krb5);
+       ZERO_STRUCT(tkt);
+       ZERO_STRUCT(ap_rep);
+
+       ZERO_STRUCTP(info3);
+
+       *info3 = NULL;
+       
+       /* 1st step: 
+        * prepare a krb5_cc_cache string for the user */
+
+       uid = get_uid_from_state(state);
+       if (uid == -1) {
+               DEBUG(0,("no valid uid\n"));
+       }
+
+       cc = generate_krb5_ccache(state->mem_ctx,
+                                 state->request.data.auth.krb5_cc_type,
+                                 state->request.data.auth.uid, 
+                                 &internal_ccache);
+       if (cc == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+
+       /* 2nd step: 
+        * get kerberos properties */
+       
+       if (domain->private_data) {
+               ads = (ADS_STRUCT *)domain->private_data;
+               time_offset = ads->auth.time_offset; 
+       }
+
+
+       /* 3rd step: 
+        * do kerberos auth and setup ccache as the user */
+
+       parse_domain_user(state->request.data.auth.user, name_domain, name_user);
+
+       realm = domain->alt_name;
+       strupper_m(realm);
+       
+       principal_s = talloc_asprintf(state->mem_ctx, "%s@%s", name_user, realm); 
+       if (principal_s == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       service = talloc_asprintf(state->mem_ctx, "krbtgt/%s@%s", realm, realm);
+       if (service == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       /* if this is a user ccache, we need to act as the user to let the krb5
+        * library handle the chown, etc. */
+
+       /************************ NON-ROOT **********************/
+
+       if (!internal_ccache) {
+
+               seteuid(uid);
+               DEBUG(10,("winbindd_raw_kerberos_login: uid is %d\n", uid));
+       }
+
+       krb5_ret = kerberos_kinit_password(principal_s, 
+                                          state->request.data.auth.pass, 
+                                          time_offset, 
+                                          &ticket_lifetime,
+                                          &renewal_until,
+                                          cc, 
+                                          True,
+                                          WINBINDD_PAM_AUTH_KRB5_RENEW_TIME);
+
+       if (krb5_ret) {
+               DEBUG(1,("winbindd_raw_kerberos_login: kinit failed for '%s' with: %s (%d)\n", 
+                       principal_s, error_message(krb5_ret), krb5_ret));
+               result = krb5_to_nt_status(krb5_ret);
+               goto done;
+       }
+
+       /* does http_timestring use heimdals libroken strftime?? - Guenther */
+       DEBUG(10,("got TGT for %s in %s (valid until: %s (%d), renewable till: %s (%d))\n", 
+               principal_s, cc, 
+               http_timestring(ticket_lifetime), (int)ticket_lifetime, 
+               http_timestring(renewal_until), (int)renewal_until));
+
+       client_princ = talloc_strdup(state->mem_ctx, global_myname());
+       if (client_princ == NULL) {
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+       strlower_m(client_princ);
+
+       local_service = talloc_asprintf(state->mem_ctx, "HOST/%s@%s", client_princ, lp_realm());
+       if (local_service == NULL) {
+               DEBUG(0,("winbindd_raw_kerberos_login: out of memory\n"));
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+
+       krb5_ret = cli_krb5_get_ticket(local_service, 
+                                      time_offset, 
+                                      &tkt, 
+                                      &session_key_krb5, 
+                                      0, 
+                                      cc);
+       if (krb5_ret) {
+               DEBUG(1,("winbindd_raw_kerberos_login: failed to get ticket for: %s\n", 
+                       local_service));
+               result = krb5_to_nt_status(krb5_ret);
+               goto done;
+       }
+
+       if (!internal_ccache) {
+               seteuid(0);
+       }
+
+       /************************ NON-ROOT **********************/
+
+       result = ads_verify_ticket(state->mem_ctx, 
+                                  lp_realm(), 
+                                  &tkt, 
+                                  &client_princ_out, 
+                                  &pac_data, 
+                                  &ap_rep, 
+                                  &session_key);       
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(0,("winbindd_raw_kerberos_login: ads_verify_ticket failed: %s\n", 
+                       nt_errstr(result)));
+               goto done;
+       }
+
+       DEBUG(10,("winbindd_raw_kerberos_login: winbindd validated ticket of %s\n", 
+               client_princ));
+
+       if (!pac_data) {
+               DEBUG(3,("winbindd_raw_kerberos_login: no pac data\n"));
+               result = NT_STATUS_INVALID_PARAMETER;
+               goto done;
+       }
+                       
+       logon_info = get_logon_info_from_pac(pac_data);
+       if (logon_info == NULL) {
+               DEBUG(1,("winbindd_raw_kerberos_login: no logon info\n"));
+               result = NT_STATUS_INVALID_PARAMETER;
+               goto done;
+       }
+
+
+       /* last step: 
+        * put results together */
+
+       *info3 = &logon_info->info3;
+
+       /* if we had a user's ccache then return that string for the pam
+        * environment */
+
+       if (!internal_ccache) {
+               
+               setup_return_cc_name(state, cc);
+
+               result = add_ccache_to_list(principal_s,
+                                           cc,
+                                           service,
+                                           state->request.data.auth.user,
+                                           NULL,
+                                           state->request.data.auth.pass,
+                                           uid,
+                                           time(NULL),
+                                           ticket_lifetime,
+                                           renewal_until, 
+                                           lp_winbind_refresh_tickets());
+
+               if (!NT_STATUS_IS_OK(result)) {
+                       DEBUG(10,("winbindd_raw_kerberos_login: failed to add ccache to list: %s\n", 
+                               nt_errstr(result)));
+               }
+       }
+
+       result = NT_STATUS_OK;
+
+done:
+       data_blob_free(&session_key);
+       data_blob_free(&session_key_krb5);
+       data_blob_free(&ap_rep);
+       data_blob_free(&tkt);
+
+       SAFE_FREE(client_princ_out);
+
+       if (!internal_ccache) {
+               seteuid(0);
+       }
+
+       return result;
+#else 
+       return NT_STATUS_NOT_SUPPORTED;
+#endif /* HAVE_KRB5 */
+}
 
 void winbindd_pam_auth(struct winbindd_cli_state *state)
 {
@@ -206,7 +647,7 @@ void winbindd_pam_auth(struct winbindd_cli_state *state)
        parse_domain_user(state->request.data.auth.user,
                          name_domain, name_user);
 
-       domain = find_auth_domain(name_domain);
+       domain = find_auth_domain(state, name_domain);
 
        if (domain == NULL) {
                set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
@@ -222,12 +663,221 @@ void winbindd_pam_auth(struct winbindd_cli_state *state)
        sendto_domain(state, domain);
 }
 
-enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
-                                           struct winbindd_cli_state *state) 
+NTSTATUS winbindd_dual_pam_auth_cached(struct winbindd_domain *domain,
+                                      struct winbindd_cli_state *state,
+                                      NET_USER_INFO_3 **info3)
 {
-       NTSTATUS result;
+       NTSTATUS result = NT_STATUS_LOGON_FAILURE;
+       uint16 max_allowed_bad_attempts; 
        fstring name_domain, name_user;
-        NET_USER_INFO_3 info3;
+       DOM_SID sid;
+       enum SID_NAME_USE type;
+       uchar new_nt_pass[NT_HASH_LEN];
+       const uint8 *cached_nt_pass;
+       NET_USER_INFO_3 *my_info3;
+       time_t kickoff_time, must_change_time;
+
+       *info3 = NULL;
+
+       ZERO_STRUCTP(info3);
+
+       DEBUG(10,("winbindd_dual_pam_auth_cached\n"));
+
+       /* Parse domain and username */
+       
+       parse_domain_user(state->request.data.auth.user, name_domain, name_user);
+
+
+       if (!lookup_cached_name(state->mem_ctx,
+                               name_domain,
+                               name_user,
+                               &sid,
+                               &type)) {
+               DEBUG(10,("winbindd_dual_pam_auth_cached: no such user in the cache\n"));
+               return NT_STATUS_NO_SUCH_USER;
+       }
+
+       if (type != SID_NAME_USER) {
+               DEBUG(10,("winbindd_dual_pam_auth_cached: not a user (%s)\n", sid_type_lookup(type)));
+               return NT_STATUS_LOGON_FAILURE;
+       }
+
+       result = winbindd_get_creds(domain, 
+                                   state->mem_ctx, 
+                                   &sid, 
+                                   &my_info3, 
+                                   &cached_nt_pass);
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get creds: %s\n", nt_errstr(result)));
+               return result;
+       }
+
+       *info3 = my_info3;
+
+       E_md4hash(state->request.data.auth.pass, new_nt_pass);
+
+       dump_data(100, (const char *)new_nt_pass, NT_HASH_LEN);
+       dump_data(100, (const char *)cached_nt_pass, NT_HASH_LEN);
+
+       if (!memcmp(cached_nt_pass, new_nt_pass, NT_HASH_LEN)) {
+
+               /* User *DOES* know the password, update logon_time and reset
+                * bad_pw_count */
+       
+               my_info3->user_flgs |= LOGON_CACHED_ACCOUNT;
+       
+               if (my_info3->acct_flags & ACB_AUTOLOCK) {
+                       return NT_STATUS_ACCOUNT_LOCKED_OUT;
+               }
+       
+               if (my_info3->acct_flags & ACB_DISABLED) {
+                       return NT_STATUS_ACCOUNT_DISABLED;
+               }
+       
+               if (my_info3->acct_flags & ACB_WSTRUST) {
+                       return NT_STATUS_NOLOGON_WORKSTATION_TRUST_ACCOUNT;
+               }
+       
+               if (my_info3->acct_flags & ACB_SVRTRUST) {
+                       return NT_STATUS_NOLOGON_SERVER_TRUST_ACCOUNT;
+               }
+       
+               if (my_info3->acct_flags & ACB_DOMTRUST) {
+                       return NT_STATUS_NOLOGON_INTERDOMAIN_TRUST_ACCOUNT;
+               }
+       
+               if (!(my_info3->acct_flags & ACB_NORMAL)) {
+                       DEBUG(10,("winbindd_dual_pam_auth_cached: whats wrong with that one?: 0x%08x\n", 
+                               my_info3->acct_flags));
+                       return NT_STATUS_LOGON_FAILURE;
+               }
+       
+               kickoff_time = nt_time_to_unix(&my_info3->kickoff_time);
+               if (kickoff_time != 0 && time(NULL) > kickoff_time) {
+                       return NT_STATUS_ACCOUNT_EXPIRED;
+               }
+
+               must_change_time = nt_time_to_unix(&my_info3->pass_must_change_time);
+               if (must_change_time != 0 && must_change_time < time(NULL)) {
+                       return NT_STATUS_PASSWORD_EXPIRED;
+               }
+       
+               /* FIXME: we possibly should handle logon hours as well (does xp when
+                * offline?) see auth/auth_sam.c:sam_account_ok for details */
+
+               unix_to_nt_time(&my_info3->logon_time, time(NULL));
+               my_info3->bad_pw_count = 0;
+
+               result = winbindd_update_creds_by_info3(domain,
+                                                       state->mem_ctx,
+                                                       state->request.data.auth.user,
+                                                       state->request.data.auth.pass,
+                                                       my_info3);
+               if (!NT_STATUS_IS_OK(result)) {
+                       DEBUG(1,("failed to update creds: %s\n", nt_errstr(result)));
+                       return result;
+               }
+
+               return NT_STATUS_OK;
+
+       }
+
+       /* User does *NOT* know the correct password, modify info3 accordingly */
+
+       /* failure of this is not critical */
+       result = get_max_bad_attempts_from_lockout_policy(domain, state->mem_ctx, &max_allowed_bad_attempts);
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(10,("winbindd_dual_pam_auth_cached: failed to get max_allowed_bad_attempts. "
+                         "Won't be able to honour account lockout policies\n"));
+       }
+
+       if (max_allowed_bad_attempts == 0) {
+               return NT_STATUS_WRONG_PASSWORD;
+       }
+
+       /* increase counter */
+       if (my_info3->bad_pw_count < max_allowed_bad_attempts) {
+       
+               my_info3->bad_pw_count++;
+       }
+
+       /* lockout user */
+       if (my_info3->bad_pw_count >= max_allowed_bad_attempts) {
+
+               my_info3->acct_flags |= ACB_AUTOLOCK;
+       }
+
+       result = winbindd_update_creds_by_info3(domain,
+                                               state->mem_ctx,
+                                               state->request.data.auth.user,
+                                               NULL,
+                                               my_info3);
+
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(0,("winbindd_dual_pam_auth_cached: failed to update creds %s\n", 
+                       nt_errstr(result)));
+       }
+
+       return NT_STATUS_LOGON_FAILURE;
+}
+
+NTSTATUS winbindd_dual_pam_auth_kerberos(struct winbindd_domain *domain,
+                                        struct winbindd_cli_state *state, 
+                                        NET_USER_INFO_3 **info3)
+{
+       struct winbindd_domain *contact_domain;
+       fstring name_domain, name_user;
+       NTSTATUS result;
+
+       DEBUG(10,("winbindd_dual_pam_auth_kerberos\n"));
+       
+       /* Parse domain and username */
+       
+       parse_domain_user(state->request.data.auth.user, name_domain, name_user);
+
+       /* what domain should we contact? */
+       
+       if ( IS_DC ) {
+               if (!(contact_domain = find_domain_from_name(name_domain))) {
+                       DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", 
+                                 state->request.data.auth.user, name_domain, name_user, name_domain)); 
+                       result = NT_STATUS_NO_SUCH_USER;
+                       goto done;
+               }
+               
+       } else {
+               if (is_myname(name_domain)) {
+                       DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain));
+                       result =  NT_STATUS_NO_SUCH_USER;
+                       goto done;
+               }
+               
+               contact_domain = find_domain_from_name(name_domain);
+               if (contact_domain == NULL) {
+                       DEBUG(3, ("Authentication for domain for [%s] -> [%s]\\[%s] failed as %s is not a trusted domain\n", 
+                                 state->request.data.auth.user, name_domain, name_user, name_domain)); 
+
+                       contact_domain = find_our_domain();
+               }
+       }
+
+       set_dc_type_and_flags(contact_domain);
+
+       if (!contact_domain->active_directory) {
+               DEBUG(3,("krb5 auth requested but domain is not Active Directory\n"));
+               return NT_STATUS_INVALID_LOGON_TYPE;
+       }
+
+       result = winbindd_raw_kerberos_login(contact_domain, state, info3);
+done:
+       return result;
+}
+
+NTSTATUS winbindd_dual_pam_auth_samlogon(struct winbindd_domain *domain,
+                                        struct winbindd_cli_state *state,
+                                        NET_USER_INFO_3 **info3)
+{
+
        struct rpc_pipe_client *netlogon_pipe;
        uchar chal[8];
        DATA_BLOB lm_resp;
@@ -236,17 +886,23 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
        unsigned char local_lm_response[24];
        unsigned char local_nt_response[24];
        struct winbindd_domain *contact_domain;
+       fstring name_domain, name_user;
        BOOL retry;
+       NTSTATUS result;
+       NET_USER_INFO_3 *my_info3;
 
-       /* Ensure null termination */
-       state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0';
+       ZERO_STRUCTP(info3);
 
-       /* Ensure null termination */
-       state->request.data.auth.pass[sizeof(state->request.data.auth.pass)-1]='\0';
+       *info3 = NULL;
 
-       DEBUG(3, ("[%5lu]: pam auth %s\n", (unsigned long)state->pid,
-                 state->request.data.auth.user));
+       my_info3 = TALLOC_ZERO_P(state->mem_ctx, NET_USER_INFO_3);
+       if (my_info3 == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
+
+       DEBUG(10,("winbindd_dual_pam_auth_samlogon\n"));
+       
        /* Parse domain and username */
        
        parse_domain_user(state->request.data.auth.user, name_domain, name_user);
@@ -332,7 +988,7 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
 
        do {
 
-               ZERO_STRUCT(info3);
+               ZERO_STRUCTP(my_info3);
                retry = False;
 
                result = cm_connect_netlogon(contact_domain, &netlogon_pipe);
@@ -352,7 +1008,7 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
                                                           chal,
                                                           lm_resp,
                                                           nt_resp,
-                                                          &info3);
+                                                          my_info3);
                attempts += 1;
 
                /* We have to try a second time as cm_connect_netlogon
@@ -381,25 +1037,154 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
                
        } while ( (attempts < 2) && retry );
 
+       *info3 = my_info3;
+done:
+       return result;
+}
+
+enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain,
+                                           struct winbindd_cli_state *state) 
+{
+       NTSTATUS result = NT_STATUS_LOGON_FAILURE;
+       fstring name_domain, name_user;
+       NET_USER_INFO_3 *info3;
+       
+       /* Ensure null termination */
+       state->request.data.auth.user[sizeof(state->request.data.auth.user)-1]='\0';
+
+       /* Ensure null termination */
+       state->request.data.auth.pass[sizeof(state->request.data.auth.pass)-1]='\0';
+
+       DEBUG(3, ("[%5lu]: dual pam auth %s\n", (unsigned long)state->pid,
+                 state->request.data.auth.user));
+
+       /* Parse domain and username */
+       
+       parse_domain_user(state->request.data.auth.user, name_domain, name_user);
+
+       DEBUG(10,("winbindd_dual_pam_auth: domain: %s last was %s\n", domain->name, domain->online ? "online":"offline"));
+
+       /* Check for Kerberos authentication */
+       if (domain->online && (state->request.flags & WBFLAG_PAM_KRB5)) {
+       
+               result = winbindd_dual_pam_auth_kerberos(domain, state, &info3);
+
+               if (NT_STATUS_IS_OK(result)) {
+                       DEBUG(10,("winbindd_dual_pam_auth_kerberos succeeded\n"));
+                       goto process_result;
+               } else {
+                       DEBUG(10,("winbindd_dual_pam_auth_kerberos failed: %s\n", nt_errstr(result)));
+               }
+
+               if (NT_STATUS_EQUAL(result, NT_STATUS_NO_LOGON_SERVERS)) {
+                       DEBUG(10,("winbindd_dual_pam_auth_kerberos setting domain to offline\n"));
+                       domain->online = False;
+               }
+               
+               if (state->request.flags & WBFLAG_PAM_FALLBACK_AFTER_KRB5) {
+                       DEBUG(3,("falling back to samlogon\n"));
+                       goto sam_logon;
+               } else {
+                       goto cached_logon;
+               }
+       }
+
+sam_logon:
+       /* Check for Samlogon authentication */
+       if (domain->online) {
+               result = winbindd_dual_pam_auth_samlogon(domain, state, &info3);
+       
+               if (NT_STATUS_IS_OK(result)) {
+                       DEBUG(10,("winbindd_dual_pam_auth_samlogon succeeded\n"));
+                       goto process_result;
+               } else {
+                       DEBUG(10,("winbindd_dual_pam_auth_samlogon failed: %s\n", nt_errstr(result)));
+                       if (domain->online) {
+                               /* We're still online - fail. */
+                               goto done;
+                       }
+                       /* Else drop through and see if we can check offline.... */
+               }
+       }
+
+cached_logon:
+       /* Check for Cached logons */
+       if (!domain->online && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN) && 
+           lp_winbind_offline_logon()) {
+       
+               result = winbindd_dual_pam_auth_cached(domain, state, &info3);
+
+               if (NT_STATUS_IS_OK(result)) {
+                       DEBUG(10,("winbindd_dual_pam_auth_cached succeeded\n"));
+                       goto process_result;
+               } else {
+                       DEBUG(10,("winbindd_dual_pam_auth_cached failed: %s\n", nt_errstr(result)));
+                       goto done;
+               }
+       }
+
+process_result:
+
        if (NT_STATUS_IS_OK(result)) {
-               netsamlogon_cache_store(name_user, &info3);
-               wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3);
+       
+               netsamlogon_cache_store(name_user, info3);
+               wcache_invalidate_samlogon(find_domain_from_name(name_domain), info3);
 
                /* Check if the user is in the right group */
 
-               if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3,
+               if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, info3,
                                        state->request.data.auth.require_membership_of_sid))) {
                        DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n",
                                  state->request.data.auth.user, 
                                  state->request.data.auth.require_membership_of_sid));
+                       goto done;
                }
-       }
 
-done:
+               if (state->request.flags & WBFLAG_PAM_INFO3_NDR) {
+                       result = append_info3_as_ndr(state->mem_ctx, state, info3);
+                       if (!NT_STATUS_IS_OK(result)) {
+                               DEBUG(10,("Failed to append INFO3 (NDR): %s\n", nt_errstr(result)));
+                               goto done;
+                       }
+               }
+
+               if (state->request.flags & WBFLAG_PAM_INFO3_TEXT) {
+                       result = append_info3_as_txt(state->mem_ctx, state, info3);
+                       if (!NT_STATUS_IS_OK(result)) {
+                               DEBUG(10,("Failed to append INFO3 (TXT): %s\n", nt_errstr(result)));
+                               goto done;
+                       }
+
+               }
 
+               if ((state->request.flags & WBFLAG_PAM_CACHED_LOGIN) &&
+                   lp_winbind_offline_logon()) {
+
+                       result = winbindd_store_creds(domain,
+                                                     state->mem_ctx,
+                                                     state->request.data.auth.user,
+                                                     state->request.data.auth.pass,
+                                                     info3, NULL);
+                       if (!NT_STATUS_IS_OK(result)) {
+                               DEBUG(10,("Failed to store creds: %s\n", nt_errstr(result)));
+                               goto done;
+                       }
+
+               }
+
+               result = fillup_password_policy(domain, state);
+
+               if (!NT_STATUS_IS_OK(result)) {
+                       DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(result)));
+                       goto done;
+               }
+       
+       } 
+
+done:
        /* give us a more useful (more correct?) error code */
        if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ||
-                               (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
+           (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
                result = NT_STATUS_NO_LOGON_SERVERS;
        }
        
@@ -439,8 +1224,8 @@ done:
                        DOM_SID user_sid;
                        fstring sidstr;
 
-                       sid_copy(&user_sid, &info3.dom_sid.sid);
-                       sid_append_rid(&user_sid, info3.user_rid);
+                       sid_copy(&user_sid, &info3->dom_sid.sid);
+                       sid_append_rid(&user_sid, info3->user_rid);
                        sid_to_string(sidstr, &user_sid);
                        afsname = talloc_string_sub(state->mem_ctx, afsname,
                                                    "%s", sidstr);
@@ -474,10 +1259,11 @@ done:
        no_token:
                talloc_free(afsname);
        }
-               
+
        return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
 }
 
+
 /**********************************************************************
  Challenge Response Authentication Protocol 
 **********************************************************************/
@@ -525,7 +1311,7 @@ void winbindd_pam_auth_crap(struct winbindd_cli_state *state)
        }
 
        if (domain_name != NULL)
-               domain = find_auth_domain(domain_name);
+               domain = find_auth_domain(state, domain_name);
 
        if (domain != NULL) {
                sendto_domain(state, domain);
@@ -675,6 +1461,7 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain,
        } while ( (attempts < 2) && retry );
 
        if (NT_STATUS_IS_OK(result)) {
+
                netsamlogon_cache_store(name_user, &info3);
                wcache_invalidate_samlogon(find_domain_from_name(name_domain), &info3);
 
@@ -732,7 +1519,7 @@ done:
 
        /* give us a more useful (more correct?) error code */
        if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) ||
-                               (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
+           (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) {
                result = NT_STATUS_NO_LOGON_SERVERS;
        }
 
@@ -763,12 +1550,16 @@ done:
 
 void winbindd_pam_chauthtok(struct winbindd_cli_state *state)
 {
-       NTSTATUS result;
-       char *oldpass, *newpass;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       char *oldpass;
+       char *newpass = NULL;
        fstring domain, user;
        POLICY_HND dom_pol;
        struct winbindd_domain *contact_domain;
        struct rpc_pipe_client *cli;
+       BOOL got_info = False;
+       SAM_UNK_INFO_1 *info;
+       SAMR_CHANGE_REJECT *reject;
 
        DEBUG(3, ("[%5lu]: pam chauthtok %s\n", (unsigned long)state->pid,
                state->request.data.chauthtok.user));
@@ -798,10 +1589,70 @@ void winbindd_pam_chauthtok(struct winbindd_cli_state *state)
                goto done;
        }
 
-       result = rpccli_samr_chgpasswd_user(cli, state->mem_ctx, user, newpass,
-                                           oldpass);
+       result = rpccli_samr_chgpasswd3(cli, state->mem_ctx, user, newpass, oldpass, &info, &reject);
+
+       /* FIXME: need to check for other error codes ? */
+       if (NT_STATUS_EQUAL(result, NT_STATUS_PASSWORD_RESTRICTION)) {
+
+               state->response.data.auth.policy.min_length_password = 
+                       info->min_length_password;
+               state->response.data.auth.policy.password_history = 
+                       info->password_history;
+               state->response.data.auth.policy.password_properties = 
+                       info->password_properties;
+               state->response.data.auth.policy.expire = 
+                       nt_time_to_unix_abs(&info->expire);
+               state->response.data.auth.policy.min_passwordage = 
+                       nt_time_to_unix_abs(&info->min_passwordage);
+
+               state->response.data.auth.reject_reason = 
+                       reject->reject_reason;
+
+               got_info = True;
+               
+       } else if (!NT_STATUS_IS_OK(result)) {
+
+               DEBUG(10,("Password change with chgpasswd3 failed with: %s, retrying chgpasswd_user\n", 
+                       nt_errstr(result)));
+               
+               state->response.data.auth.reject_reason = 0;
+
+               result = rpccli_samr_chgpasswd_user(cli, state->mem_ctx, user, newpass, oldpass);
+       }
+
+done: 
+       if (NT_STATUS_IS_OK(result) && (state->request.flags & WBFLAG_PAM_CACHED_LOGIN) &&
+           lp_winbind_offline_logon()) {
+
+               NTSTATUS cred_ret;
+               
+               cred_ret = winbindd_update_creds_by_name(contact_domain,
+                                                        state->mem_ctx, user,
+                                                        newpass);
+               if (!NT_STATUS_IS_OK(cred_ret)) {
+                       DEBUG(10,("Failed to store creds: %s\n", nt_errstr(cred_ret)));
+                       goto process_result; /* FIXME: hm, risking inconsistant cache ? */
+               }
+       }               
+
+       if (!NT_STATUS_IS_OK(result) && !got_info) {
+
+               NTSTATUS policy_ret;
+               
+               policy_ret = fillup_password_policy(contact_domain, state);
+
+               /* failure of this is non critical, it will just provide no
+                * additional information to the client why the change has
+                * failed - Guenther */
+
+               if (!NT_STATUS_IS_OK(policy_ret)) {
+                       DEBUG(10,("Failed to get password policies: %s\n", nt_errstr(policy_ret)));
+                       goto process_result;
+               }
+       }
+
+process_result:
 
-done:    
        state->response.data.auth.nt_status = NT_STATUS_V(result);
        fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
        fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
@@ -819,3 +1670,112 @@ done:
        else
                request_error(state);
 }
+
+void winbindd_pam_logoff(struct winbindd_cli_state *state)
+{
+       struct winbindd_domain *domain;
+       fstring name_domain, user;
+       
+       DEBUG(3, ("[%5lu]: pam logoff %s\n", (unsigned long)state->pid,
+               state->request.data.logoff.user));
+
+       /* Ensure null termination */
+       state->request.data.logoff.user
+               [sizeof(state->request.data.logoff.user)-1]='\0';
+
+       state->request.data.logoff.krb5ccname
+               [sizeof(state->request.data.logoff.krb5ccname)-1]='\0';
+
+       parse_domain_user(state->request.data.logoff.user, name_domain, user);
+
+       domain = find_auth_domain(state, name_domain);
+
+       if (domain == NULL) {
+               set_auth_errors(&state->response, NT_STATUS_NO_SUCH_USER);
+               DEBUG(5, ("Pam Logoff for %s returned %s "
+                         "(PAM: %d)\n",
+                         state->request.data.auth.user, 
+                         state->response.data.auth.nt_status_string,
+                         state->response.data.auth.pam_error));
+               request_error(state);
+               return;
+       }
+
+       sendto_domain(state, domain);
+}
+
+enum winbindd_result winbindd_dual_pam_logoff(struct winbindd_domain *domain,
+                                             struct winbindd_cli_state *state) 
+{
+       NTSTATUS result = NT_STATUS_NOT_SUPPORTED;
+       struct WINBINDD_CCACHE_ENTRY *entry;
+       int ret;
+
+       DEBUG(3, ("[%5lu]: pam dual logoff %s\n", (unsigned long)state->pid,
+               state->request.data.logoff.user));
+
+       if (!(state->request.flags & WBFLAG_PAM_KRB5)) {
+               result = NT_STATUS_OK;
+               goto process_result;
+       }
+
+#ifdef HAVE_KRB5
+       
+       /* what we need here is to find the corresponding krb5 ccache name *we*
+        * created for a given username and destroy it (as the user who created it) */
+       
+       entry = get_ccache_by_username(state->request.data.logoff.user);
+       if (entry == NULL) {
+               DEBUG(10,("winbindd_pam_logoff: could not get ccname for user %s\n", 
+                       state->request.data.logoff.user));
+               goto process_result;
+       }
+
+       DEBUG(10,("winbindd_pam_logoff: found ccache [%s]\n", entry->ccname));
+
+       if (entry->uid < 0 || state->request.data.logoff.uid < 0) {
+               DEBUG(0,("winbindd_pam_logoff: invalid uid\n"));
+               goto process_result;
+       }
+
+       if (entry->uid != state->request.data.logoff.uid) {
+               DEBUG(0,("winbindd_pam_logoff: uid's differ: %d != %d\n", 
+                       entry->uid, state->request.data.logoff.uid));
+               goto process_result;
+       }
+
+       if (!strcsequal(entry->ccname, state->request.data.logoff.krb5ccname)) {
+               DEBUG(0,("winbindd_pam_logoff: krb5ccnames differ: (daemon) %s != (client) %s\n", 
+                       entry->ccname, state->request.data.logoff.krb5ccname));
+               goto process_result;
+       }
+
+       seteuid(entry->uid);
+
+       ret = ads_kdestroy(entry->ccname);
+
+       seteuid(0);
+
+       if (ret) {
+               DEBUG(0,("winbindd_pam_logoff: failed to destroy user ccache %s with: %s\n", 
+                       entry->ccname, error_message(ret)));
+       } else {
+               DEBUG(10,("winbindd_pam_logoff: successfully destroyed ccache %s for user %s\n", 
+                       entry->ccname, state->request.data.logoff.user));
+               remove_ccache_by_ccname(entry->ccname);
+       }
+
+       result = krb5_to_nt_status(ret);
+#else
+       result = NT_STATUS_NOT_SUPPORTED;
+#endif
+
+process_result:
+       state->response.data.auth.nt_status = NT_STATUS_V(result);
+       fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result));
+       fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result));
+       state->response.data.auth.pam_error = nt_status_to_pam(result);
+
+       return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
+}
+
index c32aa01a38a5d7bb7cb0c9d868c7989fc56dfbba..96a85a4f3a0a8e569d6785c3e4ba245f724e3b2a 100644 (file)
@@ -151,7 +151,8 @@ BOOL fill_passdb_alias_grmem(struct winbindd_domain *domain,
        *gr_mem = NULL;
        *gr_mem_len = 0;
 
-       if (!pdb_enum_aliasmem(group_sid, &members, &num_members))
+       if (!NT_STATUS_IS_OK(pdb_enum_aliasmem(group_sid, &members,
+                                              &num_members)))
                return True;
 
        for (i=0; i<num_members; i++) {
@@ -265,19 +266,24 @@ static NTSTATUS sid_to_name(struct winbindd_domain *domain,
                            char **name,
                            enum SID_NAME_USE *type)
 {
-       struct acct_info info;
+       const char *dom, *nam;
 
        DEBUG(10, ("Converting SID %s\n", sid_string_static(sid)));
 
-       if (!pdb_get_aliasinfo(sid, &info))
+       /* Paranoia check */
+       if (!sid_check_is_in_builtin(sid) &&
+           !sid_check_is_in_our_domain(sid)) {
+               DEBUG(0, ("Possible deadlock: Trying to lookup SID %s with "
+                         "passdb backend\n", sid_string_static(sid)));
                return NT_STATUS_NONE_MAPPED;
+       }
 
-       *domain_name = talloc_strdup(mem_ctx, domain->name);
-       *name = talloc_strdup(mem_ctx, info.acct_name);
-       if (sid_check_is_in_builtin(sid))
-               *type = SID_NAME_WKN_GRP;
-       else
-               *type = SID_NAME_ALIAS;
+       if (!lookup_sid(mem_ctx, sid, &dom, &nam, type)) {
+               return NT_STATUS_NONE_MAPPED;
+       }
+
+       *domain_name = talloc_strdup(mem_ctx, dom);
+       *name = talloc_strdup(mem_ctx, nam);
 
        return NT_STATUS_OK;
 }
@@ -305,14 +311,14 @@ static NTSTATUS lookup_useraliases(struct winbindd_domain *domain,
                                   uint32 num_sids, const DOM_SID *sids,
                                   uint32 *p_num_aliases, uint32 **rids)
 {
-       BOOL result;
+       NTSTATUS result;
        size_t num_aliases = 0;
 
        result = pdb_enum_alias_memberships(mem_ctx, &domain->sid,
                                            sids, num_sids, rids, &num_aliases);
 
        *p_num_aliases = num_aliases;
-       return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+       return result;
 }
 
 /* Lookup group membership given a rid.   */
@@ -322,16 +328,106 @@ static NTSTATUS lookup_groupmem(struct winbindd_domain *domain,
                                DOM_SID **sid_mem, char ***names, 
                                uint32 **name_types)
 {
+       size_t i, num_members, num_mapped;
+       uint32 *rids;
+       NTSTATUS result;
+       const DOM_SID **sids;
+       struct lsa_dom_info *lsa_domains;
+       struct lsa_name_info *lsa_names;
+
+       if (!sid_check_is_in_our_domain(group_sid)) {
+               /* There's no groups, only aliases in BUILTIN */
+               return NT_STATUS_NO_SUCH_GROUP;
+       }
+
+       result = pdb_enum_group_members(mem_ctx, group_sid, &rids,
+                                       &num_members);
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
+       }
+
+       if (num_members == 0) {
+               *num_names = 0;
+               *sid_mem = NULL;
+               *names = NULL;
+               *name_types = NULL;
+               return NT_STATUS_OK;
+       }
+
+       *sid_mem = TALLOC_ARRAY(mem_ctx, DOM_SID, num_members);
+       *names = TALLOC_ARRAY(mem_ctx, char *, num_members);
+       *name_types = TALLOC_ARRAY(mem_ctx, uint32, num_members);
+       sids = TALLOC_ARRAY(mem_ctx, const DOM_SID *, num_members);
+
+       if (((*sid_mem) == NULL) || ((*names) == NULL) ||
+           ((*name_types) == NULL) || (sids == NULL)) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       for (i=0; i<num_members; i++) {
+               DOM_SID *sid = &((*sid_mem)[i]);
+               sid_copy(sid, &domain->sid);
+               sid_append_rid(sid, rids[i]);
+               sids[i] = sid;
+       }
+
+       result = lookup_sids(mem_ctx, num_members, sids, 1,
+                            &lsa_domains, &lsa_names);
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
+       }
+
+       num_mapped = 0;
+       for (i=0; i<num_members; i++) {
+               if (lsa_names[i].type != SID_NAME_USER) {
+                       DEBUG(2, ("Got %s as group member -- ignoring\n",
+                                 sid_type_lookup(lsa_names[i].type)));
+                       continue;
+               }
+               (*names)[i] = talloc_steal((*names),
+                                          lsa_names[i].name);
+               (*name_types)[i] = lsa_names[i].type;
+
+               num_mapped += 1;
+       }
+
+       *num_names = num_mapped;
+
        return NT_STATUS_OK;
 }
 
 /* find the sequence number for a domain */
 static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
 {
-       *seq = 1;
+       BOOL result;
+       time_t seq_num;
+
+       result = pdb_get_seq_num(&seq_num);
+       if (!result) {
+               *seq = 1;
+       }
+
+       *seq = (int) seq_num;
+       /* *seq = 1; */
        return NT_STATUS_OK;
 }
 
+static NTSTATUS lockout_policy(struct winbindd_domain *domain,
+                              TALLOC_CTX *mem_ctx,
+                              SAM_UNK_INFO_12 *lockout_policy)
+{
+       /* actually we have that */
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
+
+static NTSTATUS password_policy(struct winbindd_domain *domain,
+                               TALLOC_CTX *mem_ctx,
+                               SAM_UNK_INFO_1 *password_policy)
+{
+       /* actually we have that */
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
+
 /* get a list of trusted domains */
 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
                                TALLOC_CTX *mem_ctx,
@@ -341,41 +437,35 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
                                DOM_SID **dom_sids)
 {
        NTSTATUS nt_status;
-       int enum_ctx = 0;
-       int num_sec_domains;
-       TRUSTDOM **domains;
+       struct trustdom_info **domains;
+       int i;
+
        *num_domains = 0;
        *names = NULL;
        *alt_names = NULL;
        *dom_sids = NULL;
-       do {
-               int i;
-               nt_status = secrets_get_trusted_domains(mem_ctx, &enum_ctx, 1,
-                                                       &num_sec_domains,
-                                                       &domains);
-               *names = TALLOC_REALLOC_ARRAY(mem_ctx, *names, char *,
-                                       num_sec_domains + *num_domains);
-               *alt_names = TALLOC_REALLOC_ARRAY(mem_ctx, *alt_names, char *,
-                                           num_sec_domains + *num_domains);
-               *dom_sids = TALLOC_REALLOC_ARRAY(mem_ctx, *dom_sids, DOM_SID,
-                                          num_sec_domains + *num_domains);
-
-               for (i=0; i< num_sec_domains; i++) {
-                       if (pull_ucs2_talloc(mem_ctx, &(*names)[*num_domains],
-                                            domains[i]->name) == -1) {
-                               return NT_STATUS_NO_MEMORY;
-                       }
-                       (*alt_names)[*num_domains] = NULL;
-                       (*dom_sids)[*num_domains] = domains[i]->sid;
-                       (*num_domains)++;
-               }
 
-       } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES));
+       nt_status = secrets_trusted_domains(mem_ctx, num_domains,
+                                           &domains);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               return nt_status;
+       }
 
-       if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MORE_ENTRIES)) {
-               return NT_STATUS_OK;
+       *names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
+       *alt_names = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
+       *dom_sids = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_domains);
+
+       if ((*alt_names == NULL) || (*names == NULL) || (*dom_sids == NULL)) {
+               return NT_STATUS_NO_MEMORY;
        }
-       return nt_status;
+
+       for (i=0; i<*num_domains; i++) {
+               (*alt_names)[i] = NULL;
+               (*names)[i] = talloc_steal((*names), domains[i]->name);
+               sid_copy(&(*dom_sids)[i], &domains[i]->sid);
+       }
+
+       return NT_STATUS_OK;
 }
 
 /* the rpc backend methods are exposed via this structure */
@@ -391,5 +481,7 @@ struct winbindd_methods passdb_methods = {
        lookup_useraliases,
        lookup_groupmem,
        sequence_number,
+       lockout_policy,
+       password_policy,
        trusted_domains,
 };
index 77df9c1513c79bfcb1f3244d3651b1d0d86a6954..e37bfcad9782237d79d67afee37b27e8b14647bb 100644 (file)
@@ -220,6 +220,36 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
        return result;
 }
 
+/* find the lockout policy of a domain */
+static NTSTATUS lockout_policy(struct winbindd_domain *domain, 
+                              TALLOC_CTX *mem_ctx,
+                              SAM_UNK_INFO_12 *lockout_policy)
+{
+       NTSTATUS result;
+
+       result = msrpc_methods.lockout_policy(domain, mem_ctx, lockout_policy);
+
+       if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))
+               result = msrpc_methods.lockout_policy(domain, mem_ctx, lockout_policy);
+
+       return result;
+}
+
+/* find the password policy of a domain */
+static NTSTATUS password_policy(struct winbindd_domain *domain, 
+                               TALLOC_CTX *mem_ctx,
+                               SAM_UNK_INFO_1 *password_policy)
+{
+       NTSTATUS result;
+       result = msrpc_methods.password_policy(domain, mem_ctx, password_policy);
+
+       if (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))
+               result = msrpc_methods.password_policy(domain, mem_ctx, password_policy);
+       
+       return result;
+}
+
 /* get a list of trusted domains */
 static NTSTATUS trusted_domains(struct winbindd_domain *domain,
                                TALLOC_CTX *mem_ctx,
@@ -255,5 +285,7 @@ struct winbindd_methods reconnect_methods = {
        lookup_useraliases,
        lookup_groupmem,
        sequence_number,
+       lockout_policy,
+       password_policy,
        trusted_domains,
 };
index 6179189e30904cec6654dc7809f975ef014f668b..4aaedad4a216cbfd8d0d4a155dfe4b808ff6d34c 100644 (file)
@@ -269,7 +269,7 @@ NTSTATUS msrpc_name_to_sid(struct winbindd_domain *domain,
                return result;
 
        result = rpccli_lsa_lookup_names(cli, mem_ctx, &lsa_policy, 1, 
-                                        &full_name, &sids, &types);
+                                        &full_name, NULL, &sids, &types);
         
        if (!NT_STATUS_IS_OK(result))
                return result;
@@ -883,6 +883,71 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
        return result;
 }
 
+/* find the lockout policy for a domain */
+NTSTATUS msrpc_lockout_policy(struct winbindd_domain *domain, 
+                             TALLOC_CTX *mem_ctx,
+                             SAM_UNK_INFO_12 *lockout_policy)
+{
+       NTSTATUS result;
+       struct rpc_pipe_client *cli;
+       POLICY_HND dom_pol;
+       SAM_UNK_CTR ctr;
+
+       DEBUG(10,("rpc: fetch lockout policy for %s\n", domain->name));
+
+       result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
+       if (!NT_STATUS_IS_OK(result)) {
+               goto done;
+       }
+
+       result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 12, &ctr);
+       if (!NT_STATUS_IS_OK(result)) {
+               goto done;
+       }
+
+       *lockout_policy = ctr.info.inf12;
+
+       DEBUG(10,("msrpc_lockout_policy: bad_attempt_lockout %d\n", 
+               ctr.info.inf12.bad_attempt_lockout));
+
+  done:
+
+       return result;
+}
+
+/* find the password policy for a domain */
+NTSTATUS msrpc_password_policy(struct winbindd_domain *domain, 
+                              TALLOC_CTX *mem_ctx,
+                              SAM_UNK_INFO_1 *password_policy)
+{
+       NTSTATUS result;
+       struct rpc_pipe_client *cli;
+       POLICY_HND dom_pol;
+       SAM_UNK_CTR ctr;
+
+       DEBUG(10,("rpc: fetch password policy for %s\n", domain->name));
+
+       result = cm_connect_sam(domain, mem_ctx, &cli, &dom_pol);
+       if (!NT_STATUS_IS_OK(result)) {
+               goto done;
+       }
+
+       result = rpccli_samr_query_dom_info(cli, mem_ctx, &dom_pol, 1, &ctr);
+       if (!NT_STATUS_IS_OK(result)) {
+               goto done;
+       }
+
+       *password_policy = ctr.info.inf1;
+
+       DEBUG(10,("msrpc_password_policy: min_length_password %d\n", 
+               ctr.info.inf1.min_length_password));
+
+  done:
+
+       return result;
+}
+
+
 /* the rpc backend methods are exposed via this structure */
 struct winbindd_methods msrpc_methods = {
        False,
@@ -896,5 +961,7 @@ struct winbindd_methods msrpc_methods = {
        msrpc_lookup_useraliases,
        lookup_groupmem,
        sequence_number,
+       msrpc_lockout_policy,
+       msrpc_password_policy,
        trusted_domains,
 };
index fc878cb5ccbe64a7ea9b04e51897cccfdb1efd97..a4cd8f760428cac0b85e9290311d6938dd540358 100644 (file)
@@ -506,10 +506,10 @@ static void gid2sid_idmap_set_mapping_recv(void *private_data, BOOL success)
        request_ok(state->cli_state);
 }
 
-void winbindd_allocate_rid(struct winbindd_cli_state *state)
+void winbindd_allocate_uid(struct winbindd_cli_state *state)
 {
        if ( !state->privileged ) {
-               DEBUG(2, ("winbindd_allocate_rid: non-privileged access "
+               DEBUG(2, ("winbindd_allocate_uid: non-privileged access "
                          "denied!\n"));
                request_error(state);
                return;
@@ -518,25 +518,22 @@ void winbindd_allocate_rid(struct winbindd_cli_state *state)
        sendto_child(state, idmap_child());
 }
 
-enum winbindd_result winbindd_dual_allocate_rid(struct winbindd_domain *domain,
+enum winbindd_result winbindd_dual_allocate_uid(struct winbindd_domain *domain,
                                                struct winbindd_cli_state *state)
 {
-       /* We tell idmap to always allocate a user RID. There might be a good
-        * reason to keep RID allocation for users to even and groups to
-        * odd. This needs discussion I think. For now only allocate user
-        * rids. */
+       union unid_t id;
 
-       if (!NT_STATUS_IS_OK(idmap_allocate_rid(&state->response.data.rid,
-                                               USER_RID_TYPE)))
+       if (!NT_STATUS_IS_OK(idmap_allocate_id(&id, ID_USERID))) {
                return WINBINDD_ERROR;
-
+       }
+       state->response.data.uid = id.uid;
        return WINBINDD_OK;
 }
 
-void winbindd_allocate_rid_and_gid(struct winbindd_cli_state *state)
+void winbindd_allocate_gid(struct winbindd_cli_state *state)
 {
        if ( !state->privileged ) {
-               DEBUG(2, ("winbindd_allocate_rid: non-privileged access "
+               DEBUG(2, ("winbindd_allocate_gid: non-privileged access "
                          "denied!\n"));
                request_error(state);
                return;
@@ -545,30 +542,15 @@ void winbindd_allocate_rid_and_gid(struct winbindd_cli_state *state)
        sendto_child(state, idmap_child());
 }
 
-enum winbindd_result winbindd_dual_allocate_rid_and_gid(struct winbindd_domain *domain,
-                                                       struct winbindd_cli_state *state)
+enum winbindd_result winbindd_dual_allocate_gid(struct winbindd_domain *domain,
+                                               struct winbindd_cli_state *state)
 {
-       NTSTATUS result;
-       DOM_SID sid;
-
-       /* We tell idmap to always allocate a user RID. This is really
-        * historic and needs to be fixed. I *think* this has to do with the
-        * way winbind determines its free RID space. */
-
-       result = idmap_allocate_rid(&state->response.data.rid_and_gid.rid,
-                                   USER_RID_TYPE);
+       union unid_t id;
 
-       if (!NT_STATUS_IS_OK(result))
+       if (!NT_STATUS_IS_OK(idmap_allocate_id(&id, ID_GROUPID))) {
                return WINBINDD_ERROR;
-
-       sid_copy(&sid, get_global_sam_sid());
-       sid_append_rid(&sid, state->response.data.rid_and_gid.rid);
-
-       result = idmap_sid_to_gid(&sid, &state->response.data.rid_and_gid.gid,
-                                 0);
-
-       if (!NT_STATUS_IS_OK(result))
-               return WINBINDD_ERROR;
-
+       }
+       state->response.data.gid = id.gid;
        return WINBINDD_OK;
 }
+
index 0b88d5eee5f760893addc799b21cce415f732900..9670bf534cb9fc9356c8c93d9f7fae6dace602b3 100644 (file)
@@ -122,10 +122,10 @@ static BOOL winbindd_fill_pwent(char *dom_name, char *user_name,
                             pw->pw_uid, pw->pw_gid, shell, pw->pw_shell))
                return False;
 
-       /* Password - set to "x" as we can't generate anything useful here.
+       /* Password - set to "*" as we can't generate anything useful here.
           Authentication can be done using the pam_winbind module. */
 
-       safe_strcpy(pw->pw_passwd, "x", sizeof(pw->pw_passwd) - 1);
+       safe_strcpy(pw->pw_passwd, "*", sizeof(pw->pw_passwd) - 1);
 
        return True;
 }
@@ -307,10 +307,10 @@ static void getpwsid_sid2gid_recv(void *private_data, BOOL success, gid_t gid)
                goto failed;
        }
 
-       /* Password - set to "x" as we can't generate anything useful here.
+       /* Password - set to "*" as we can't generate anything useful here.
           Authentication can be done using the pam_winbind module. */
 
-       safe_strcpy(pw->pw_passwd, "x", sizeof(pw->pw_passwd) - 1);
+       safe_strcpy(pw->pw_passwd, "*", sizeof(pw->pw_passwd) - 1);
 
        request_ok(s->state);
        return;
index 4c3306a8acab7eaa99d0ca0f38e7d20d52e5e2c5..b92ee0de825f8a3c19116fcf13a248a3f457fa64 100644 (file)
@@ -161,6 +161,7 @@ static struct winbindd_domain *add_trusted_domain(const char *domain_name, const
        domain->sequence_number = DOM_SEQUENCE_NONE;
        domain->last_seq_check = 0;
        domain->initialized = False;
+       domain->online = False;
        if (sid) {
                sid_copy(&domain->sid, sid);
        }
@@ -334,6 +335,7 @@ enum winbindd_result init_child_connection(struct winbindd_domain *domain,
        struct winbindd_request *request;
        struct winbindd_response *response;
        struct init_child_state *state;
+       struct winbindd_domain *request_domain;
 
        mem_ctx = talloc_init("init_child_connection");
        if (mem_ctx == NULL) {
@@ -366,7 +368,6 @@ enum winbindd_result init_child_connection(struct winbindd_domain *domain,
                fstrcpy(request->domain_name, domain->name);
                request->data.init_conn.is_primary = True;
                fstrcpy(request->data.init_conn.dcname, "");
-
                async_request(mem_ctx, &domain->child, request, response,
                              init_child_recv, state);
                return WINBINDD_PENDING;
@@ -378,7 +379,11 @@ enum winbindd_result init_child_connection(struct winbindd_domain *domain,
        request->cmd = WINBINDD_GETDCNAME;
        fstrcpy(request->domain_name, domain->name);
 
-       async_domain_request(mem_ctx, find_our_domain(), request, response,
+       /* save online flag */
+       request_domain = find_our_domain();
+       request_domain->online = domain->online;
+       
+       async_domain_request(mem_ctx, request_domain, request, response,
                             init_child_getdc_recv, state);
        return WINBINDD_PENDING;
 }
@@ -1079,10 +1084,6 @@ static int convert_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA data, void *state
 #define HWM_GROUP  "GROUP HWM"
 #define HWM_USER   "USER HWM"
 
-/* idmap version determines auto-conversion */
-#define IDMAP_VERSION 2
-
-
 /*****************************************************************************
  Convert the idmap database from an older version.
 *****************************************************************************/
index 70275abf9224a91ddf1a7104acfd38a2b7719481..cbdb6fa811620e857c8cd73e6e032f87cc3ac5ab 100644 (file)
@@ -199,10 +199,10 @@ static int _smb_add_user(pam_handle_t *pamh, unsigned int ctrl,
 
     /* Add the user to the db if they aren't already there. */
    if (!exist) {
-       retval = local_password_change( name, LOCAL_ADD_USER|LOCAL_SET_PASSWORD,
+       retval = NT_STATUS_IS_OK(local_password_change( name, LOCAL_ADD_USER|LOCAL_SET_PASSWORD,
                                         pass, err_str,
                                         sizeof(err_str),
-                                        msg_str, sizeof(msg_str) );
+                                        msg_str, sizeof(msg_str) ));
        if (!retval && *err_str)
        {
            err_str[PSTRING_LEN-1] = '\0';
@@ -221,8 +221,8 @@ static int _smb_add_user(pam_handle_t *pamh, unsigned int ctrl,
     /* mimick 'update encrypted' as long as the 'no pw req' flag is not set */
     if ( pdb_get_acct_ctrl(sampass) & ~ACB_PWNOTREQ )
     {
-       retval = local_password_change( name, LOCAL_SET_PASSWORD, pass, err_str, sizeof(err_str),
-                                        msg_str, sizeof(msg_str) );
+       retval = NT_STATUS_IS_OK(local_password_change( name, LOCAL_SET_PASSWORD, pass, err_str, sizeof(err_str),
+                                        msg_str, sizeof(msg_str) ));
        if (!retval && *err_str)
        {
            err_str[PSTRING_LEN-1] = '\0';
index 8149bc12003b982d55766ee2ba6661447c9bd331..176b278c0439b8a279affe3f11a14c89e198f8b8 100644 (file)
@@ -47,9 +47,9 @@ int smb_update_db( pam_handle_t *pamh, int ctrl, const char *user,  const char *
        err_str[0] = '\0';
        msg_str[0] = '\0';
 
-       retval = local_password_change( user, LOCAL_SET_PASSWORD, pass_new,
+       retval = NT_STATUS_IS_OK(local_password_change( user, LOCAL_SET_PASSWORD, pass_new,
                                        err_str, sizeof(err_str),
-                                       msg_str, sizeof(msg_str) );
+                                       msg_str, sizeof(msg_str) ));
 
        if (!retval) {
                if (*err_str) {
@@ -298,7 +298,7 @@ int pam_sm_chauthtok(pam_handle_t *pamh, int flags,
            uid_t uid;
            
             /* password updated */
-               if (!NT_STATUS_IS_OK(sid_to_uid(pdb_get_user_sid(sampass), &uid))) {
+               if (!sid_to_uid(pdb_get_user_sid(sampass), &uid)) {
                        _log_err( LOG_NOTICE, "Unable to get uid for user %s",
                                pdb_get_username(sampass));
                        _log_err( LOG_NOTICE, "password for (%s) changed by (%s/%d)",
index 3f2c638816003c46b51de2316f138a3a3e97bd2f..add74acc5da21e5569f3e372d4971fb3d3dec4f3 100644 (file)
@@ -398,7 +398,7 @@ int _smb_verify_password( pam_handle_t * pamh, SAM_ACCOUNT *sampass,
                       service ? service : "**unknown**", name);
                     newauth->count = 1;
                 }
-               if (!NT_STATUS_IS_OK(sid_to_uid(pdb_get_user_sid(sampass), &(newauth->id)))) {
+               if (!sid_to_uid(pdb_get_user_sid(sampass), &(newauth->id))) {
                     _log_err(LOG_NOTICE,
                       "failed auth request by %s for service %s as %s",
                       uidtoname(getuid()),
index a2aa851b095f918e15f04cdd2f291413aaff3426..a8867280474811f84b323b76e671d605172a6fce 100644 (file)
@@ -54,6 +54,7 @@
 #include "includes.h"
 
 BOOL in_client = False;                /* Not in the client by default */
+BOOL in_server = False;                /* Not in the server by default */
 BOOL bLoaded = False;
 
 extern userdom_struct current_user_info;
@@ -76,6 +77,9 @@ extern enum protocol_types Protocol;
 #define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
 #define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
 
+#define USERSHARE_VALID 1
+#define USERSHARE_PENDING_DELETE 2
+
 int keepalive = DEFAULT_KEEPALIVE;
 BOOL use_getwd_cache = True;
 
@@ -94,8 +98,7 @@ struct _param_opt_struct {
 /* 
  * This structure describes global (ie., server-wide) parameters.
  */
-typedef struct
-{
+typedef struct {
        char *smb_ports;
        char *dos_charset;
        char *unix_charset;
@@ -167,7 +170,6 @@ typedef struct
        BOOL bUtmp;
        char *szIdmapUID;
        char *szIdmapGID;
-       BOOL bEnableRidAlgorithm;
        BOOL bPassdbExpandExplicit;
        int AlgorithmicRidBase;
        char *szTemplateHomedir;
@@ -178,6 +180,8 @@ typedef struct
        BOOL bWinbindUseDefaultDomain;
        BOOL bWinbindTrustedDomainsOnly;
        BOOL bWinbindNestedGroups;
+       BOOL bWinbindRefreshTickets;
+       BOOL bWinbindOfflineLogon;
        char **szIdmapBackend;
        char *szAddShareCommand;
        char *szChangeShareCommand;
@@ -186,6 +190,10 @@ typedef struct
        char *szGuestaccount;
        char *szManglingMethod;
        char **szServicesList;
+       char *szUsersharePath;
+       char *szUsershareTemplateShare;
+       char **szUsersharePrefixAllowList;
+       char **szUsersharePrefixDenyList;
        int mangle_prefix;
        int max_log_size;
        char *szLogLevel;
@@ -299,24 +307,27 @@ typedef struct
        BOOL bDeferSharingViolations;
        BOOL bEnablePrivileges;
        BOOL bASUSupport;
+       BOOL bUsershareOwnerOnly;
        int restrict_anonymous;
        int name_cache_timeout;
        int client_signing;
        int server_signing;
+       int iUsershareMaxShares;
+
        BOOL bResetOnZeroVC;
        param_opt_struct *param_opt;
-}
-global;
+} global;
 
 static global Globals;
 
 /* 
  * This structure describes a single service. 
  */
-typedef struct
-{
+typedef struct {
        BOOL valid;
        BOOL autoloaded;
+       int usershare;
+       time_t usershare_last_mod;
        char *szService;
        char *szPath;
        char *szUsername;
@@ -445,14 +456,15 @@ typedef struct
        param_opt_struct *param_opt;
 
        char dummy[3];          /* for alignment */
-}
-service;
+} service;
 
 
 /* This is a default service used to prime a services structure */
 static service sDefault = {
        True,                   /* valid */
        False,                  /* not autoloaded */
+       0,                      /* not a usershare */
+       (time_t)0,              /* No last mod time */
        NULL,                   /* szService */
        NULL,                   /* szPath */
        NULL,                   /* szUsername */
@@ -1214,6 +1226,12 @@ static struct parm_struct parm_table[] = {
        {"root preexec close", P_BOOL, P_LOCAL, &sDefault.bRootpreexecClose, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
        {"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
        {"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT}, 
+       {"usershare max shares", P_INTEGER, P_GLOBAL, &Globals.iUsershareMaxShares, NULL, NULL, FLAG_ADVANCED},
+       {"usershare owner only", P_BOOL, P_GLOBAL, &Globals.bUsershareOwnerOnly, NULL, NULL, FLAG_ADVANCED}, 
+       {"usershare path", P_STRING, P_GLOBAL, &Globals.szUsersharePath, NULL, NULL, FLAG_ADVANCED},
+       {"usershare prefix allow list", P_LIST, P_GLOBAL, &Globals.szUsersharePrefixAllowList, NULL, NULL, FLAG_ADVANCED}, 
+       {"usershare prefix deny list", P_LIST, P_GLOBAL, &Globals.szUsersharePrefixDenyList, NULL, NULL, FLAG_ADVANCED}, 
+       {"usershare template share", P_STRING, P_GLOBAL, &Globals.szUsershareTemplateShare, NULL, NULL, FLAG_ADVANCED},
        {"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE }, 
        {"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
        {"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE}, 
@@ -1242,7 +1260,6 @@ static struct parm_struct parm_table[] = {
 
        {N_("Winbind options"), P_SEP, P_SEPARATOR}, 
 
-       {"enable rid algorithm", P_BOOL, P_GLOBAL, &Globals.bEnableRidAlgorithm, NULL, NULL, FLAG_DEPRECATED}, 
        {"passdb expand explicit", P_BOOL, P_GLOBAL, &Globals.bPassdbExpandExplicit, NULL, NULL, FLAG_ADVANCED},
        {"idmap backend", P_LIST, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED}, 
        {"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED}, 
@@ -1260,6 +1277,8 @@ static struct parm_struct parm_table[] = {
        {"winbind nested groups", P_BOOL, P_GLOBAL, &Globals.bWinbindNestedGroups, NULL, NULL, FLAG_ADVANCED}, 
        {"winbind max idle children", P_INTEGER, P_GLOBAL, &Globals.winbind_max_idle_children, NULL, NULL, FLAG_ADVANCED}, 
        {"winbind nss info", P_LIST, P_GLOBAL, &Globals.szWinbindNssInfo, NULL, NULL, FLAG_ADVANCED}, 
+       {"winbind refresh tickets", P_BOOL, P_GLOBAL, &Globals.bWinbindRefreshTickets, NULL, NULL, FLAG_ADVANCED}, 
+       {"winbind offline logon", P_BOOL, P_GLOBAL, &Globals.bWinbindOfflineLogon, NULL, NULL, FLAG_ADVANCED},
 
        {NULL,  P_BOOL,  P_NONE,  NULL,  NULL,  NULL,  0}
 };
@@ -1612,8 +1631,9 @@ static void init_globals(BOOL first_time_only)
        Globals.bWinbindNestedGroups = False;
        Globals.winbind_max_idle_children = 3;
        Globals.szWinbindNssInfo = str_list_make("template", NULL);
+       Globals.bWinbindRefreshTickets = False;
+       Globals.bWinbindOfflineLogon = False;
 
-       Globals.bEnableRidAlgorithm = True;
        Globals.bPassdbExpandExplicit = True;
 
        Globals.name_cache_timeout = 660; /* In seconds */
@@ -1636,6 +1656,15 @@ static void init_globals(BOOL first_time_only)
        Globals.bASUSupport       = True;
        
        Globals.szServicesList = str_list_make( "Spooler NETLOGON", NULL );
+
+       /* User defined shares. */
+       pstrcpy(s, dyn_LOCKDIR);
+       pstrcat(s, "/usershares");
+       string_set(&Globals.szUsersharePath, s);
+       string_set(&Globals.szUsershareTemplateShare, "");
+       Globals.iUsershareMaxShares = 0;
+       /* By default disallow sharing of directories not owned by the sharer. */
+       Globals.bUsershareOwnerOnly = True;
 }
 
 static TALLOC_CTX *lp_talloc;
@@ -1652,6 +1681,19 @@ void lp_talloc_free(void)
        lp_talloc = NULL;
 }
 
+TALLOC_CTX *tmp_talloc_ctx(void)
+{
+       if (lp_talloc == NULL) {
+               lp_talloc = talloc_init(NULL);
+       }
+
+       if (lp_talloc == NULL) {
+               smb_panic("Could not create temporary talloc context\n");
+       }
+
+       return lp_talloc;
+}
+
 /*******************************************************************
  Convenience routine to grab string parameters into temporary memory
  and run standard_sub_basic on them. The buffers can be written to by
@@ -1800,10 +1842,10 @@ FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
 FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
 FN_GLOBAL_BOOL(lp_winbind_trusted_domains_only, &Globals.bWinbindTrustedDomainsOnly)
 FN_GLOBAL_BOOL(lp_winbind_nested_groups, &Globals.bWinbindNestedGroups)
-
+FN_GLOBAL_BOOL(lp_winbind_refresh_tickets, &Globals.bWinbindRefreshTickets)
+FN_GLOBAL_BOOL(lp_winbind_offline_logon, &Globals.bWinbindOfflineLogon)
 
 FN_GLOBAL_LIST(lp_idmap_backend, &Globals.szIdmapBackend)
-FN_GLOBAL_BOOL(lp_enable_rid_algorithm, &Globals.bEnableRidAlgorithm)
 FN_GLOBAL_BOOL(lp_passdb_expand_explicit, &Globals.bPassdbExpandExplicit)
 
 #ifdef WITH_LDAP_SAMCONFIG
@@ -1821,9 +1863,13 @@ FN_GLOBAL_INTEGER(lp_ldap_page_size, &Globals.ldap_page_size)
 FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
 FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
 FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
+FN_GLOBAL_STRING(lp_usershare_path, &Globals.szUsersharePath)
+FN_GLOBAL_LIST(lp_usershare_prefix_allow_list, &Globals.szUsersharePrefixAllowList)
+FN_GLOBAL_LIST(lp_usershare_prefix_deny_list, &Globals.szUsersharePrefixDenyList)
 
 FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs)
 
+FN_GLOBAL_BOOL(lp_usershare_owner_only, &Globals.bUsershareOwnerOnly)
 FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
 FN_GLOBAL_BOOL(lp_reset_on_zero_vc, &Globals.bResetOnZeroVC)
 FN_GLOBAL_BOOL(lp_ms_add_printer_wizard, &Globals.bMsAddPrinterWizard)
@@ -1912,6 +1958,8 @@ FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
 FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
 FN_GLOBAL_INTEGER(lp_lock_spin_count, &Globals.iLockSpinCount)
 FN_GLOBAL_INTEGER(lp_lock_sleep_time, &Globals.iLockSpinTime)
+FN_GLOBAL_INTEGER(lp_usershare_max_shares, &Globals.iUsershareMaxShares)
+
 FN_LOCAL_STRING(lp_preexec, szPreExec)
 FN_LOCAL_STRING(lp_postexec, szPostExec)
 FN_LOCAL_STRING(lp_rootpreexec, szRootPreExec)
@@ -2479,7 +2527,7 @@ static char *canonicalize_servicename(const char *src)
        }
 
        fstrcpy( canon, src );
-       strupper_m( canon );
+       strlower_m( canon );
 
        return canon;
 }
@@ -4028,9 +4076,11 @@ void lp_killunused(BOOL (*snumused) (int))
                if (!VALID(i))
                        continue;
 
-               /* don't kill autoloaded services */
-               if ( ServicePtrs[i]->autoloaded )
+               /* don't kill autoloaded or usershare services */
+               if ( ServicePtrs[i]->autoloaded ||
+                               ServicePtrs[i]->usershare == USERSHARE_VALID) {
                        continue;
+               }
 
                if (!snumused || !snumused(i)) {
                        free_service_byindex(i);
@@ -4179,6 +4229,7 @@ static void set_server_role(void)
 /***********************************************************
  If we should send plaintext/LANMAN passwords in the clinet
 ************************************************************/
+
 static void set_allowed_client_auth(void)
 {
        if (Globals.bClientNTLMv2Auth) {
@@ -4189,6 +4240,611 @@ static void set_allowed_client_auth(void)
        }
 }
 
+/***************************************************************************
+ JRA.
+ The following code allows smbd to read a user defined share file.
+ Yes, this is my intent. Yes, I'm comfortable with that...
+
+ THE FOLLOWING IS SECURITY CRITICAL CODE.
+
+ It washes your clothes, it cleans your house, it guards you while you sleep...
+ Do not f%^k with it....
+***************************************************************************/
+
+#define MAX_USERSHARE_FILE_SIZE (10*1024)
+
+/***************************************************************************
+ Check allowed stat state of a usershare file.
+ Ensure we print out who is dicking with us so the admin can
+ get their sorry ass fired.
+***************************************************************************/
+
+static BOOL check_usershare_stat(const char *fname, SMB_STRUCT_STAT *psbuf)
+{
+       if (!S_ISREG(psbuf->st_mode)) {
+               DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
+                       "not a regular file\n",
+                       fname, (unsigned int)psbuf->st_uid ));
+               return False;
+       }
+
+       /* Ensure this doesn't have the other write bit set. */
+       if (psbuf->st_mode & S_IWOTH) {
+               DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
+                       "public write. Refusing to allow as a usershare file.\n",
+                       fname, (unsigned int)psbuf->st_uid ));
+               return False;
+       }
+
+       /* Should be 10k or less. */
+       if (psbuf->st_size > MAX_USERSHARE_FILE_SIZE) {
+               DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
+                       "too large (%u) to be a user share file.\n",
+                       fname, (unsigned int)psbuf->st_uid,
+                       (unsigned int)psbuf->st_size ));
+               return False;
+       }
+
+       return True;
+}
+
+/***************************************************************************
+ Parse the contents of a usershare file.
+***************************************************************************/
+
+enum usershare_err parse_usershare_file(TALLOC_CTX *ctx, 
+                       SMB_STRUCT_STAT *psbuf,
+                       const char *servicename,
+                       int snum,
+                       char **lines,
+                       int numlines,
+                       pstring sharepath,
+                       pstring comment,
+                       SEC_DESC **ppsd)
+{
+       const char **prefixallowlist = lp_usershare_prefix_allow_list();
+       const char **prefixdenylist = lp_usershare_prefix_deny_list();
+       SMB_STRUCT_DIR *dp;
+       SMB_STRUCT_STAT sbuf;
+
+       if (numlines < 4) {
+               return USERSHARE_MALFORMED_FILE;
+       }
+
+       if (!strequal(lines[0], "#VERSION 1")) {
+               return USERSHARE_BAD_VERSION;
+       }
+
+       if (!strnequal(lines[1], "path=", 5)) {
+               return USERSHARE_MALFORMED_PATH;
+       }
+
+       pstrcpy(sharepath, &lines[1][5]);
+       trim_string(sharepath, " ", " ");
+
+       if (!strnequal(lines[2], "comment=", 8)) {
+               return USERSHARE_MALFORMED_COMMENT_DEF;
+       }
+
+       pstrcpy(comment, &lines[2][8]);
+       trim_string(comment, " ", " ");
+       trim_char(comment, '"', '"');
+
+       if (!strnequal(lines[3], "usershare_acl=", 14)) {
+               return USERSHARE_MALFORMED_ACL_DEF;
+       }
+
+       if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
+               return USERSHARE_ACL_ERR;
+       }
+
+       if (snum != -1 && strequal(sharepath, ServicePtrs[snum]->szPath)) {
+               /* Path didn't change, no checks needed. */
+               return USERSHARE_OK;
+       }
+
+       /* The path *must* be absolute. */
+       if (sharepath[0] != '/') {
+               DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
+                       servicename, sharepath));
+               return USERSHARE_PATH_NOT_ABSOLUTE;
+       }
+
+       /* If there is a usershare prefix deny list ensure one of these paths
+          doesn't match the start of the user given path. */
+       if (prefixdenylist) {
+               int i;
+               for ( i=0; prefixdenylist[i]; i++ ) {
+                       DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
+                               servicename, i, prefixdenylist[i], sharepath ));
+                       if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
+                               DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
+                                       "usershare prefix deny list entries.\n",
+                                       servicename, sharepath));
+                               return USERSHARE_PATH_IS_DENIED;
+                       }
+               }
+       }
+
+       /* If there is a usershare prefix allow list ensure one of these paths
+          does match the start of the user given path. */
+
+       if (prefixallowlist) {
+               int i;
+               for ( i=0; prefixallowlist[i]; i++ ) {
+                       DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
+                               servicename, i, prefixallowlist[i], sharepath ));
+                       if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
+                               break;
+                       }
+               }
+               if (prefixallowlist[i] == NULL) {
+                       DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
+                               "usershare prefix allow list entries.\n",
+                               servicename, sharepath));
+                       return USERSHARE_PATH_NOT_ALLOWED;
+               }
+        }
+
+       /* Ensure this is pointing to a directory. */
+       dp = sys_opendir(sharepath);
+
+       if (!dp) {
+               DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
+                       servicename, sharepath));
+               return USERSHARE_PATH_NOT_DIRECTORY;
+       }
+
+       /* Ensure the owner of the usershare file has permission to share
+          this directory. */
+
+       if (sys_stat(sharepath, &sbuf) == -1) {
+               DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
+                       servicename, sharepath, strerror(errno) ));
+               sys_closedir(dp);
+               return USERSHARE_POSIX_ERR;
+       }
+
+       sys_closedir(dp);
+
+       if (!S_ISDIR(sbuf.st_mode)) {
+               DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
+                       servicename, sharepath ));
+               return USERSHARE_PATH_NOT_DIRECTORY;
+       }
+
+       /* Check if sharing is restricted to owner-only. */
+       /* psbuf is the stat of the usershare definition file,
+          sbuf is the stat of the target directory to be shared. */
+
+       if (lp_usershare_owner_only()) {
+               /* root can share anything. */
+               if ((psbuf->st_uid != 0) && (sbuf.st_uid != psbuf->st_uid)) {
+                       return USERSHARE_PATH_NOT_ALLOWED;
+               }
+       }
+
+       return USERSHARE_OK;
+}
+
+/***************************************************************************
+ Deal with a usershare file.
+ Returns:
+       >= 0 - snum
+       -1 - Bad name, invalid contents.
+          - service name already existed and not a usershare, problem
+           with permissions to share directory etc.
+***************************************************************************/
+
+static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
+{
+       SMB_STRUCT_STAT sbuf;
+       SMB_STRUCT_STAT lsbuf;
+       pstring fname;
+       pstring sharepath;
+       pstring comment;
+       fstring service_name;
+       char **lines = NULL;
+       int numlines = 0;
+       int fd = -1;
+       int iService = -1;
+       TALLOC_CTX *ctx = NULL;
+       SEC_DESC *psd = NULL;
+
+       /* Ensure share name doesn't contain invalid characters. */
+       if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
+               DEBUG(0,("process_usershare_file: share name %s contains "
+                       "invalid characters (any of %s)\n",
+                       file_name, INVALID_SHARENAME_CHARS ));
+               return -1;
+       }
+
+       fstrcpy(service_name, file_name);
+
+       pstrcpy(fname, dir_name);
+       pstrcat(fname, "/");
+       pstrcat(fname, file_name);
+
+       /* Minimize the race condition by doing an lstat before we
+          open and fstat. Ensure this isn't a symlink link. */
+
+       if (sys_lstat(fname, &lsbuf) != 0) {
+               DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
+                       fname, strerror(errno) ));
+               return -1;
+       }
+
+       /* This must be a regular file, not a symlink, directory or
+          other strange filetype. */
+       if (!check_usershare_stat(fname, &lsbuf)) {
+               return -1;
+       }
+
+       /* See if there is already a servicenum for this name. */
+       /* tdb_fetch_int32 returns -1 if not found. */
+       iService = (int)tdb_fetch_int32(ServiceHash, canonicalize_servicename(service_name) );
+
+       if (iService != -1 && ServicePtrs[iService]->usershare_last_mod == lsbuf.st_mtime) {
+               /* Nothing changed - Mark valid and return. */
+               DEBUG(10,("process_usershare_file: service %s not changed.\n",
+                       service_name ));
+               ServicePtrs[iService]->usershare = USERSHARE_VALID;
+               return iService;
+       }
+
+       /* Try and open the file read only - no symlinks allowed. */
+#ifdef O_NOFOLLOW
+       fd = sys_open(fname, O_RDONLY|O_NOFOLLOW, 0);
+#else
+       fd = sys_open(fname, O_RDONLY, 0);
+#endif
+
+       if (fd == -1) {
+               DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
+                       fname, strerror(errno) ));
+               return -1;
+       }
+
+       /* Now fstat to be *SURE* it's a regular file. */
+       if (sys_fstat(fd, &sbuf) != 0) {
+               close(fd);
+               DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
+                       fname, strerror(errno) ));
+               return -1;
+       }
+
+       /* Is it the same dev/inode as was lstated ? */
+       if (lsbuf.st_dev != sbuf.st_dev || lsbuf.st_ino != sbuf.st_ino) {
+               close(fd);
+               DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
+                       "Symlink spoofing going on ?\n", fname ));
+               return -1;
+       }
+
+       /* This must be a regular file, not a symlink, directory or
+          other strange filetype. */
+       if (!check_usershare_stat(fname, &sbuf)) {
+               return -1;
+       }
+
+       lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE);
+
+       close(fd);
+       if (lines == NULL) {
+               DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
+                       fname, (unsigned int)sbuf.st_uid ));
+       }
+
+       /* Should we allow printers to be shared... ? */
+       ctx = talloc_init("usershare_sd_xctx");
+       if (!ctx) {
+               SAFE_FREE(lines);
+               return 1;
+       }
+
+       if (parse_usershare_file(ctx, &sbuf, service_name, iService, lines, numlines, sharepath, comment, &psd) != USERSHARE_OK) {
+               talloc_destroy(ctx);
+               SAFE_FREE(lines);
+               return -1;
+       }
+
+       SAFE_FREE(lines);
+
+       /* Everything ok - add the service possibly using a template. */
+       if (iService < 0) {
+               const service *sp = &sDefault;
+               if (snum_template != -1) {
+                       sp = ServicePtrs[snum_template];
+               }
+
+               if ((iService = add_a_service(sp, service_name)) < 0) {
+                       DEBUG(0, ("process_usershare_file: Failed to add "
+                               "new service %s\n", service_name));
+                       talloc_destroy(ctx);
+                       return -1;
+               }
+
+               /* Read only is controlled by usershare ACL below. */
+               ServicePtrs[iService]->bRead_only = False;
+       }
+
+       /* Write the ACL of the new/modified share. */
+       if (!set_share_security(ctx, service_name, psd)) {
+                DEBUG(0, ("process_usershare_file: Failed to set share "
+                       "security for user share %s\n",
+                       service_name ));
+               lp_remove_service(iService);
+               talloc_destroy(ctx);
+               return -1;
+       }
+
+       talloc_destroy(ctx);
+
+       /* If from a template it may be marked invalid. */
+       ServicePtrs[iService]->valid = True;
+
+       /* Set the service as a valid usershare. */
+       ServicePtrs[iService]->usershare = USERSHARE_VALID;
+
+       /* And note when it was loaded. */
+       ServicePtrs[iService]->usershare_last_mod = sbuf.st_mtime;
+       string_set(&ServicePtrs[iService]->szPath, sharepath);
+       string_set(&ServicePtrs[iService]->comment, comment);
+
+       return iService;
+}
+
+/***************************************************************************
+ Checks if a usershare entry has been modified since last load.
+***************************************************************************/
+
+static BOOL usershare_exists(int iService, time_t *last_mod)
+{
+       SMB_STRUCT_STAT lsbuf;
+       const char *usersharepath = Globals.szUsersharePath;
+       pstring fname;
+
+       pstrcpy(fname, usersharepath);
+       pstrcat(fname, "/");
+       pstrcat(fname, ServicePtrs[iService]->szService);
+
+       if (sys_lstat(fname, &lsbuf) != 0) {
+               return False;
+       }
+
+       if (!S_ISREG(lsbuf.st_mode)) {
+               return False;
+       }
+
+       *last_mod = lsbuf.st_mtime;
+       return True;
+}
+
+/***************************************************************************
+ Load a usershare service by name. Returns a valid servicenumber or -1.
+***************************************************************************/
+
+int load_usershare_service(const char *servicename)
+{
+       SMB_STRUCT_STAT sbuf;
+       const char *usersharepath = Globals.szUsersharePath;
+       int max_user_shares = Globals.iUsershareMaxShares;
+       int snum_template = -1;
+
+       if (*usersharepath == 0 ||  max_user_shares == 0) {
+               return -1;
+       }
+
+       if (sys_stat(usersharepath, &sbuf) != 0) {
+               DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
+                       usersharepath, strerror(errno) ));
+               return -1;
+       }
+
+       if (!S_ISDIR(sbuf.st_mode)) {
+               DEBUG(0,("load_usershare_service: %s is not a directory.\n",
+                       usersharepath ));
+               return -1;
+       }
+
+       /*
+        * This directory must be owned by root, and have the 't' bit set.
+        * It also must not be writable by "other".
+        */
+
+#ifdef S_ISVTX
+       if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
+#else
+       if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
+#endif
+               DEBUG(0,("load_usershare_service: directory %s is not owned by root "
+                       "or does not have the sticky bit 't' set or is writable by anyone.\n",
+                       usersharepath ));
+               return -1;
+       }
+
+       /* Ensure the template share exists if it's set. */
+       if (Globals.szUsershareTemplateShare[0]) {
+               /* We can't use lp_servicenumber here as we are recommending that
+                  template shares have -valid=False set. */
+               for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
+                       if (ServicePtrs[snum_template]->szService &&
+                                       strequal(ServicePtrs[snum_template]->szService,
+                                               Globals.szUsershareTemplateShare)) {
+                               break;
+                       }
+               }
+
+               if (snum_template == -1) {
+                       DEBUG(0,("load_usershare_service: usershare template share %s "
+                               "does not exist.\n",
+                               Globals.szUsershareTemplateShare ));
+                       return -1;
+               }
+       }
+
+       return process_usershare_file(usersharepath, servicename, snum_template);
+}
+
+/***************************************************************************
+ Load all user defined shares from the user share directory.
+ We only do this if we're enumerating the share list.
+ This is the function that can delete usershares that have
+ been removed.
+***************************************************************************/
+
+int load_usershare_shares(void)
+{
+       SMB_STRUCT_DIR *dp;
+       SMB_STRUCT_STAT sbuf;
+       SMB_STRUCT_DIRENT *de;
+       int num_usershares = 0;
+       int max_user_shares = Globals.iUsershareMaxShares;
+       unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
+       unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
+       unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
+       int iService;
+       int snum_template = -1;
+       const char *usersharepath = Globals.szUsersharePath;
+       int ret = lp_numservices();
+
+       if (max_user_shares == 0 || *usersharepath == '\0') {
+               return lp_numservices();
+       }
+
+       if (sys_stat(usersharepath, &sbuf) != 0) {
+               DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
+                       usersharepath, strerror(errno) ));
+               return ret;
+       }
+
+       /*
+        * This directory must be owned by root, and have the 't' bit set.
+        * It also must not be writable by "other".
+        */
+
+#ifdef S_ISVTX
+       if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
+#else
+       if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
+#endif
+               DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
+                       "or does not have the sticky bit 't' set or is writable by anyone.\n",
+                       usersharepath ));
+               return ret;
+       }
+
+       /* Ensure the template share exists if it's set. */
+       if (Globals.szUsershareTemplateShare[0]) {
+               /* We can't use lp_servicenumber here as we are recommending that
+                  template shares have -valid=False set. */
+               for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
+                       if (ServicePtrs[snum_template]->szService &&
+                                       strequal(ServicePtrs[snum_template]->szService,
+                                               Globals.szUsershareTemplateShare)) {
+                               break;
+                       }
+               }
+
+               if (snum_template == -1) {
+                       DEBUG(0,("load_usershare_shares: usershare template share %s "
+                               "does not exist.\n",
+                               Globals.szUsershareTemplateShare ));
+                       return ret;
+               }
+       }
+
+       /* Mark all existing usershares as pending delete. */
+       for (iService = iNumServices - 1; iService >= 0; iService--) {
+               if (VALID(iService) && ServicePtrs[iService]->usershare) {
+                       ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
+               }
+       }
+
+       dp = sys_opendir(usersharepath);
+       if (!dp) {
+               DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
+                       usersharepath, strerror(errno) ));
+               return ret;
+       }
+
+       for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
+                       (de = sys_readdir(dp));
+                       num_dir_entries++ ) {
+               int r;
+               const char *n = de->d_name;
+
+               /* Ignore . and .. */
+               if (*n == '.') {
+                       if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
+                               continue;
+                       }
+               }
+
+               if (n[0] == ':') {
+                       /* Temporary file used when creating a share. */
+                       num_tmp_dir_entries++;
+               }
+
+               /* Allow 20% tmp entries. */
+               if (num_tmp_dir_entries > allowed_tmp_entries) {
+                       DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
+                               "in directory %s\n",
+                               num_tmp_dir_entries, usersharepath));
+                       break;
+               }
+
+               r = process_usershare_file(usersharepath, n, snum_template);
+               if (r == 0) {
+                       /* Update the services count. */
+                       num_usershares++;
+                       if (num_usershares >= max_user_shares) {
+                               DEBUG(0,("load_usershare_shares: max user shares reached "
+                                       "on file %s in directory %s\n",
+                                       n, usersharepath ));
+                               break;
+                       }
+               } else if (r == -1) {
+                       num_bad_dir_entries++;
+               }
+
+               /* Allow 20% bad entries. */
+               if (num_bad_dir_entries > allowed_bad_entries) {
+                       DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
+                               "in directory %s\n",
+                               num_bad_dir_entries, usersharepath));
+                       break;
+               }
+
+               /* Allow 20% bad entries. */
+               if (num_dir_entries > max_user_shares + allowed_bad_entries) {
+                       DEBUG(0,("load_usershare_shares: too many total entries (%u) "
+                       "in directory %s\n",
+                       num_dir_entries, usersharepath));
+                       break;
+               }
+       }
+
+       sys_closedir(dp);
+
+       /* Sweep through and delete any non-refreshed usershares that are
+          not currently in use. */
+       for (iService = iNumServices - 1; iService >= 0; iService--) {
+               if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
+                       if (conn_snum_used(iService)) {
+                               continue;
+                       }
+                       /* Remove from the share ACL db. */
+                       DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
+                               lp_servicename(iService) ));
+                       delete_share_security(iService);
+                       free_service_byindex(iService);
+               }
+       }
+
+       return lp_numservices();
+}
+
 /***************************************************************************
  Load the services array from the services file. Return True on success, 
  False on failure.
@@ -4339,8 +4995,9 @@ int lp_servicenumber(const char *pszServiceName)
        int iService;
         fstring serviceName;
         
-        if (!pszServiceName)
+        if (!pszServiceName) {
                return GLOBAL_SECTION_SNUM;
+       }
         
        for (iService = iNumServices - 1; iService >= 0; iService--) {
                if (VALID(iService) && ServicePtrs[iService]->szService) {
@@ -4350,8 +5007,30 @@ int lp_servicenumber(const char *pszServiceName)
                         */
                        fstrcpy(serviceName, ServicePtrs[iService]->szService);
                        standard_sub_basic(get_current_username(), serviceName,sizeof(serviceName));
-                       if (strequal(serviceName, pszServiceName))
+                       if (strequal(serviceName, pszServiceName)) {
                                break;
+                       }
+               }
+       }
+
+       if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
+               time_t last_mod;
+
+               if (!usershare_exists(iService, &last_mod)) {
+                       /* Remove the share security tdb entry for it. */
+                       delete_share_security(iService);
+                       /* Remove it from the array. */
+                       free_service_byindex(iService);
+                       /* Doesn't exist anymore. */
+                       return GLOBAL_SECTION_SNUM;
+               }
+
+               /* Has it been modified ? If so delete and reload. */
+               if (ServicePtrs[iService]->usershare_last_mod < last_mod) {
+                       /* Remove it from the array. */
+                       free_service_byindex(iService);
+                       /* and now reload it. */
+                       iService = load_usershare_service(pszServiceName);
                }
        }
 
index 2a6c8b3e6504e7fc09def7ff1c3d46ba9875184a..f5ce6bdb647a5846cd932d265c2b755a9d0e73ca 100644 (file)
@@ -532,7 +532,7 @@ static myFILE *OpenConfFile( const char *FileName )
        if (!ret)
                return NULL;
 
-       ret->buf = file_load(FileName, &ret->size);
+       ret->buf = file_load(FileName, &ret->size, 0);
        if( NULL == ret->buf ) {
                DEBUG( lvl, ("%s Unable to open configuration file \"%s\":\n\t%s\n",
                        func, FileName, strerror(errno)) );
index 4640eb6ae5877c29264373ede608823fc593b07f..6266aa9cab72bcd017a6557d0737de32da160ca4 100644 (file)
@@ -3,6 +3,7 @@
    uid/user handling
    Copyright (C) Andrew Tridgell         1992-1998
    Copyright (C) Gerald (Jerry) Carter   2003
+   Copyright (C) Volker Lendecke        2005
    
    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
@@ -67,7 +68,7 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
        if (strequal(domain, get_global_sam_name())) {
 
                /* It's our own domain, lookup the name in passdb */
-               if (lookup_global_sam_name(name, &rid, &type)) {
+               if (lookup_global_sam_name(name, flags, &rid, &type)) {
                        sid_copy(&sid, get_global_sam_sid());
                        sid_append_rid(&sid, rid);
                        goto ok;
@@ -87,16 +88,31 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
                goto failed;
        }
 
-       if (domain[0] != '\0') {
-               /* An explicit domain name was given, here our last resort is
-                * winbind. */
-               if (winbind_lookup_name(domain, name, &sid, &type)) {
+       /* Try the explicit winbind lookup first, don't let it guess the
+        * domain yet at this point yet. This comes later. */
+
+       if ((domain[0] != '\0') &&
+           (winbind_lookup_name(domain, name, &sid, &type))) {
+                       goto ok;
+       }
+
+       if (strequal(domain, unix_users_domain_name())) {
+               if (lookup_unix_user_name(name, &sid)) {
+                       type = SID_NAME_USER;
+                       goto ok;
+               }
+               goto failed;
+       }
+
+       if (strequal(domain, unix_groups_domain_name())) {
+               if (lookup_unix_group_name(name, &sid)) {
+                       type = SID_NAME_DOM_GRP;
                        goto ok;
                }
                goto failed;
        }
 
-       if (!(flags & LOOKUP_NAME_ISOLATED)) {
+       if ((domain[0] == '\0') && (!(flags & LOOKUP_NAME_ISOLATED))) {
                goto failed;
        }
 
@@ -176,7 +192,7 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
 
        /* Both cases are done by looking at our passdb */
 
-       if (lookup_global_sam_name(name, &rid, &type)) {
+       if (lookup_global_sam_name(name, flags, &rid, &type)) {
                domain = talloc_strdup(tmp_ctx, get_global_sam_name());
                sid_copy(&sid, get_global_sam_sid());
                sid_append_rid(&sid, rid);
@@ -232,6 +248,22 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
        }
 
        /* 10. Don't translate */
+
+       /* 11. Ok, windows would end here. Samba has two more options:
+               Unmapped users and unmapped groups */
+
+       if (lookup_unix_user_name(name, &sid)) {
+               domain = talloc_strdup(tmp_ctx, unix_users_domain_name());
+               type = SID_NAME_USER;
+               goto ok;
+       }
+
+       if (lookup_unix_group_name(name, &sid)) {
+               domain = talloc_strdup(tmp_ctx, unix_groups_domain_name());
+               type = SID_NAME_DOM_GRP;
+               goto ok;
+       }
+
  failed:
        talloc_free(tmp_ctx);
        return False;
@@ -265,113 +297,513 @@ BOOL lookup_name(TALLOC_CTX *mem_ctx,
        return True;
 }
 
-/*****************************************************************
- *THE CANONICAL* convert SID to name function.
- Tries local lookup first - for local sids, then tries winbind.
-*****************************************************************/  
+static BOOL winbind_lookup_rids(TALLOC_CTX *mem_ctx,
+                               const DOM_SID *domain_sid,
+                               int num_rids, uint32 *rids,
+                               const char **domain_name,
+                               const char **names, uint32 *types)
+{
+       /* Unless the winbind interface is upgraded, fall back to ask for
+        * individual sids. I imagine introducing a lookuprids operation that
+        * directly proxies to lsa_lookupsids to the correct DC. -- vl */
+
+       int i;
+       for (i=0; i<num_rids; i++) {
+               DOM_SID sid;
+
+               sid_copy(&sid, domain_sid);
+               sid_append_rid(&sid, rids[i]);
+
+               if (winbind_lookup_sid(mem_ctx, &sid,
+                                      *domain_name == NULL ?
+                                      domain_name : NULL,
+                                      &names[i], &types[i])) {
+                       if ((names[i] == NULL) || ((*domain_name) == NULL)) {
+                               return False;
+                       }
+               } else {
+                       types[i] = SID_NAME_UNKNOWN;
+               }
+       }
+       return True;
+}
 
-BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
-               const char **ret_domain, const char **ret_name,
-               enum SID_NAME_USE *ret_type)
+static BOOL lookup_rids(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
+                       int num_rids, uint32_t *rids,
+                       const char **domain_name,
+                       const char ***names, enum SID_NAME_USE **types)
 {
-       const char *domain = NULL;
-       const char *name = NULL;
-       enum SID_NAME_USE type;
-       TALLOC_CTX *tmp_ctx = talloc_new(mem_ctx);
+       int i;
 
-       /* Check if this is our own sid.  This should perhaps be done by
-          winbind?  For the moment handle it here. */
+       *names = TALLOC_ARRAY(mem_ctx, const char *, num_rids);
+       *types = TALLOC_ARRAY(mem_ctx, enum SID_NAME_USE, num_rids);
 
-       if (tmp_ctx == NULL) {
-               DEBUG(0, ("talloc_new failed\n"));
+       if ((*names == NULL) || (*types == NULL)) {
                return False;
        }
 
-       if (sid_check_is_domain(sid)) {
-               domain = talloc_strdup(tmp_ctx, get_global_sam_name());
-               name = talloc_strdup(tmp_ctx, "");
-               type = SID_NAME_DOMAIN;
-               goto ok;
+       if (sid_check_is_domain(domain_sid)) {
+               NTSTATUS result;
+
+               if (*domain_name == NULL) {
+                       *domain_name = talloc_strdup(
+                               mem_ctx, get_global_sam_name());
+               }
+
+               if (*domain_name == NULL) {
+                       return False;
+               }
+
+               become_root();
+               result = pdb_lookup_rids(domain_sid, num_rids, rids,
+                                        *names, *types);
+               unbecome_root();
+
+               return (NT_STATUS_IS_OK(result) ||
+                       NT_STATUS_EQUAL(result, NT_STATUS_NONE_MAPPED) ||
+                       NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED));
        }
 
-       if (sid_check_is_in_our_domain(sid)) {
-               uint32 rid;
-               SMB_ASSERT(sid_peek_rid(sid, &rid));
+       if (sid_check_is_builtin(domain_sid)) {
 
-               /* For our own domain passdb is responsible */
-               if (!lookup_global_sam_rid(tmp_ctx, rid, &name, &type)) {
-                       goto failed;
+               if (*domain_name == NULL) {
+                       *domain_name = talloc_strdup(
+                               mem_ctx, builtin_domain_name());
                }
 
-               domain = talloc_strdup(tmp_ctx, get_global_sam_name());
-               goto ok;
+               if (*domain_name == NULL) {
+                       return False;
+               }
+
+               for (i=0; i<num_rids; i++) {
+                       if (lookup_builtin_rid(*names, rids[i],
+                                              &(*names)[i])) {
+                               if ((*names)[i] == NULL) {
+                                       return False;
+                               }
+                               (*types)[i] = SID_NAME_ALIAS;
+                       } else {
+                               (*types)[i] = SID_NAME_UNKNOWN;
+                       }
+               }
+               return True;
+       }
+
+       if (sid_check_is_wellknown_domain(domain_sid, NULL)) {
+               for (i=0; i<num_rids; i++) {
+                       DOM_SID sid;
+                       sid_copy(&sid, domain_sid);
+                       sid_append_rid(&sid, rids[i]);
+                       if (lookup_wellknown_sid(mem_ctx, &sid,
+                                                domain_name, &(*names)[i])) {
+                               if ((*names)[i] == NULL) {
+                                       return False;
+                               }
+                               (*types)[i] = SID_NAME_WKN_GRP;
+                       } else {
+                               (*types)[i] = SID_NAME_UNKNOWN;
+                       }
+               }
+               return True;
+       }
+
+       if (sid_check_is_unix_users(domain_sid)) {
+               if (*domain_name == NULL) {
+                       *domain_name = talloc_strdup(
+                               mem_ctx, unix_users_domain_name());
+               }
+               for (i=0; i<num_rids; i++) {
+                       (*names)[i] = talloc_strdup(
+                               (*names), uidtoname(rids[i]));
+                       (*types)[i] = SID_NAME_USER;
+               }
+               return True;
+       }
+
+       if (sid_check_is_unix_groups(domain_sid)) {
+               if (*domain_name == NULL) {
+                       *domain_name = talloc_strdup(
+                               mem_ctx, unix_groups_domain_name());
+               }
+               for (i=0; i<num_rids; i++) {
+                       (*names)[i] = talloc_strdup(
+                               (*names), gidtoname(rids[i]));
+                       (*types)[i] = SID_NAME_DOM_GRP;
+               }
+               return True;
+       }
+
+       return winbind_lookup_rids(mem_ctx, domain_sid, num_rids, rids,
+                                  domain_name, *names, *types);
+}
+
+/*
+ * Is the SID a domain as such? If yes, lookup its name.
+ */
+
+static BOOL lookup_as_domain(const DOM_SID *sid, TALLOC_CTX *mem_ctx,
+                            const char **name)
+{
+       const char *tmp;
+       enum SID_NAME_USE type;
+
+       if (sid_check_is_domain(sid)) {
+               *name = talloc_strdup(mem_ctx, get_global_sam_name());
+               return True;
        }
 
        if (sid_check_is_builtin(sid)) {
+               *name = talloc_strdup(mem_ctx, builtin_domain_name());
+               return True;
+       }
 
-               domain = talloc_strdup(tmp_ctx, builtin_domain_name());
+       if (sid_check_is_wellknown_domain(sid, &tmp)) {
+               *name = talloc_strdup(mem_ctx, tmp);
+               return True;
+       }
 
-               /* Yes, W2k3 returns "BUILTIN" both as domain and name here */
-               name = talloc_strdup(tmp_ctx, builtin_domain_name());
-               type = SID_NAME_DOMAIN;
-               goto ok;
+       if (sid->num_auths != 4) {
+               /* This can't be a domain */
+               return False;
        }
 
-       if (sid_check_is_in_builtin(sid)) {
-               uint32 rid;
+       if (IS_DC) {
+               uint32 i, num_domains;
+               struct trustdom_info **domains;
 
-               SMB_ASSERT(sid_peek_rid(sid, &rid));
+               /* This is relatively expensive, but it happens only on DCs
+                * and for SIDs that have 4 sub-authorities and thus look like
+                * domains */
 
-               if (!lookup_builtin_rid(tmp_ctx, rid, &name)) {
-                       goto failed;
+               if (!NT_STATUS_IS_OK(secrets_trusted_domains(mem_ctx,
+                                                            &num_domains,
+                                                            &domains))) {
+                       return False;
                }
 
-               /* There's only aliases in S-1-5-32 */
-               type = SID_NAME_ALIAS;
-               domain = talloc_strdup(tmp_ctx, builtin_domain_name());
+               for (i=0; i<num_domains; i++) {
+                       if (sid_equal(sid, &domains[i]->sid)) {
+                               *name = talloc_strdup(mem_ctx,
+                                                     domains[i]->name);
+                               return True;
+                       }
+               }
+               return False;
+       }
 
-               goto ok;
+       if (winbind_lookup_sid(mem_ctx, sid, &tmp, NULL, &type) &&
+           (type == SID_NAME_DOMAIN)) {
+               *name = tmp;
+               return True;
        }
 
-       if (winbind_lookup_sid(tmp_ctx, sid, &domain, &name, &type)) {
-               goto ok;
+       return False;
+}
+
+/*
+ * This tries to implement the rather weird rules for the lsa_lookup level
+ * parameter.
+ *
+ * This is as close as we can get to what W2k3 does. With this we survive the
+ * RPC-LSALOOKUP samba4 test as of 2006-01-08. NT4 as a PDC is a bit more
+ * different, but I assume that's just being too liberal. For example, W2k3
+ * replies to everything else but the levels 1-6 with INVALID_PARAMETER
+ * whereas NT4 does the same as level 1 (I think). I did not fully test that
+ * with NT4, this is what w2k3 does.
+ *
+ * Level 1: Ask everywhere
+ * Level 2: Ask domain and trusted domains, no builtin and wkn
+ * Level 3: Only ask domain
+ * Level 4: W2k3ad: Only ask AD trusts
+ * Level 5: Don't lookup anything
+ * Level 6: Like 4
+ */
+
+static BOOL check_dom_sid_to_level(const DOM_SID *sid, int level)
+{
+       int ret = False;
+
+       switch(level) {
+       case 1:
+               ret = True;
+               break;
+       case 2:
+               ret = (!sid_check_is_builtin(sid) &&
+                      !sid_check_is_wellknown_domain(sid, NULL));
+               break;
+       case 3:
+       case 4:
+       case 6:
+               ret = sid_check_is_domain(sid);
+               break;
+       case 5:
+               ret = False;
+               break;
        }
 
-       DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying "
-                 "special SIDs.\n", sid_string_static(sid)));
+       DEBUG(10, ("%s SID %s in level %d\n",
+                  ret ? "Accepting" : "Rejecting",
+                  sid_string_static(sid), level));
+       return ret;
+}
 
-       if (lookup_wellknown_sid(tmp_ctx, sid, &domain, &name)) {
-               type = SID_NAME_WKN_GRP;
-               goto ok;
+/*
+ * Lookup a bunch of SIDs. This is modeled after lsa_lookup_sids with
+ * references to domains, it is explicitly made for this.
+ *
+ * This attempts to be as efficient as possible: It collects all SIDs
+ * belonging to a domain and hands them in bulk to the appropriate lookup
+ * function. In particular pdb_lookup_rids with ldapsam_trusted benefits
+ * *hugely* from this. Winbind is going to be extended with a lookup_rids
+ * interface as well, so on a DC we can do a bulk lsa_lookuprids to the
+ * appropriate DC.
+ */
+
+NTSTATUS lookup_sids(TALLOC_CTX *mem_ctx, int num_sids,
+                    const DOM_SID **sids, int level,
+                    struct lsa_dom_info **ret_domains,
+                    struct lsa_name_info **ret_names)
+{
+       TALLOC_CTX *tmp_ctx;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       struct lsa_name_info *name_infos;
+       struct lsa_dom_info *dom_infos;
+
+       int i, j;
+
+       tmp_ctx = talloc_new(mem_ctx);
+       if (tmp_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
+               return NT_STATUS_NO_MEMORY;
        }
 
- failed:
-       DEBUG(10, ("Failed to lookup sid %s\n", sid_string_static(sid)));
+       name_infos = TALLOC_ARRAY(tmp_ctx, struct lsa_name_info, num_sids);
+       dom_infos = TALLOC_ZERO_ARRAY(tmp_ctx, struct lsa_dom_info,
+                                     MAX_REF_DOMAINS);
+       if ((name_infos == NULL) || (dom_infos == NULL)) {
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+
+       /* First build up the data structures:
+        * 
+        * dom_infos is a list of domains referenced in the list of
+        * SIDs. Later we will walk the list of domains and look up the RIDs
+        * in bulk.
+        *
+        * name_infos is a shadow-copy of the SIDs array to collect the real
+        * data.
+        *
+        * dom_info->idxs is an index into the name_infos array. The
+        * difficulty we have here is that we need to keep the SIDs the client
+        * asked for in the same order for the reply
+        */
+
+       for (i=0; i<num_sids; i++) {
+               DOM_SID sid;
+               uint32 rid;
+               const char *domain_name = NULL;
+
+               sid_copy(&sid, sids[i]);
+               name_infos[i].type = SID_NAME_USE_NONE;
+
+               if (lookup_as_domain(&sid, name_infos, &domain_name)) {
+                       /* We can't push that through the normal lookup
+                        * process, as this would reference illegal
+                        * domains.
+                        *
+                        * For example S-1-5-32 would end up referencing
+                        * domain S-1-5- with RID 32 which is clearly wrong.
+                        */
+                       if (domain_name == NULL) {
+                               result = NT_STATUS_NO_MEMORY;
+                               goto done;
+                       }
+                               
+                       name_infos[i].rid = 0;
+                       name_infos[i].type = SID_NAME_DOMAIN;
+                       name_infos[i].name = NULL;
+
+                       if (sid_check_is_builtin(&sid)) {
+                               /* Yes, W2k3 returns "BUILTIN" both as domain
+                                * and name here */
+                               name_infos[i].name = talloc_strdup(
+                                       name_infos, builtin_domain_name());
+                               if (name_infos[i].name == NULL) {
+                                       result = NT_STATUS_NO_MEMORY;
+                                       goto done;
+                               }
+                       }
+               } else {
+                       /* This is a normal SID with rid component */
+                       if (!sid_split_rid(&sid, &rid)) {
+                               result = NT_STATUS_INVALID_PARAMETER;
+                               goto done;
+                       }
+               }
+
+               if (!check_dom_sid_to_level(&sid, level)) {
+                       name_infos[i].rid = 0;
+                       name_infos[i].type = SID_NAME_UNKNOWN;
+                       name_infos[i].name = NULL;
+                       continue;
+               }
+
+               for (j=0; j<MAX_REF_DOMAINS; j++) {
+                       if (!dom_infos[j].valid) {
+                               break;
+                       }
+                       if (sid_equal(&sid, &dom_infos[j].sid)) {
+                               break;
+                       }
+               }
+
+               if (j == MAX_REF_DOMAINS) {
+                       /* TODO: What's the right error message here? */
+                       result = NT_STATUS_NONE_MAPPED;
+                       goto done;
+               }
+
+               if (!dom_infos[j].valid) {
+                       /* We found a domain not yet referenced, create a new
+                        * ref. */
+                       dom_infos[j].valid = True;
+                       sid_copy(&dom_infos[j].sid, &sid);
+
+                       if (domain_name != NULL) {
+                               /* This name was being found above in the case
+                                * when we found a domain SID */
+                               dom_infos[j].name =
+                                       talloc_steal(dom_infos, domain_name);
+                       } else {
+                               /* lookup_rids will take care of this */
+                               dom_infos[j].name = NULL;
+                       }
+               }
+
+               name_infos[i].dom_idx = j;
+
+               if (name_infos[i].type == SID_NAME_USE_NONE) {
+                       name_infos[i].rid = rid;
+
+                       ADD_TO_ARRAY(dom_infos, int, i, &dom_infos[j].idxs,
+                                    &dom_infos[j].num_idxs);
+
+                       if (dom_infos[j].idxs == NULL) {
+                               result = NT_STATUS_NO_MEMORY;
+                               goto done;
+                       }
+               }
+       }
+
+       /* Iterate over the domains found */
+
+       for (i=0; i<MAX_REF_DOMAINS; i++) {
+               uint32_t *rids;
+               const char **names;
+               enum SID_NAME_USE *types;
+               struct lsa_dom_info *dom = &dom_infos[i];
+
+               if (!dom->valid) {
+                       /* No domains left, we're done */
+                       break;
+               }
+
+               rids = TALLOC_ARRAY(tmp_ctx, uint32, dom->num_idxs);
+
+               if (rids == NULL) {
+                       result = NT_STATUS_NO_MEMORY;
+                       goto done;
+               }
+
+               for (j=0; j<dom->num_idxs; j++) {
+                       rids[j] = name_infos[dom->idxs[j]].rid;
+               }
+
+               if (!lookup_rids(tmp_ctx, &dom->sid,
+                                dom->num_idxs, rids, &dom->name,
+                                &names, &types)) {
+                       result = NT_STATUS_NO_MEMORY;
+                       goto done;
+               }
+
+               talloc_steal(dom_infos, dom->name);
+
+               for (j=0; j<dom->num_idxs; j++) {
+                       int idx = dom->idxs[j];
+                       name_infos[idx].type = types[j];
+                       if (types[j] != SID_NAME_UNKNOWN) {
+                               name_infos[idx].name =
+                                       talloc_steal(name_infos, names[j]);
+                       } else {
+                               name_infos[idx].name = NULL;
+                       }
+               }
+       }
+
+       *ret_domains = talloc_steal(mem_ctx, dom_infos);
+       *ret_names = talloc_steal(mem_ctx, name_infos);
+       result = NT_STATUS_OK;
+
+ done:
        talloc_free(tmp_ctx);
-       return False;
+       return result;
+}
 
- ok:
+/*****************************************************************
+ *THE CANONICAL* convert SID to name function.
+*****************************************************************/  
 
-       if ((domain == NULL) || (name == NULL)) {
-               DEBUG(0, ("talloc failed\n"));
-               talloc_free(tmp_ctx);
+BOOL lookup_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
+               const char **ret_domain, const char **ret_name,
+               enum SID_NAME_USE *ret_type)
+{
+       struct lsa_dom_info *domain;
+       struct lsa_name_info *name;
+       TALLOC_CTX *tmp_ctx;
+       BOOL ret = False;
+
+       tmp_ctx = talloc_new(mem_ctx);
+
+       if (tmp_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
                return False;
        }
 
+       if (!NT_STATUS_IS_OK(lookup_sids(tmp_ctx, 1, &sid, 1,
+                                        &domain, &name))) {
+               goto done;
+       }
+
+       if (name->type == SID_NAME_UNKNOWN) {
+               goto done;
+       }
+
        if (ret_domain != NULL) {
-               *ret_domain = talloc_steal(mem_ctx, domain);
+               *ret_domain = talloc_steal(mem_ctx, domain->name);
        }
 
        if (ret_name != NULL) {
-               *ret_name = talloc_steal(mem_ctx, name);
+               *ret_name = talloc_steal(mem_ctx, name->name);
        }
 
        if (ret_type != NULL) {
-               *ret_type = type;
+               *ret_type = name->type;
        }
 
+       ret = True;
+
+ done:
+       if (ret) {
+               DEBUG(10, ("Sid %s -> %s\\%s(%d)\n",
+                          sid_string_static(sid), domain->name,
+                          name->name, name->type));
+       } else {
+               DEBUG(10, ("failed to lookup sid %s\n",
+                          sid_string_static(sid)));
+       }
        talloc_free(tmp_ctx);
-       return True;
+       return ret;
 }
 
 /*****************************************************************
@@ -448,7 +880,7 @@ static BOOL fetch_uid_from_cache( uid_t *puid, const DOM_SID *psid )
  Store uid to SID mapping in cache.
 *****************************************************************/  
 
-static void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
+void store_uid_sid_cache(const DOM_SID *psid, uid_t uid)
 {
        struct uid_sid_cache *pc;
 
@@ -520,7 +952,7 @@ static BOOL fetch_gid_from_cache(gid_t *pgid, const DOM_SID *psid)
  Store gid to SID mapping in cache.
 *****************************************************************/  
 
-static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
+void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
 {
        struct gid_sid_cache *pc;
 
@@ -552,200 +984,255 @@ static void store_gid_sid_cache(const DOM_SID *psid, gid_t gid)
  *THE CANONICAL* convert uid_t to SID function.
 *****************************************************************/  
 
-NTSTATUS uid_to_sid(DOM_SID *psid, uid_t uid)
+void uid_to_sid(DOM_SID *psid, uid_t uid)
 {
        uid_t low, high;
+       uint32 rid;
 
        ZERO_STRUCTP(psid);
 
        if (fetch_sid_from_uid_cache(psid, uid))
-               return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
+               return;
 
-       /* DC's never use winbindd to resolve users outside the 
-          defined idmap range */
+       if (lp_idmap_uid(&low, &high) && (uid >= low) && (uid <= high) &&
+           winbind_uid_to_sid(psid, uid)) {
 
-       if ( lp_server_role()==ROLE_DOMAIN_MEMBER 
-               || (lp_idmap_uid(&low, &high) && uid >= low && uid <= high) ) 
-       {
-               if (winbind_uid_to_sid(psid, uid)) {
-
-                       DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
-                                 (unsigned int)uid, sid_string_static(psid)));
+               DEBUG(10,("uid_to_sid: winbindd %u -> %s\n",
+                         (unsigned int)uid, sid_string_static(psid)));
+               goto done;
+       }
 
-                       if (psid)
-                               store_uid_sid_cache(psid, uid);
-                       return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
-               }
+       if (pdb_uid_to_rid(uid, &rid)) {
+               /* This is a mapped user */
+               sid_copy(psid, get_global_sam_sid());
+               sid_append_rid(psid, rid);
+               goto done;
        }
 
-       if (!local_uid_to_sid(psid, uid)) {
-               DEBUG(10,("uid_to_sid: local %u failed to map to sid\n", (unsigned int)uid ));
-               return NT_STATUS_UNSUCCESSFUL;
+       if (pdb_rid_algorithm() && (uid < max_algorithmic_uid())) {
+               sid_copy(psid, get_global_sam_sid());
+               sid_append_rid(psid, algorithmic_pdb_uid_to_user_rid(uid));
+               goto done;
+       } else {
+               sid_copy(psid, &global_sid_Unix_Users);
+               sid_append_rid(psid, uid);
+               goto done;
        }
-        
+
+ done:
        DEBUG(10,("uid_to_sid: local %u -> %s\n", (unsigned int)uid,
                  sid_string_static(psid)));
 
        store_uid_sid_cache(psid, uid);
-       return NT_STATUS_OK;
+       return;
 }
 
 /*****************************************************************
  *THE CANONICAL* convert gid_t to SID function.
 *****************************************************************/  
 
-NTSTATUS gid_to_sid(DOM_SID *psid, gid_t gid)
+void gid_to_sid(DOM_SID *psid, gid_t gid)
 {
        gid_t low, high;
 
        ZERO_STRUCTP(psid);
 
        if (fetch_sid_from_gid_cache(psid, gid))
-               return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
+               return;
 
-       /* DC's never use winbindd to resolve groups outside the
-          defined idmap range */
+       if (lp_idmap_gid(&low, &high) && (gid >= low) && (gid <= high) &&
+           winbind_gid_to_sid(psid, gid)) {
 
-       if ( lp_server_role()==ROLE_DOMAIN_MEMBER
-               || (lp_idmap_gid(&low, &high) && gid >= low && gid <= high) )
-        {
-               if (winbind_gid_to_sid(psid, gid)) {
+               DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
+                         (unsigned int)gid, sid_string_static(psid)));
+               goto done;
+       }
 
-                       DEBUG(10,("gid_to_sid: winbindd %u -> %s\n",
-                                 (unsigned int)gid, sid_string_static(psid)));
-                        
-                       if (psid)
-                               store_gid_sid_cache(psid, gid);
-                       return ( psid ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL );
-               }
+       if (pdb_gid_to_sid(gid, psid)) {
+               /* This is a mapped group */
+               goto done;
        }
 
-       if (!local_gid_to_sid(psid, gid)) {
-               DEBUG(10,("gid_to_sid: local %u failed to map to sid\n", (unsigned int)gid ));
-               return NT_STATUS_UNSUCCESSFUL;
+       if (pdb_rid_algorithm() && (gid < max_algorithmic_gid())) {
+               sid_copy(psid, get_global_sam_sid());
+               sid_append_rid(psid, pdb_gid_to_group_rid(gid));
+               goto done;
+       } else {
+               sid_copy(psid, &global_sid_Unix_Groups);
+               sid_append_rid(psid, gid);
+               goto done;
        }
-        
+
+ done:
        DEBUG(10,("gid_to_sid: local %u -> %s\n", (unsigned int)gid,
                  sid_string_static(psid)));
 
        store_gid_sid_cache(psid, gid);
-       return NT_STATUS_OK;
+       return;
 }
 
 /*****************************************************************
  *THE CANONICAL* convert SID to uid function.
 *****************************************************************/  
 
-NTSTATUS sid_to_uid(const DOM_SID *psid, uid_t *puid)
+BOOL sid_to_uid(const DOM_SID *psid, uid_t *puid)
 {
-       enum SID_NAME_USE name_type;
+       enum SID_NAME_USE type;
+       uint32 rid;
+       gid_t gid;
 
        if (fetch_uid_from_cache(puid, psid))
-               return NT_STATUS_OK;
+               return True;
 
-       /* if this is our SID then go straight to a local lookup */
-       
-       if ( sid_compare_domain(get_global_sam_sid(), psid) == 0 ) {
-               DEBUG(10,("sid_to_uid: my domain (%s) - trying local.\n",
-                       sid_string_static(psid) ));
-               
-               if ( local_sid_to_uid(puid, psid, &name_type) )
-                       goto success;
-                       
-               DEBUG(10,("sid_to_uid: local lookup failed\n"));
-               
-               return NT_STATUS_UNSUCCESSFUL;
+       if (fetch_gid_from_cache(&gid, psid)) {
+               return False;
        }
-       
-       /* If it is not our local domain, only hope is winbindd */
 
-       if ( !winbind_lookup_sid(NULL, psid, NULL, NULL, &name_type) ) {
-               DEBUG(10,("sid_to_uid: winbind lookup for non-local sid %s failed\n",
-                       sid_string_static(psid) ));
-                       
-               return NT_STATUS_UNSUCCESSFUL;
+       if (sid_peek_check_rid(&global_sid_Unix_Users, psid, &rid)) {
+               uid_t uid = rid;
+               *puid = uid;
+               goto done;
        }
 
-       /* If winbindd does know the SID, ensure this is a user */
+       if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
+               union unid_t id;
+
+               if (pdb_sid_to_id(psid, &id, &type)) {
+                       if (type != SID_NAME_USER) {
+                               DEBUG(5, ("sid %s is a %s, expected a user\n",
+                                         sid_string_static(psid),
+                                         sid_type_lookup(type)));
+                               return False;
+                       }
+                       *puid = id.uid;
+                       goto done;
+               }
+               if (pdb_rid_algorithm() &&
+                   algorithmic_pdb_rid_is_user(rid)) {
+                       *puid = algorithmic_pdb_user_rid_to_uid(rid);
+                       goto done;
+               }
 
-       if (name_type != SID_NAME_USER) {
-               DEBUG(10,("sid_to_uid: winbind lookup succeeded but SID is not a user (%u)\n",
-                       (unsigned int)name_type ));
-               return NT_STATUS_INVALID_PARAMETER;
+               /* This was ours, but it was neither mapped nor
+                * algorithmic. Fail */
+               return False;
        }
 
-       /* get the uid.  Has to work or else we are dead in the water */
+       if (winbind_lookup_sid(NULL, psid, NULL, NULL, &type)) {
+
+               if (type != SID_NAME_USER) {
+                       DEBUG(10, ("sid_to_uid: sid %s is a %s\n",
+                                  sid_string_static(psid),
+                                  sid_type_lookup(type)));
+                       return False;
+               }
 
-       if ( !winbind_sid_to_uid(puid, psid) ) {
-               DEBUG(10,("sid_to_uid: winbind failed to allocate a new uid for sid %s\n",
-                         sid_string_static(psid)));
-               return NT_STATUS_UNSUCCESSFUL;
+               if (!winbind_sid_to_uid(puid, psid)) {
+                       DEBUG(5, ("sid_to_uid: winbind failed to allocate a "
+                                 "new uid for sid %s\n",
+                                 sid_string_static(psid)));
+                       return False;
+               }
+               goto done;
        }
 
-success:
+       /* TODO: Here would be the place to allocate both a gid and a uid for
+        * the SID in question */
+
+       return False;
+
+ done:
        DEBUG(10,("sid_to_uid: %s -> %u\n", sid_string_static(psid),
                (unsigned int)*puid ));
 
        store_uid_sid_cache(psid, *puid);
-       
-       return NT_STATUS_OK;
+       return True;
 }
+
 /*****************************************************************
  *THE CANONICAL* convert SID to gid function.
  Group mapping is used for gids that maps to Wellknown SIDs
 *****************************************************************/  
 
-NTSTATUS sid_to_gid(const DOM_SID *psid, gid_t *pgid)
+BOOL sid_to_gid(const DOM_SID *psid, gid_t *pgid)
 {
-       enum SID_NAME_USE name_type;
+       uint32 rid;
+       GROUP_MAP map;
+       union unid_t id;
+       enum SID_NAME_USE type;
+       uid_t uid;
 
        if (fetch_gid_from_cache(pgid, psid))
-               return NT_STATUS_OK;
+               return True;
 
-       /*
-        * First we must look up the name and decide if this is a group sid.
-        * Group mapping can deal with foreign SIDs
-        */
+       if (fetch_uid_from_cache(&uid, psid))
+               return False;
+
+       if (sid_peek_check_rid(&global_sid_Unix_Groups, psid, &rid)) {
+               gid_t gid = rid;
+               *pgid = gid;
+               goto done;
+       }
+
+       if (sid_check_is_in_builtin(psid) && pdb_getgrsid(&map, *psid)) {
+               *pgid = map.gid;
+               goto done;
+       }
 
-       if ( local_sid_to_gid(pgid, psid, &name_type) )
-               goto success;
+       if (sid_peek_check_rid(get_global_sam_sid(), psid, &rid)) {
+               if (pdb_sid_to_id(psid, &id, &type)) {
+                       if ((type != SID_NAME_DOM_GRP) &&
+                           (type != SID_NAME_ALIAS)) {
+                               DEBUG(5, ("sid %s is a %s, expected a group\n",
+                                         sid_string_static(psid),
+                                         sid_type_lookup(type)));
+                               return False;
+                       }
+                       *pgid = id.gid;
+                       goto done;
+               }
+               if (pdb_rid_algorithm() &&
+                   !algorithmic_pdb_rid_is_user(rid)) {
+                       /* This must be a group, presented as alias */
+                       *pgid = pdb_group_rid_to_gid(rid);
+                       goto done;
+               }
+               /* This was ours, but it was neither mapped nor
+                * algorithmic. Fail. */
+               return False;
+       }
        
-       if (!winbind_lookup_sid(NULL, psid, NULL, NULL, &name_type)) {
-               DEBUG(10,("sid_to_gid: no one knows the SID %s (tried local, then "
-                         "winbind)\n", sid_string_static(psid)));
+       if (!winbind_lookup_sid(NULL, psid, NULL, NULL, &type)) {
+               DEBUG(11,("sid_to_gid: no one knows the SID %s (tried local, "
+                         "then winbind)\n", sid_string_static(psid)));
                
-               return NT_STATUS_UNSUCCESSFUL;
+               return False;
        }
 
        /* winbindd knows it; Ensure this is a group sid */
 
-       if ((name_type != SID_NAME_DOM_GRP) && (name_type != SID_NAME_ALIAS) 
-               && (name_type != SID_NAME_WKN_GRP)) 
-       {
-               DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is not a known group (%u)\n",
-                       (unsigned int)name_type ));
-
-               /* winbindd is running and knows about this SID.  Just the wrong type.
-                  Don't fallback to a local lookup here */
-                  
-               return NT_STATUS_INVALID_PARAMETER;
+       if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
+           (type != SID_NAME_WKN_GRP)) {
+               DEBUG(10,("sid_to_gid: winbind lookup succeeded but SID is "
+                         "a %s\n", sid_type_lookup(type)));
+               return False;
        }
        
        /* winbindd knows it and it is a type of group; sid_to_gid must succeed
           or we are dead in the water */
 
        if ( !winbind_sid_to_gid(pgid, psid) ) {
-               DEBUG(10,("sid_to_gid: winbind failed to allocate a new gid for sid %s\n",
-                         sid_string_static(psid)));
-               return NT_STATUS_UNSUCCESSFUL;
+               DEBUG(10,("sid_to_gid: winbind failed to allocate a new gid "
+                         "for sid %s\n", sid_string_static(psid)));
+               return False;
        }
 
-success:
+ done:
        DEBUG(10,("sid_to_gid: %s -> %u\n", sid_string_static(psid),
                  (unsigned int)*pgid ));
 
        store_gid_sid_cache(psid, *pgid);
        
-       return NT_STATUS_OK;
+       return True;
 }
 
index 074a516bcb6713e81e40323056b9512d5c671201..d7cae06749c5f74836b18bf80a0493c3f2618021 100644 (file)
@@ -35,13 +35,14 @@ static DOM_SID *global_sam_sid=NULL;
  Read a SID from a file. This is for compatibility with the old MACHINE.SID
  style of SID storage
 ****************************************************************************/
+
 static BOOL read_sid_from_file(const char *fname, DOM_SID *sid)
 {
        char **lines;
        int numlines;
        BOOL ret;
 
-       lines = file_lines_load(fname, &numlines);
+       lines = file_lines_load(fname, &numlines,0);
        
        if (!lines || numlines < 1) {
                if (lines) file_lines_free(lines);
index f9f6021d81b5358bc4a735a3921d6d53a57b1c7c..90a51d1cbdc227dd056cca2d7a13c8f5095aab88 100644 (file)
@@ -350,34 +350,129 @@ NTSTATUS pdb_init_sam_pw(SAM_ACCOUNT **new_sam_acct, const struct passwd *pwd)
  on the UNIX user.  Pass in a RID if you have one
  ************************************************************/
 
-NTSTATUS pdb_init_sam_new(SAM_ACCOUNT **new_sam_acct, const char *username,
-                          uint32 rid)
+NTSTATUS pdb_init_sam_new(SAM_ACCOUNT **new_sam_acct, const char *username)
 {
-       NTSTATUS        nt_status = NT_STATUS_NO_MEMORY;
+       NTSTATUS        result;
        struct passwd   *pwd;
-       BOOL            ret;
-       
-       pwd = Get_Pwnam(username);
+       uint32 user_rid;
+       DOM_SID user_sid, group_sid;
+       TALLOC_CTX *mem_ctx;
+       enum SID_NAME_USE type;
 
-       if (!pwd) 
-               return NT_STATUS_NO_SUCH_USER;
-       
-       if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(new_sam_acct, pwd))) {
-               *new_sam_acct = NULL;
-               return nt_status;
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
+               return NT_STATUS_NO_MEMORY;
        }
        
-       /* see if we need to generate a new rid using the 2.2 algorithm */
-       if ( rid == 0 && lp_enable_rid_algorithm() ) {
-               DEBUG(10,("pdb_init_sam_new: no RID specified.  Generating one via old algorithm\n"));
-               rid = algorithmic_pdb_uid_to_user_rid(pwd->pw_uid);
+       pwd = Get_Pwnam_alloc(mem_ctx, username);
+
+       if (pwd == NULL) {
+               DEBUG(10, ("Could not find user %s\n", username));
+               result = NT_STATUS_NO_SUCH_USER;
+               goto done;
        }
-       
-       /* set the new SID */
-       
-       ret = pdb_set_user_sid_from_rid( *new_sam_acct, rid, PDB_SET );
-        
-       return (ret ? NT_STATUS_OK : NT_STATUS_NO_SUCH_USER);
+
+       result = pdb_init_sam_pw(new_sam_acct, pwd);
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(10, ("pdb_init_sam_pw failed: %s\n", nt_errstr(result)));
+               goto done;
+       }
+               
+       if (pdb_rid_algorithm()) {
+               if (!pdb_set_user_sid_from_rid(
+                           *new_sam_acct,
+                           algorithmic_pdb_uid_to_user_rid(pwd->pw_uid),
+                           PDB_SET)) {
+                       result = NT_STATUS_INTERNAL_ERROR;
+                       goto done;
+               }
+               if (!pdb_set_group_sid_from_rid(
+                           *new_sam_acct, pdb_gid_to_group_rid(pwd->pw_gid),
+                           PDB_SET)) {
+                       result = NT_STATUS_INTERNAL_ERROR;
+                       goto done;
+               }
+               result = NT_STATUS_OK;
+               goto done;
+       }
+
+       /* No algorithmic mapping, meaning that we have to figure out the
+        * primary group SID according to group mapping and the user SID must
+        * be a newly allocated one */
+
+       if (!pdb_gid_to_sid(pwd->pw_gid, &group_sid)) {
+               struct group *grp;
+               GROUP_MAP map;
+
+               grp = getgrgid(pwd->pw_gid);
+               if (grp == NULL) {
+                       DEBUG(1, ("Primary group %d of user %s does not "
+                                 "exist.\n", pwd->pw_gid, username));
+                       result = NT_STATUS_INVALID_PRIMARY_GROUP;
+                       goto done;
+               }
+
+               DEBUG(5, ("Primary group %s of user %s is not mapped to "
+                         "a domain group, auto-mapping it\n",
+                         grp->gr_name, username));
+               result = map_unix_group(grp, &map);
+               if (!NT_STATUS_IS_OK(result)) {
+                       DEBUG(1, ("Failed to map group %s\n", grp->gr_name));
+                       goto done;
+               }
+               sid_copy(&group_sid, &map.sid);
+               DEBUG(5, ("Mapped unix group %s to SID %s\n",
+                         grp->gr_name, sid_string_static(&group_sid)));
+       }
+
+       /* Now check that it's actually a domain group and not something
+        * else */
+
+       if (!lookup_sid(mem_ctx, &group_sid, NULL, NULL, &type)) {
+               DEBUG(3, ("Could not lookup %s's primary group sid %s\n",
+                         username, sid_string_static(&group_sid)));
+               result = NT_STATUS_INVALID_PRIMARY_GROUP;
+               goto done;
+       }
+
+       if (type != SID_NAME_DOM_GRP) {
+               DEBUG(3, ("Primary group for user %s is a %s and not a domain "
+                         "group\n", username, sid_type_lookup(type)));
+               result = NT_STATUS_INVALID_PRIMARY_GROUP;
+               goto done;
+       }
+
+       if (!pdb_set_group_sid(*new_sam_acct, &group_sid, PDB_SET)) {
+               DEBUG(3, ("Could not set group SID\n"));
+               result = NT_STATUS_INTERNAL_ERROR;
+               goto done;
+       }
+
+       if (!pdb_new_rid(&user_rid)) {
+               DEBUG(3, ("Could not allocate a new RID\n"));
+               result = NT_STATUS_ACCESS_DENIED;
+               goto done;
+       }
+
+       sid_copy(&user_sid, get_global_sam_sid());
+       sid_append_rid(&user_sid, user_rid);
+
+       if (!pdb_set_user_sid(*new_sam_acct, &user_sid, PDB_SET)) {
+               DEBUG(3, ("pdb_set_user_sid failed\n"));
+               result = NT_STATUS_INTERNAL_ERROR;
+               goto done;
+       }
+
+       result = NT_STATUS_OK;
+
+ done:
+       if (!NT_STATUS_IS_OK(result) && (*new_sam_acct != NULL)) {
+               pdb_free_sam(new_sam_acct);
+       }
+
+       talloc_free(mem_ctx);
+       return result;
 }
 
 
@@ -666,6 +761,11 @@ uid_t algorithmic_pdb_user_rid_to_uid(uint32 user_rid)
        return (uid_t)(((user_rid & (~USER_RID_TYPE)) - rid_offset)/RID_MULTIPLIER);
 }
 
+uid_t max_algorithmic_uid(void)
+{
+       return algorithmic_pdb_user_rid_to_uid(0xfffffffe);
+}
+
 /*******************************************************************
  converts UNIX uid to an NT User RID.
  ********************************************************************/
@@ -686,6 +786,11 @@ gid_t pdb_group_rid_to_gid(uint32 group_rid)
        return (gid_t)(((group_rid & (~GROUP_RID_TYPE))- rid_offset)/RID_MULTIPLIER);
 }
 
+gid_t max_algorithmic_gid(void)
+{
+       return pdb_group_rid_to_gid(0xffffffff);
+}
+
 /*******************************************************************
  converts NT Group RID to a UNIX uid.
  
@@ -731,130 +836,12 @@ BOOL algorithmic_pdb_rid_is_user(uint32 rid)
        return False;
 }
 
-/*******************************************************************
- Look up a rid in the SAM we're responsible for (i.e. passdb)
- ********************************************************************/
-
-BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid, const char **name,
-                          enum SID_NAME_USE *psid_name_use)
-{
-       SAM_ACCOUNT *sam_account = NULL;
-       GROUP_MAP map;
-       BOOL ret;
-       DOM_SID sid;
-
-       *psid_name_use = SID_NAME_UNKNOWN;
-       
-       DEBUG(5,("lookup_global_sam_rid: looking up RID %u.\n",
-                (unsigned int)rid));
-
-       sid_copy(&sid, get_global_sam_sid());
-       sid_append_rid(&sid, rid);
-       
-       /* see if the passdb can help us with the name of the user */
-       if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) {
-               return False;
-       }
-
-       /* BEING ROOT BLLOCK */
-       become_root();
-       if (pdb_getsampwsid(sam_account, &sid)) {
-               unbecome_root();                /* -----> EXIT BECOME_ROOT() */
-               *name = talloc_strdup(mem_ctx, pdb_get_username(sam_account));
-               *psid_name_use = SID_NAME_USER;
-
-               pdb_free_sam(&sam_account);
-                       
-               return True;
-       }
-       pdb_free_sam(&sam_account);
-       
-       ret = pdb_getgrsid(&map, sid);
-       unbecome_root();
-       /* END BECOME_ROOT BLOCK */
-       
-       if ( ret ) {
-               if (map.gid!=(gid_t)-1) {
-                       DEBUG(5,("lookup_global_sam_rid: mapped group %s to "
-                                "gid %u\n", map.nt_name,
-                                (unsigned int)map.gid));
-               } else {
-                       DEBUG(5,("lookup_global_sam_rid: mapped group %s to "
-                                "no unix gid.  Returning name.\n",
-                                map.nt_name));
-               }
-
-               *name = talloc_strdup(mem_ctx, map.nt_name);
-               *psid_name_use = map.sid_name_use;
-               return True;
-       }
-
-       if (rid == DOMAIN_USER_RID_ADMIN) {
-               *psid_name_use = SID_NAME_USER;
-               *name = talloc_strdup(mem_ctx, "Administrator");
-               return True;
-       }
-
-       if (algorithmic_pdb_rid_is_user(rid)) {
-               uid_t uid;
-               struct passwd *pw = NULL;
-
-               DEBUG(5, ("assuming RID %u is a user\n", (unsigned)rid));
-
-                       uid = algorithmic_pdb_user_rid_to_uid(rid);
-               pw = sys_getpwuid( uid );
-               
-               DEBUG(5,("lookup_global_sam_rid: looking up uid %u %s\n",
-                        (unsigned int)uid, pw ? "succeeded" : "failed" ));
-                        
-               if ( !pw ) {
-                       *name  = talloc_asprintf(mem_ctx, "unix_user.%u",
-                                                (unsigned int)uid);
-               } else {
-                       *name = talloc_strdup(mem_ctx, pw->pw_name );
-               }
-                       
-               DEBUG(5,("lookup_global_sam_rid: found user %s for rid %u\n",
-                        *name, (unsigned int)rid ));
-                        
-               *psid_name_use = SID_NAME_USER;
-               
-               return ( pw != NULL );
-       } else {
-               gid_t gid;
-               struct group *gr; 
-                       
-               DEBUG(5, ("assuming RID %u is a group\n", (unsigned)rid));
-
-               gid = pdb_group_rid_to_gid(rid);
-               gr = getgrgid(gid);
-                       
-               DEBUG(5,("lookup_global_sam_rid: looking up gid %u %s\n",
-                        (unsigned int)gid, gr ? "succeeded" : "failed" ));
-                       
-               if( !gr ) {
-                       *name = talloc_asprintf(mem_ctx, "unix_group.%u",
-                                              (unsigned int)gid);
-               } else {
-                       *name = talloc_strdup(mem_ctx, gr->gr_name);
-               }
-                       
-               DEBUG(5,("lookup_global_sam_rid: found group %s for rid %u\n",
-                        *name, (unsigned int)rid ));
-               
-               /* assume algorithmic groups are domain global groups */
-               
-               *psid_name_use = SID_NAME_DOM_GRP;
-               
-               return ( gr != NULL );
-       }
-}
-
 /*******************************************************************
  Convert a name into a SID. Used in the lookup name rpc.
  ********************************************************************/
 
-BOOL lookup_global_sam_name(const char *c_user, uint32_t *rid, enum SID_NAME_USE *type)
+BOOL lookup_global_sam_name(const char *c_user, int flags, uint32_t *rid,
+                           enum SID_NAME_USE *type)
 {
        fstring user;
        SAM_ACCOUNT *sam_account = NULL;
@@ -877,7 +864,13 @@ BOOL lookup_global_sam_name(const char *c_user, uint32_t *rid, enum SID_NAME_USE
        /* BEGIN ROOT BLOCK */
        
        become_root();
-       if (pdb_getsampwnam(sam_account, user)) {
+
+       /* LOOKUP_NAME_GROUP is a hack to allow valid users = @foo to work
+        * correctly in the case where foo also exists as a user. If the flag
+        * is set, don't look for users at all. */
+
+       if (((flags & LOOKUP_NAME_GROUP) == 0) &&
+           pdb_getsampwnam(sam_account, user)) {
                const DOM_SID *user_sid;
 
                unbecome_root();
@@ -891,15 +884,7 @@ BOOL lookup_global_sam_name(const char *c_user, uint32_t *rid, enum SID_NAME_USE
                }
 
                sid_peek_rid(user_sid, rid);
-
-               if (pdb_get_acct_ctrl(sam_account) &
-                   (ACB_DOMTRUST|ACB_WSTRUST|ACB_SVRTRUST)) {
-                       /* We have to filter them out in lsa_lookupnames,
-                        * indicate that this is not a real user.  */
-                       *type = SID_NAME_COMPUTER;
-               } else {
-                       *type = SID_NAME_USER;
-               }
+               *type = SID_NAME_USER;
                pdb_free_sam(&sam_account);
                return True;
        }
@@ -929,6 +914,8 @@ BOOL lookup_global_sam_name(const char *c_user, uint32_t *rid, enum SID_NAME_USE
                return True;
        }
 
+       return False;
+
        /* it's not a mapped group */
        grp = getgrnam(user);
        if(!grp) {
@@ -965,13 +952,14 @@ BOOL lookup_global_sam_name(const char *c_user, uint32_t *rid, enum SID_NAME_USE
  Change a password entry in the local smbpasswd file.
  *************************************************************/
 
-BOOL local_password_change(const char *user_name, int local_flags,
+NTSTATUS local_password_change(const char *user_name, int local_flags,
                           const char *new_passwd, 
                           char *err_str, size_t err_str_len,
                           char *msg_str, size_t msg_str_len)
 {
        SAM_ACCOUNT     *sam_pass=NULL;
        uint16 other_acb;
+       NTSTATUS result;
 
        *err_str = '\0';
        *msg_str = '\0';
@@ -985,14 +973,30 @@ BOOL local_password_change(const char *user_name, int local_flags,
                pdb_free_sam(&sam_pass);
                
                if ((local_flags & LOCAL_ADD_USER) || (local_flags & LOCAL_DELETE_USER)) {
-                       /* Might not exist in /etc/passwd.  Use rid algorithm here */
-                       if (!NT_STATUS_IS_OK(pdb_init_sam_new(&sam_pass, user_name, 0))) {
-                               slprintf(err_str, err_str_len-1, "Failed to initialise SAM_ACCOUNT for user %s. Does this user exist in the UNIX password database ?\n", user_name);
-                               return False;
+                       int tmp_debug = DEBUGLEVEL;
+
+                       /* Might not exist in /etc/passwd. */
+
+                       if (tmp_debug < 1) {
+                               DEBUGLEVEL = 1;
+                       }
+
+                       result = pdb_init_sam_new(&sam_pass, user_name);
+                       DEBUGLEVEL = tmp_debug;
+                       if (NT_STATUS_EQUAL(result,
+                                           NT_STATUS_INVALID_PRIMARY_GROUP)) {
+                               return result;
+                       }
+
+                       if (!NT_STATUS_IS_OK(result)) {
+                               slprintf(err_str, err_str_len-1, "Failed to "
+                                        "initialize account for user %s: %s\n",
+                                        user_name, nt_errstr(result));
+                               return result;
                        }
                } else {
                        slprintf(err_str, err_str_len-1,"Failed to find entry for user %s.\n", user_name);
-                       return False;
+                       return NT_STATUS_NO_SUCH_USER;
                }
        } else {
                unbecome_root();
@@ -1006,19 +1010,19 @@ BOOL local_password_change(const char *user_name, int local_flags,
                if (!pdb_set_acct_ctrl(sam_pass, ACB_WSTRUST | other_acb, PDB_CHANGED) ) {
                        slprintf(err_str, err_str_len - 1, "Failed to set 'trusted workstation account' flags for user %s.\n", user_name);
                        pdb_free_sam(&sam_pass);
-                       return False;
+                       return NT_STATUS_UNSUCCESSFUL;
                }
        } else if (local_flags & LOCAL_INTERDOM_ACCOUNT) {
                if (!pdb_set_acct_ctrl(sam_pass, ACB_DOMTRUST | other_acb, PDB_CHANGED)) {
                        slprintf(err_str, err_str_len - 1, "Failed to set 'domain trust account' flags for user %s.\n", user_name);
                        pdb_free_sam(&sam_pass);
-                       return False;
+                       return NT_STATUS_UNSUCCESSFUL;
                }
        } else {
                if (!pdb_set_acct_ctrl(sam_pass, ACB_NORMAL | other_acb, PDB_CHANGED)) {
                        slprintf(err_str, err_str_len - 1, "Failed to set 'normal account' flags for user %s.\n", user_name);
                        pdb_free_sam(&sam_pass);
-                       return False;
+                       return NT_STATUS_UNSUCCESSFUL;
                }
        }
 
@@ -1031,13 +1035,13 @@ BOOL local_password_change(const char *user_name, int local_flags,
                if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_DISABLED, PDB_CHANGED)) {
                        slprintf(err_str, err_str_len-1, "Failed to set 'disabled' flag for user %s.\n", user_name);
                        pdb_free_sam(&sam_pass);
-                       return False;
+                       return NT_STATUS_UNSUCCESSFUL;
                }
        } else if (local_flags & LOCAL_ENABLE_USER) {
                if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
                        slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name);
                        pdb_free_sam(&sam_pass);
-                       return False;
+                       return NT_STATUS_UNSUCCESSFUL;
                }
        }
        
@@ -1045,7 +1049,7 @@ BOOL local_password_change(const char *user_name, int local_flags,
                if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)|ACB_PWNOTREQ, PDB_CHANGED)) {
                        slprintf(err_str, err_str_len-1, "Failed to set 'no password required' flag for user %s.\n", user_name);
                        pdb_free_sam(&sam_pass);
-                       return False;
+                       return NT_STATUS_UNSUCCESSFUL;
                }
        } else if (local_flags & LOCAL_SET_PASSWORD) {
                /*
@@ -1061,19 +1065,19 @@ BOOL local_password_change(const char *user_name, int local_flags,
                        if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_DISABLED), PDB_CHANGED)) {
                                slprintf(err_str, err_str_len-1, "Failed to unset 'disabled' flag for user %s.\n", user_name);
                                pdb_free_sam(&sam_pass);
-                               return False;
+                               return NT_STATUS_UNSUCCESSFUL;
                        }
                }
                if (!pdb_set_acct_ctrl (sam_pass, pdb_get_acct_ctrl(sam_pass)&(~ACB_PWNOTREQ), PDB_CHANGED)) {
                        slprintf(err_str, err_str_len-1, "Failed to unset 'no password required' flag for user %s.\n", user_name);
                        pdb_free_sam(&sam_pass);
-                       return False;
+                       return NT_STATUS_UNSUCCESSFUL;
                }
                
                if (!pdb_set_plaintext_passwd (sam_pass, new_passwd)) {
                        slprintf(err_str, err_str_len-1, "Failed to set password for user %s.\n", user_name);
                        pdb_free_sam(&sam_pass);
-                       return False;
+                       return NT_STATUS_UNSUCCESSFUL;
                }
        }       
 
@@ -1081,24 +1085,25 @@ BOOL local_password_change(const char *user_name, int local_flags,
                if (pdb_add_sam_account(sam_pass)) {
                        slprintf(msg_str, msg_str_len-1, "Added user %s.\n", user_name);
                        pdb_free_sam(&sam_pass);
-                       return True;
+                       return NT_STATUS_OK;
                } else {
                        slprintf(err_str, err_str_len-1, "Failed to add entry for user %s.\n", user_name);
                        pdb_free_sam(&sam_pass);
-                       return False;
+                       return NT_STATUS_UNSUCCESSFUL;
                }
        } else if (local_flags & LOCAL_DELETE_USER) {
                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;
+                       return NT_STATUS_UNSUCCESSFUL;
                }
                slprintf(msg_str, msg_str_len-1, "Deleted user %s.\n", user_name);
        } else {
-               if(!pdb_update_sam_account(sam_pass)) {
+               result = pdb_update_sam_account(sam_pass);
+               if(!NT_STATUS_IS_OK(result)) {
                        slprintf(err_str, err_str_len-1, "Failed to modify entry for user %s.\n", user_name);
                        pdb_free_sam(&sam_pass);
-                       return False;
+                       return result;
                }
                if(local_flags & LOCAL_DISABLE_USER)
                        slprintf(msg_str, msg_str_len-1, "Disabled user %s.\n", user_name);
@@ -1109,232 +1114,7 @@ BOOL local_password_change(const char *user_name, int local_flags,
        }
 
        pdb_free_sam(&sam_pass);
-       return True;
-}
-
-/****************************************************************************
- Convert a uid to SID - algorithmic.
-****************************************************************************/
-
-DOM_SID *algorithmic_uid_to_sid(DOM_SID *psid, uid_t uid)
-{
-       if ( !lp_enable_rid_algorithm() )
-               return NULL;
-
-       DEBUG(8,("algorithmic_uid_to_sid: falling back to RID algorithm\n"));
-       sid_copy( psid, get_global_sam_sid() );
-       sid_append_rid( psid, algorithmic_pdb_uid_to_user_rid(uid) );
-       DEBUG(10,("algorithmic_uid_to_sid:  uid (%d) -> SID %s.\n",
-               (unsigned int)uid, sid_string_static(psid) ));
-
-       return psid;
-}
-
-/****************************************************************************
- Convert a uid to SID - locally.
-****************************************************************************/
-
-DOM_SID *local_uid_to_sid(DOM_SID *psid, uid_t uid)
-{
-       SAM_ACCOUNT *sampw = NULL;
-       struct passwd *unix_pw;
-       BOOL ret;
-       
-       unix_pw = sys_getpwuid( uid );
-
-       if ( !unix_pw ) {
-               DEBUG(4,("local_uid_to_sid: host has no idea of uid %lu\n", (unsigned long)uid));
-               return algorithmic_uid_to_sid( psid, uid);
-       }
-       
-       if ( !NT_STATUS_IS_OK(pdb_init_sam(&sampw)) ) {
-               DEBUG(0,("local_uid_to_sid: failed to allocate SAM_ACCOUNT object\n"));
-               return NULL;
-       }
-       
-       become_root();
-       ret = pdb_getsampwnam( sampw, unix_pw->pw_name );
-       unbecome_root();
-       
-       if ( ret )
-               sid_copy( psid, pdb_get_user_sid(sampw) );
-       else {
-               DEBUG(4,("local_uid_to_sid: User %s [uid == %lu] has no samba account\n",
-                       unix_pw->pw_name, (unsigned long)uid));
-
-               algorithmic_uid_to_sid( psid, uid);
-       }
-
-       pdb_free_sam(&sampw);
-
-       DEBUG(10,("local_uid_to_sid:  uid (%d) -> SID %s (%s).\n", 
-               (unsigned int)uid, sid_string_static(psid), unix_pw->pw_name));
-       
-       return psid;
-}
-
-/****************************************************************************
- Convert a SID to uid - locally.
-****************************************************************************/
-
-BOOL local_sid_to_uid(uid_t *puid, const DOM_SID *psid, enum SID_NAME_USE *name_type)
-{
-       SAM_ACCOUNT *sampw = NULL;      
-       struct passwd *unix_pw;
-       const char *user_name;
-
-       *name_type = SID_NAME_UNKNOWN;
-
-       /*
-        * We can only convert to a uid if this is our local
-        * Domain SID (ie. we are the controling authority).
-        */
-       if (!sid_check_is_in_our_domain(psid) ) {
-               DEBUG(5,("local_sid_to_uid: this SID (%s) is not from our domain\n", sid_string_static(psid)));
-               return False;
-       }
-
-       /* lookup the user account */
-       
-       if ( !NT_STATUS_IS_OK(pdb_init_sam(&sampw)) ) {
-               DEBUG(0,("local_sid_to_uid: Failed to allocate memory for SAM_ACCOUNT object\n"));
-               return False;
-       }
-               
-       become_root();
-       if ( !pdb_getsampwsid(sampw, psid) ) {
-               unbecome_root();
-               pdb_free_sam(&sampw);
-               DEBUG(8,("local_sid_to_uid: Could not find SID %s in passdb\n",
-                       sid_string_static(psid)));
-               return False;
-       }
-       unbecome_root();
-       
-       user_name = pdb_get_username(sampw);
-
-       unix_pw = sys_getpwnam( user_name );
-
-       if ( !unix_pw ) {
-               DEBUG(0,("local_sid_to_uid: %s found in passdb but getpwnam() return NULL!\n",
-                       user_name));
-               pdb_free_sam( &sampw );
-               return False;
-       }
-               
-       *puid = unix_pw->pw_uid;
-       
-       DEBUG(10,("local_sid_to_uid: SID %s -> uid (%u) (%s).\n", sid_string_static(psid),
-               (unsigned int)*puid, user_name ));
-
-       *name_type = SID_NAME_USER;
-       pdb_free_sam( &sampw );
-       return True;
-}
-
-/****************************************************************************
- Convert a gid to SID - locally.
-****************************************************************************/
-
-DOM_SID *local_gid_to_sid(DOM_SID *psid, gid_t gid)
-{
-       GROUP_MAP group;
-       BOOL ret;
-       
-       /* we don't need to disable winbindd since the gid is stored in 
-          the GROUP_MAP object */
-          
-       /* done as root since ldap backend requires root to open a connection */
-
-       become_root();
-       ret = pdb_getgrgid( &group, gid );
-       unbecome_root();
-       
-       if ( !ret ) {
-
-               /* fallback to rid mapping if enabled */
-
-               if ( lp_enable_rid_algorithm() ) {
-                       sid_copy(psid, get_global_sam_sid());
-                       sid_append_rid(psid, pdb_gid_to_group_rid(gid));
-
-                       DEBUG(10,("local_gid_to_sid: Fall back to algorithmic mapping: %u -> %s\n", 
-                               (unsigned int)gid, sid_string_static(psid)));
-                               
-                       return psid;
-               }
-               else
-                       return NULL;
-       }
-       
-       sid_copy( psid, &group.sid );
-       
-       DEBUG(10,("local_gid_to_sid:  gid (%d) -> SID %s.\n", 
-               (unsigned int)gid, sid_string_static(psid)));   
-       
-       return psid;
-}
-
-/****************************************************************************
- Convert a SID to gid - locally.
-****************************************************************************/
-
-BOOL local_sid_to_gid(gid_t *pgid, const DOM_SID *psid, enum SID_NAME_USE *name_type)
-{
-       uint32 rid;
-       GROUP_MAP group;
-       BOOL ret;
-
-       *name_type = SID_NAME_UNKNOWN;
-
-       /* This call can enumerate group mappings for foreign sids as well.
-          So don't check for a match against our domain SID */
-
-       /* we don't need to disable winbindd since the gid is stored in 
-          the GROUP_MAP object */
-          
-       become_root();
-       ret = pdb_getgrsid(&group, *psid);
-       unbecome_root();
-       
-       if ( !ret ) {
-
-               /* Fallback to algorithmic rid mapping if enabled */
-
-               if ( lp_enable_rid_algorithm() ) {
-
-                       if (!sid_check_is_in_our_domain(psid) ) {
-                               DEBUG(5,("local_sid_to_gid: RID algorithm only supported for our domain (%s is not)\n", sid_string_static(psid)));
-                               return False;
-                       }
-
-                       if (!sid_peek_rid(psid, &rid)) {
-                               DEBUG(10,("local_sid_to_gid: invalid SID!\n"));
-                                       return False;
-                       }
-
-                       DEBUG(10,("local_sid_to_gid: Fall back to algorithmic mapping\n"));
-
-                       if (algorithmic_pdb_rid_is_user(rid)) {
-                               DEBUG(3, ("local_sid_to_gid: SID %s is *NOT* a group\n", sid_string_static(psid)));
-                               return False;
-                       } else {
-                               *pgid = pdb_group_rid_to_gid(rid);
-                               DEBUG(10,("local_sid_to_gid: mapping: %s -> %u\n", sid_string_static(psid), (unsigned int)(*pgid)));
-                               return True;
-                       }
-               }
-               
-               return False;
-       }
-
-       *pgid = group.gid;
-       *name_type = group.sid_name_use;
-
-       DEBUG(10,("local_sid_to_gid: SID %s -> gid (%u)\n", sid_string_static(psid),
-               (unsigned int)*pgid));
-
-       return True;
+       return NT_STATUS_OK;
 }
 
 /**********************************************************************
@@ -2251,51 +2031,6 @@ BOOL pdb_copy_sam_account(const SAM_ACCOUNT *src, SAM_ACCOUNT **dst)
        return result;
 }
 
-/**********************************************************************
-**********************************************************************/
-
-static BOOL get_free_ugid_range(uint32 *low, uint32 *high)
-{
-       uid_t u_low, u_high;
-       gid_t g_low, g_high;
-
-       if (!lp_idmap_uid(&u_low, &u_high) || !lp_idmap_gid(&g_low, &g_high)) {
-               return False;
-       }
-       
-       *low  = (u_low < g_low)   ? u_low  : g_low;
-       *high = (u_high < g_high) ? u_high : g_high;
-       
-       return True;
-}
-
-/******************************************************************
- Get the the non-algorithmic RID range if idmap range are defined
-******************************************************************/
-
-BOOL get_free_rid_range(uint32 *low, uint32 *high)
-{
-       uint32 id_low, id_high;
-
-       if (!lp_enable_rid_algorithm()) {
-               *low = BASE_RID;
-               *high = (uint32)-1;
-       }
-
-       if (!get_free_ugid_range(&id_low, &id_high)) {
-               return False;
-       }
-
-       *low = algorithmic_pdb_uid_to_user_rid(id_low);
-       if (algorithmic_pdb_user_rid_to_uid((uint32)-1) < id_high) {
-               *high = (uint32)-1;
-       } else {
-               *high = algorithmic_pdb_uid_to_user_rid(id_high);
-       }
-
-       return True;
-}
-
 /*********************************************************************
  Update the bad password count checking the AP_RESET_COUNT_TIME 
 *********************************************************************/
index 783e9e23fa306ecb696c33c2ff5e2e483a0d144e..71fb36e0d5e8a382db02a112781764622d7345ca 100644 (file)
@@ -958,7 +958,8 @@ BOOL pdb_set_nt_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[NT_HASH_LEN], enum
        data_blob_clear_free(&sampass->private_u.nt_pw);
        
        if (pwd) {
-               sampass->private_u.nt_pw = data_blob(pwd, NT_HASH_LEN);
+               sampass->private_u.nt_pw =
+                      data_blob_talloc(sampass->mem_ctx, pwd, NT_HASH_LEN);
        } else {
                sampass->private_u.nt_pw = data_blob(NULL, 0);
        }
@@ -978,7 +979,8 @@ BOOL pdb_set_lanman_passwd (SAM_ACCOUNT *sampass, const uint8 pwd[LM_HASH_LEN],
        data_blob_clear_free(&sampass->private_u.lm_pw);
        
        if (pwd) {
-               sampass->private_u.lm_pw = data_blob(pwd, LM_HASH_LEN);
+               sampass->private_u.lm_pw =
+                      data_blob_talloc(sampass->mem_ctx, pwd, LM_HASH_LEN);
        } else {
                sampass->private_u.lm_pw = data_blob(NULL, 0);
        }
@@ -1093,8 +1095,10 @@ BOOL pdb_set_backend_private_data (SAM_ACCOUNT *sampass, void *private_data,
        if (!sampass)
                return False;
 
-       if (sampass->private_u.backend_private_data && sampass->private_u.backend_private_data_free_fn) {
-               sampass->private_u.backend_private_data_free_fn(&sampass->private_u.backend_private_data);
+       if (sampass->private_u.backend_private_data &&
+           sampass->private_u.backend_private_data_free_fn) {
+               sampass->private_u.backend_private_data_free_fn(
+                       &sampass->private_u.backend_private_data);
        }
 
        sampass->private_u.backend_private_data = private_data;
index 4808af3908195a958355723f9e5c0f64fd67612c..d8afff21115f1f72a947308f7dce579f884a49fd 100644 (file)
@@ -36,7 +36,10 @@ static void lazy_initialize_passdb(void)
 }
 
 static struct pdb_init_function_entry *pdb_find_backend_entry(const char *name);
-
+static BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid,
+                                 const char **name,
+                                 enum SID_NAME_USE *psid_name_use,
+                                 union unid_t *unix_id);
 /*******************************************************************
  Clean up uninitialised passwords.  The only way to tell 
  that these values are not 'real' is that they do not
@@ -526,9 +529,10 @@ static NTSTATUS context_enum_group_members(struct pdb_context *context,
 }
 
 static NTSTATUS context_enum_group_memberships(struct pdb_context *context,
-                                              const char *username,
-                                              gid_t primary_gid,
-                                              DOM_SID **pp_sids, gid_t **pp_gids,
+                                              TALLOC_CTX *mem_ctx,
+                                              SAM_ACCOUNT *user,
+                                              DOM_SID **pp_sids,
+                                              gid_t **pp_gids,
                                               size_t *p_num_groups)
 {
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
@@ -539,8 +543,8 @@ static NTSTATUS context_enum_group_memberships(struct pdb_context *context,
        }
 
        return context->pdb_methods->
-               enum_group_memberships(context->pdb_methods, username,
-                                      primary_gid, pp_sids, pp_gids, p_num_groups);
+               enum_group_memberships(context->pdb_methods, mem_ctx, user,
+                                      pp_sids, pp_gids, p_num_groups);
 }
 
 static NTSTATUS context_find_alias(struct pdb_context *context,
@@ -757,6 +761,63 @@ static NTSTATUS context_get_seq_num(struct pdb_context *context, time_t *seq_num
 
        return context->pdb_methods->get_seq_num(context->pdb_methods, seq_num);
 }
+
+static BOOL context_uid_to_rid(struct pdb_context *context, uid_t uid,
+                              uint32 *rid)
+{
+       if ((context == NULL) || (context->pdb_methods == NULL)) {
+               DEBUG(0, ("invalid pdb_context specified!\n"));
+               return False;
+       }
+
+       return context->pdb_methods->uid_to_rid(context->pdb_methods, uid,
+                                               rid);
+}
+       
+static BOOL context_gid_to_sid(struct pdb_context *context, gid_t gid,
+                              DOM_SID *sid)
+{
+       if ((context == NULL) || (context->pdb_methods == NULL)) {
+               DEBUG(0, ("invalid pdb_context specified!\n"));
+               return False;
+       }
+
+       return context->pdb_methods->gid_to_sid(context->pdb_methods, gid,
+                                               sid);
+}
+
+static BOOL context_sid_to_id(struct pdb_context *context,
+                             const DOM_SID *sid,
+                             union unid_t *id, enum SID_NAME_USE *type)
+{
+       if ((context == NULL) || (context->pdb_methods == NULL)) {
+               DEBUG(0, ("invalid pdb_context specified!\n"));
+               return False;
+       }
+
+       return context->pdb_methods->sid_to_id(context->pdb_methods, sid,
+                                              id, type);
+}
+       
+static BOOL context_rid_algorithm(struct pdb_context *context)
+{
+       if ((context == NULL) || (context->pdb_methods == NULL)) {
+               DEBUG(0, ("invalid pdb_context specified!\n"));
+               return False;
+       }
+
+       return context->pdb_methods->rid_algorithm(context->pdb_methods);
+}
+       
+static BOOL context_new_rid(struct pdb_context *context, uint32 *rid)
+{
+       if ((context == NULL) || (context->pdb_methods == NULL)) {
+               DEBUG(0, ("invalid pdb_context specified!\n"));
+               return False;
+       }
+
+       return context->pdb_methods->new_rid(context->pdb_methods, rid);
+}
        
 /******************************************************************
   Free and cleanup a pdb context, any associated data and anything
@@ -936,6 +997,13 @@ static NTSTATUS make_pdb_context(struct pdb_context **context)
        (*context)->pdb_search_groups = context_search_groups;
        (*context)->pdb_search_aliases = context_search_aliases;
 
+       (*context)->pdb_uid_to_rid = context_uid_to_rid;
+       (*context)->pdb_gid_to_sid = context_gid_to_sid;
+       (*context)->pdb_sid_to_id = context_sid_to_id;
+
+       (*context)->pdb_rid_algorithm = context_rid_algorithm;
+       (*context)->pdb_new_rid = context_new_rid;
+
        (*context)->free_fn = free_pdb_context;
 
        return NT_STATUS_OK;
@@ -1126,12 +1194,12 @@ BOOL pdb_add_sam_account(SAM_ACCOUNT *sam_acct)
        return NT_STATUS_IS_OK(pdb_context->pdb_add_sam_account(pdb_context, sam_acct));
 }
 
-BOOL pdb_update_sam_account(SAM_ACCOUNT *sam_acct) 
+NTSTATUS pdb_update_sam_account(SAM_ACCOUNT *sam_acct) 
 {
        struct pdb_context *pdb_context = pdb_get_static_context(False);
 
        if (!pdb_context) {
-               return False;
+               return NT_STATUS_UNSUCCESSFUL;
        }
 
        if (sam_account_cache != NULL) {
@@ -1139,7 +1207,7 @@ BOOL pdb_update_sam_account(SAM_ACCOUNT *sam_acct)
                sam_account_cache = NULL;
        }
 
-       return NT_STATUS_IS_OK(pdb_context->pdb_update_sam_account(pdb_context, sam_acct));
+       return pdb_context->pdb_update_sam_account(pdb_context, sam_acct);
 }
 
 BOOL pdb_delete_sam_account(SAM_ACCOUNT *sam_acct) 
@@ -1221,28 +1289,26 @@ BOOL pdb_getgrnam(GROUP_MAP *map, const char *name)
                               pdb_getgrnam(pdb_context, map, name));
 }
 
-BOOL pdb_add_group_mapping_entry(GROUP_MAP *map)
+NTSTATUS pdb_add_group_mapping_entry(GROUP_MAP *map)
 {
        struct pdb_context *pdb_context = pdb_get_static_context(False);
 
        if (!pdb_context) {
-               return False;
+               return NT_STATUS_UNSUCCESSFUL;
        }
 
-       return NT_STATUS_IS_OK(pdb_context->
-                              pdb_add_group_mapping_entry(pdb_context, map));
+       return pdb_context->pdb_add_group_mapping_entry(pdb_context, map);
 }
 
-BOOL pdb_update_group_mapping_entry(GROUP_MAP *map)
+NTSTATUS pdb_update_group_mapping_entry(GROUP_MAP *map)
 {
        struct pdb_context *pdb_context = pdb_get_static_context(False);
 
        if (!pdb_context) {
-               return False;
+               return NT_STATUS_UNSUCCESSFUL;
        }
 
-       return NT_STATUS_IS_OK(pdb_context->
-                              pdb_update_group_mapping_entry(pdb_context, map));
+       return pdb_context->pdb_update_group_mapping_entry(pdb_context, map);
 }
 
 BOOL pdb_delete_group_mapping_entry(DOM_SID sid)
@@ -1286,7 +1352,7 @@ NTSTATUS pdb_enum_group_members(TALLOC_CTX *mem_ctx,
                                                   pp_member_rids, p_num_members);
 }
 
-NTSTATUS pdb_enum_group_memberships(const char *username, gid_t primary_gid,
+NTSTATUS pdb_enum_group_memberships(TALLOC_CTX *mem_ctx, SAM_ACCOUNT *user,
                                    DOM_SID **pp_sids, gid_t **pp_gids,
                                    size_t *p_num_groups)
 {
@@ -1296,9 +1362,9 @@ NTSTATUS pdb_enum_group_memberships(const char *username, gid_t primary_gid,
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       return pdb_context->pdb_enum_group_memberships(pdb_context, username,
-                                                      primary_gid, pp_sids, pp_gids,
-                                                      p_num_groups);
+       return pdb_context->pdb_enum_group_memberships(
+               pdb_context, mem_ctx, user,
+               pp_sids, pp_gids, p_num_groups);
 }
 
 BOOL pdb_find_alias(const char *name, DOM_SID *sid)
@@ -1361,60 +1427,58 @@ BOOL pdb_set_aliasinfo(const DOM_SID *sid, struct acct_info *info)
                                                              info));
 }
 
-BOOL pdb_add_aliasmem(const DOM_SID *alias, const DOM_SID *member)
+NTSTATUS pdb_add_aliasmem(const DOM_SID *alias, const DOM_SID *member)
 {
        struct pdb_context *pdb_context = pdb_get_static_context(False);
 
        if (!pdb_context) {
-               return False;
+               return NT_STATUS_UNSUCCESSFUL;
        }
 
-       return NT_STATUS_IS_OK(pdb_context->
-                              pdb_add_aliasmem(pdb_context, alias, member));
+       return pdb_context->pdb_add_aliasmem(pdb_context, alias, member);
 }
 
-BOOL pdb_del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
+NTSTATUS pdb_del_aliasmem(const DOM_SID *alias, const DOM_SID *member)
 {
        struct pdb_context *pdb_context = pdb_get_static_context(False);
 
        if (!pdb_context) {
-               return False;
+               return NT_STATUS_UNSUCCESSFUL;
        }
 
-       return NT_STATUS_IS_OK(pdb_context->
-                              pdb_del_aliasmem(pdb_context, alias, member));
+       return pdb_context->pdb_del_aliasmem(pdb_context, alias, member);
 }
 
-BOOL pdb_enum_aliasmem(const DOM_SID *alias,
-                      DOM_SID **pp_members, size_t *p_num_members)
+NTSTATUS pdb_enum_aliasmem(const DOM_SID *alias,
+                          DOM_SID **pp_members, size_t *p_num_members)
 {
        struct pdb_context *pdb_context = pdb_get_static_context(False);
 
        if (!pdb_context) {
-               return False;
+               return NT_STATUS_UNSUCCESSFUL;
        }
 
-       return NT_STATUS_IS_OK(pdb_context->
-                              pdb_enum_aliasmem(pdb_context, alias,
-                                                pp_members, p_num_members));
+       return pdb_context->pdb_enum_aliasmem(pdb_context, alias,
+                                             pp_members, p_num_members);
 }
 
-BOOL pdb_enum_alias_memberships(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid,
-                               const DOM_SID *members, size_t num_members,
-                               uint32 **pp_alias_rids, size_t *p_num_alias_rids)
+NTSTATUS pdb_enum_alias_memberships(TALLOC_CTX *mem_ctx,
+                                   const DOM_SID *domain_sid,
+                                   const DOM_SID *members, size_t num_members,
+                                   uint32 **pp_alias_rids,
+                                   size_t *p_num_alias_rids)
 {
        struct pdb_context *pdb_context = pdb_get_static_context(False);
 
        if (!pdb_context) {
-               return False;
+               return NT_STATUS_NOT_IMPLEMENTED;
        }
 
-       return NT_STATUS_IS_OK(pdb_context->
-                              pdb_enum_alias_memberships(pdb_context, mem_ctx,
-                                                         domain_sid,
-                                                         members, num_members,
-                                                         pp_alias_rids,
-                                                         p_num_alias_rids));
+       return pdb_context->pdb_enum_alias_memberships(pdb_context, mem_ctx,
+                                                      domain_sid,
+                                                      members, num_members,
+                                                      pp_alias_rids,
+                                                      p_num_alias_rids);
 }
 
 NTSTATUS pdb_lookup_rids(const DOM_SID *domain_sid,
@@ -1484,6 +1548,78 @@ BOOL pdb_get_seq_num(time_t *seq_num)
        return NT_STATUS_IS_OK(pdb_context->
                               pdb_get_seq_num(pdb_context, seq_num));
 }
+
+BOOL pdb_uid_to_rid(uid_t uid, uint32 *rid)
+{
+       struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+       if (!pdb_context) {
+               return False;
+       }
+
+       return pdb_context->pdb_uid_to_rid(pdb_context, uid, rid);
+}
+
+BOOL pdb_gid_to_sid(gid_t gid, DOM_SID *sid)
+{
+       struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+       if (!pdb_context) {
+               return False;
+       }
+
+       return pdb_context->pdb_gid_to_sid(pdb_context, gid, sid);
+}
+
+BOOL pdb_sid_to_id(const DOM_SID *sid, union unid_t *id,
+                  enum SID_NAME_USE *type)
+{
+       struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+       if (!pdb_context) {
+               return False;
+       }
+
+       return pdb_context->pdb_sid_to_id(pdb_context, sid, id, type);
+}
+
+BOOL pdb_rid_algorithm(void)
+{
+       struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+       if (!pdb_context) {
+               return False;
+       }
+
+       return pdb_context->pdb_rid_algorithm(pdb_context);
+}
+
+BOOL pdb_new_rid(uint32 *rid)
+{
+       struct pdb_context *pdb_context = pdb_get_static_context(False);
+
+       if (!pdb_context) {
+               return False;
+       }
+
+       if (pdb_rid_algorithm()) {
+               DEBUG(0, ("Trying to allocate a RID when algorithmic RIDs "
+                         "are active\n"));
+               return False;
+       }
+
+       if (algorithmic_rid_base() != BASE_RID) {
+               DEBUG(0, ("'algorithmic rid base' is set but a passdb backend "
+                         "without algorithmic RIDs is chosen.\n"));
+               DEBUGADD(0, ("Please map all used groups using 'net groupmap "
+                            "add', set the maximum used RID using\n"));
+               DEBUGADD(0, ("'net setmaxrid' and remove the parameter\n"));
+               return False;
+       }
+
+       return pdb_context->pdb_new_rid(pdb_context, rid);
+}
+
 /***************************************************************
   Initialize the static context (at smbd startup etc). 
 
@@ -1567,6 +1703,117 @@ static NTSTATUS pdb_default_get_seq_num(struct pdb_methods *methods, time_t *seq
        return NT_STATUS_OK;
 }
 
+static BOOL pdb_default_uid_to_rid(struct pdb_methods *methods, uid_t uid,
+                                  uint32 *rid)
+{
+       SAM_ACCOUNT *sampw = NULL;
+       struct passwd *unix_pw;
+       BOOL ret;
+       
+       unix_pw = sys_getpwuid( uid );
+
+       if ( !unix_pw ) {
+               DEBUG(4,("pdb_default_uid_to_rid: host has no idea of uid "
+                        "%lu\n", (unsigned long)uid));
+               return False;
+       }
+       
+       if ( !NT_STATUS_IS_OK(pdb_init_sam(&sampw)) ) {
+               DEBUG(0,("pdb_default_uid_to_rid: failed to allocate "
+                        "SAM_ACCOUNT object\n"));
+               return False;
+       }
+       
+       become_root();
+       ret = NT_STATUS_IS_OK(
+               methods->getsampwnam(methods, sampw, unix_pw->pw_name ));
+       unbecome_root();
+
+       if (!ret) {
+               DEBUG(5, ("pdb_default_uid_to_rid: Did not find user "
+                         "%s (%d)\n", unix_pw->pw_name, uid));
+               pdb_free_sam(&sampw);
+               return False;
+       }
+
+       ret = sid_peek_check_rid(get_global_sam_sid(),
+                                pdb_get_user_sid(sampw), rid);
+
+       if (!ret) {
+               DEBUG(1, ("Could not peek rid out of sid %s\n",
+                         sid_string_static(pdb_get_user_sid(sampw))));
+       }
+
+       pdb_free_sam(&sampw);
+       return ret;
+}
+
+static BOOL pdb_default_gid_to_sid(struct pdb_methods *methods, gid_t gid,
+                                  DOM_SID *sid)
+{
+       GROUP_MAP map;
+
+       if (!NT_STATUS_IS_OK(methods->getgrgid(methods, &map, gid))) {
+               return False;
+       }
+
+       sid_copy(sid, &map.sid);
+       return True;
+}
+
+static BOOL pdb_default_sid_to_id(struct pdb_methods *methods,
+                                 const DOM_SID *sid,
+                                 union unid_t *id, enum SID_NAME_USE *type)
+{
+       TALLOC_CTX *mem_ctx;
+       BOOL ret = False;
+       const char *name;
+       uint32 rid;
+
+       mem_ctx = talloc_new(NULL);
+
+       if (mem_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
+               return False;
+       }
+
+       if (sid_peek_check_rid(get_global_sam_sid(), sid, &rid)) {
+               /* Here we might have users as well as groups and aliases */
+               ret = lookup_global_sam_rid(mem_ctx, rid, &name, type, id);
+               goto done;
+       }
+
+       if (sid_peek_check_rid(&global_sid_Builtin, sid, &rid)) {
+               /* Here we only have aliases */
+               GROUP_MAP map;
+               if (!NT_STATUS_IS_OK(methods->getgrsid(methods, &map, *sid))) {
+                       DEBUG(10, ("Could not find map for sid %s\n",
+                                  sid_string_static(sid)));
+                       goto done;
+               }
+               if ((map.sid_name_use != SID_NAME_ALIAS) &&
+                   (map.sid_name_use != SID_NAME_WKN_GRP)) {
+                       DEBUG(10, ("Map for sid %s is a %s, expected an "
+                                  "alias\n", sid_string_static(sid),
+                                  sid_type_lookup(map.sid_name_use)));
+                       goto done;
+               }
+
+               id->gid = map.gid;
+               *type = SID_NAME_ALIAS;
+               ret = True;
+               goto done;
+       }
+
+       DEBUG(5, ("Sid %s is neither ours nor builtin, don't know it\n",
+                 sid_string_static(sid)));
+
+ done:
+
+       talloc_free(mem_ctx);
+       return ret;
+}
+
 static void add_uid_to_array_unique(TALLOC_CTX *mem_ctx,
                                    uid_t uid, uid_t **pp_uids, size_t *p_num)
 {
@@ -1644,7 +1891,7 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods,
        *pp_member_rids = NULL;
        *p_num_members = 0;
 
-       if (!NT_STATUS_IS_OK(sid_to_gid(group, &gid)))
+       if (!sid_to_gid(group, &gid))
                return NT_STATUS_NO_SUCH_GROUP;
 
        if(!get_memberuids(mem_ctx, gid, &uids, &num_uids))
@@ -1658,10 +1905,7 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods,
        for (i=0; i<num_uids; i++) {
                DOM_SID sid;
 
-               if (!NT_STATUS_IS_OK(uid_to_sid(&sid, uids[i]))) {
-                       DEBUG(1, ("Could not map member uid to SID\n"));
-                       continue;
-               }
+               uid_to_sid(&sid, uids[i]);
 
                if (!sid_check_is_in_our_domain(&sid)) {
                        DEBUG(1, ("Inconsistent SAM -- group member uid not "
@@ -1676,6 +1920,92 @@ NTSTATUS pdb_default_enum_group_members(struct pdb_methods *methods,
        return NT_STATUS_OK;
 }
 
+/*******************************************************************
+ Look up a rid in the SAM we're responsible for (i.e. passdb)
+ ********************************************************************/
+
+static BOOL lookup_global_sam_rid(TALLOC_CTX *mem_ctx, uint32 rid,
+                                 const char **name,
+                                 enum SID_NAME_USE *psid_name_use,
+                                 union unid_t *unix_id)
+{
+       SAM_ACCOUNT *sam_account = NULL;
+       GROUP_MAP map;
+       BOOL ret;
+       DOM_SID sid;
+
+       *psid_name_use = SID_NAME_UNKNOWN;
+       
+       DEBUG(5,("lookup_global_sam_rid: looking up RID %u.\n",
+                (unsigned int)rid));
+
+       sid_copy(&sid, get_global_sam_sid());
+       sid_append_rid(&sid, rid);
+       
+       /* see if the passdb can help us with the name of the user */
+       if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_account))) {
+               return False;
+       }
+
+       /* BEING ROOT BLLOCK */
+       become_root();
+       if (pdb_getsampwsid(sam_account, &sid)) {
+               struct passwd *pw;
+
+               unbecome_root();                /* -----> EXIT BECOME_ROOT() */
+               *name = talloc_strdup(mem_ctx, pdb_get_username(sam_account));
+               *psid_name_use = SID_NAME_USER;
+
+               pdb_free_sam(&sam_account);
+
+               if (unix_id == NULL) {
+                       return True;
+               }
+
+               pw = Get_Pwnam(*name);
+               if (pw == NULL) {
+                       return False;
+               }
+               unix_id->uid = pw->pw_uid;
+               return True;
+       }
+       pdb_free_sam(&sam_account);
+       
+       ret = pdb_getgrsid(&map, sid);
+       unbecome_root();
+       /* END BECOME_ROOT BLOCK */
+       
+       if ( ret ) {
+               if (map.gid!=(gid_t)-1) {
+                       DEBUG(5,("lookup_global_sam_rid: mapped group %s to "
+                                "gid %u\n", map.nt_name,
+                                (unsigned int)map.gid));
+               } else {
+                       DEBUG(5,("lookup_global_sam_rid: mapped group %s to "
+                                "no unix gid.  Returning name.\n",
+                                map.nt_name));
+               }
+
+               *name = talloc_strdup(mem_ctx, map.nt_name);
+               *psid_name_use = map.sid_name_use;
+
+               if (unix_id == NULL) {
+                       return True;
+               }
+
+               if (map.gid == (gid_t)-1) {
+                       DEBUG(5, ("Can't find a unix id for an unmapped "
+                                 "group\n"));
+                       return False;
+               }
+
+               unix_id->gid = map.gid;
+               return True;
+       }
+
+       return False;
+}
+
 NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods,
                                 const DOM_SID *domain_sid,
                                 int num_rids,
@@ -1715,7 +2045,8 @@ NTSTATUS pdb_default_lookup_rids(struct pdb_methods *methods,
        for (i = 0; i < num_rids; i++) {
                const char *name;
 
-               if (lookup_global_sam_rid(names, rids[i], &name, &attrs[i])) {
+               if (lookup_global_sam_rid(names, rids[i], &name, &attrs[i],
+                                         NULL)) {
                        names[i] = name;
                        DEBUG(5,("lookup_rids: %s:%d\n", names[i], attrs[i]));
                        have_mapped = True;
@@ -1772,11 +2103,9 @@ NTSTATUS pdb_default_lookup_names(struct pdb_methods *methods,
        }
 
        for (i = 0; i < num_names; i++) {
-               const char *name;
-
-               if (lookup_global_sam_rid(names, rids[i], &name, &attrs[i])) {
-                       names[i] = name;
-                       DEBUG(5,("lookup_rids: %s:%d\n", names[i], attrs[i]));
+               if (lookup_global_sam_name(names[i], 0, &rids[i], &attrs[i])) {
+                       DEBUG(5,("lookup_names: %s-> %d:%d\n", names[i],
+                                rids[i], attrs[i]));
                        have_mapped = True;
                } else {
                        have_unmapped = True;
@@ -2157,6 +2486,9 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods)
        (*methods)->get_account_policy = pdb_default_get_account_policy;
        (*methods)->set_account_policy = pdb_default_set_account_policy;
        (*methods)->get_seq_num = pdb_default_get_seq_num;
+       (*methods)->uid_to_rid = pdb_default_uid_to_rid;
+       (*methods)->gid_to_sid = pdb_default_gid_to_sid;
+       (*methods)->sid_to_id = pdb_default_sid_to_id;
 
        (*methods)->search_users = pdb_default_search_users;
        (*methods)->search_groups = pdb_default_search_groups;
index b35ce18eee5760bfc86b266024052771c8403aad..a21e9768031c5bc6c778353ea261c5843bc1f12a 100644 (file)
 #include "smbldap.h"
 
 /**********************************************************************
- Free a LDAPMessage (one is stored on the SAM_ACCOUNT).
+ Simple helper function to make stuff better readable
  **********************************************************************/
-void private_data_free_fn(void **result) 
+
+static LDAP *priv2ld(struct ldapsam_privates *priv)
 {
-       ldap_msgfree(*result);
-       *result = NULL;
+       return priv->smbldap_state->ldap_struct;
 }
 
 /**********************************************************************
@@ -117,14 +116,14 @@ static const char* get_userattr_key2string( int schema_ver, int key )
  Return the list of attribute names given a user schema version.
 **********************************************************************/
 
-const char** get_userattr_list( int schema_ver )
+const char** get_userattr_list( TALLOC_CTX *mem_ctx, int schema_ver )
 {
        switch ( schema_ver ) {
                case SCHEMAVER_SAMBAACCOUNT:
-                       return get_attr_list( attrib_map_v22 );
+                       return get_attr_list( mem_ctx, attrib_map_v22 );
                        
                case SCHEMAVER_SAMBASAMACCOUNT:
-                       return get_attr_list( attrib_map_v30 );
+                       return get_attr_list( mem_ctx, attrib_map_v30 );
                default:
                        DEBUG(0,("get_userattr_list: unknown schema version specified!\n"));
                        break;
@@ -137,14 +136,17 @@ const char** get_userattr_list( int schema_ver )
  Return the list of attribute names to delete given a user schema version.
 **************************************************************************/
 
-static const char** get_userattr_delete_list( int schema_ver )
+static const char** get_userattr_delete_list( TALLOC_CTX *mem_ctx,
+                                             int schema_ver )
 {
        switch ( schema_ver ) {
                case SCHEMAVER_SAMBAACCOUNT:
-                       return get_attr_list( attrib_map_to_delete_v22 );
+                       return get_attr_list( mem_ctx,
+                                             attrib_map_to_delete_v22 );
                        
                case SCHEMAVER_SAMBASAMACCOUNT:
-                       return get_attr_list( attrib_map_to_delete_v30 );
+                       return get_attr_list( mem_ctx,
+                                             attrib_map_to_delete_v30 );
                default:
                        DEBUG(0,("get_userattr_delete_list: unknown schema version specified!\n"));
                        break;
@@ -250,13 +252,6 @@ static NTSTATUS ldapsam_get_seq_num(struct pdb_methods *my_methods, time_t *seq_
                            LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, &msg);
 
        if (rc != LDAP_SUCCESS) {
-
-               char *ld_error = NULL;
-               ldap_get_option(ldap_state->smbldap_state->ldap_struct,
-                               LDAP_OPT_ERROR_STRING, &ld_error);
-               DEBUG(0,("ldapsam_get_seq_num: Failed search for suffix: %s, error: %s (%s)\n", 
-                       suffix,ldap_err2string(rc), ld_error?ld_error:"unknown"));
-               SAFE_FREE(ld_error);
                goto done;
        }
 
@@ -399,58 +394,37 @@ static int ldapsam_search_suffix_by_sid (struct ldapsam_privates *ldap_state,
  object found in search_result depending on lp_ldap_delete_dn
 ******************************************************************/
 
-static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
-                                    LDAPMessage *result,
-                                    const char *objectclass,
-                                    const char **attrs)
+static int ldapsam_delete_entry(struct ldapsam_privates *priv,
+                               TALLOC_CTX *mem_ctx,
+                               LDAPMessage *entry,
+                               const char *objectclass,
+                               const char **attrs)
 {
-       int rc;
-       LDAPMessage *entry = NULL;
        LDAPMod **mods = NULL;
-       char *name, *dn;
+       char *name;
+       const char *dn;
        BerElement *ptr = NULL;
 
-       rc = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
-
-       if (rc != 1) {
-               DEBUG(0, ("ldapsam_delete_entry: Entry must exist exactly once!\n"));
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
-       dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
-       if (!dn) {
-               return NT_STATUS_UNSUCCESSFUL;
+       dn = smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry);
+       if (dn == NULL) {
+               return LDAP_NO_MEMORY;
        }
 
        if (lp_ldap_delete_dn()) {
-               NTSTATUS ret = NT_STATUS_OK;
-               rc = smbldap_delete(ldap_state->smbldap_state, dn);
-
-               if (rc != LDAP_SUCCESS) {
-                       DEBUG(0, ("ldapsam_delete_entry: Could not delete object %s\n", dn));
-                       ret = NT_STATUS_UNSUCCESSFUL;
-               }
-               SAFE_FREE(dn);
-               return ret;
+               return smbldap_delete(priv->smbldap_state, dn);
        }
 
        /* Ok, delete only the SAM attributes */
        
-       for (name = ldap_first_attribute(ldap_state->smbldap_state->ldap_struct, entry, &ptr);
+       for (name = ldap_first_attribute(priv2ld(priv), entry, &ptr);
             name != NULL;
-            name = ldap_next_attribute(ldap_state->smbldap_state->ldap_struct, entry, ptr)) {
+            name = ldap_next_attribute(priv2ld(priv), entry, ptr)) {
                const char **attrib;
 
                /* We are only allowed to delete the attributes that
                   really exist. */
 
                for (attrib = attrs; *attrib != NULL; attrib++) {
-                       /* Don't delete LDAP_ATTR_MOD_TIMESTAMP attribute. */
-                       if (strequal(*attrib, get_userattr_key2string(ldap_state->schema_ver,
-                                               LDAP_ATTR_MOD_TIMESTAMP))) {
-                               continue;
-                       }
                        if (strequal(*attrib, name)) {
                                DEBUG(10, ("ldapsam_delete_entry: deleting "
                                           "attribute %s\n", name));
@@ -458,33 +432,17 @@ static NTSTATUS ldapsam_delete_entry(struct ldapsam_privates *ldap_state,
                                                NULL);
                        }
                }
-
                ldap_memfree(name);
        }
-       
+
        if (ptr != NULL) {
                ber_free(ptr, 0);
        }
        
        smbldap_set_mod(&mods, LDAP_MOD_DELETE, "objectClass", objectclass);
-
-       rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
-       ldap_mods_free(mods, True);
-
-       if (rc != LDAP_SUCCESS) {
-               char *ld_error = NULL;
-               ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
-                               &ld_error);
-               
-               DEBUG(0, ("ldapsam_delete_entry: Could not delete attributes for %s, error: %s (%s)\n",
-                         dn, ldap_err2string(rc), ld_error?ld_error:"unknown"));
-               SAFE_FREE(ld_error);
-               SAFE_FREE(dn);
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-
-       SAFE_FREE(dn);
-       return NT_STATUS_OK;
+       talloc_autofree_ldapmod(mem_ctx, mods);
+       
+       return smbldap_modify(priv->smbldap_state, dn, mods);
 }
                  
 /* New Interface is being implemented here */
@@ -627,13 +585,16 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                return False;
        }
 
-       if (ldap_state->smbldap_state->ldap_struct == NULL) {
-               DEBUG(0, ("init_sam_from_ldap: ldap_state->smbldap_state->ldap_struct is NULL!\n"));
+       if (priv2ld(ldap_state) == NULL) {
+               DEBUG(0, ("init_sam_from_ldap: ldap_state->smbldap_state->"
+                         "ldap_struct is NULL!\n"));
                return False;
        }
        
-       if (!smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, "uid", username)) {
-               DEBUG(1, ("init_sam_from_ldap: No uid attribute found for this user!\n"));
+       if (!smbldap_get_single_pstring(priv2ld(ldap_state), entry, "uid",
+                                       username)) {
+               DEBUG(1, ("init_sam_from_ldap: No uid attribute found for "
+                         "this user!\n"));
                return False;
        }
 
@@ -992,6 +953,15 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state,
                ZERO_STRUCT(hours);
        }
 
+       if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
+               if (smbldap_get_single_pstring(priv2ld(ldap_state), entry,
+                                              "uidNumber", temp)) {
+                       /* We've got a uid, feed the cache */
+                       uid_t uid = strtoul(temp, NULL, 10);
+                       store_uid_sid_cache(pdb_get_user_sid(sampass), uid);
+               }
+       }
+
        /* check the timestamp of the cache vs ldap entry */
        if (!(ldap_entry_time = ldapsam_get_entry_timestamp(ldap_state, 
                                                            entry)))
@@ -1380,10 +1350,10 @@ static NTSTATUS ldapsam_setsampwent(struct pdb_methods *my_methods, BOOL update,
        DEBUG(10,("ldapsam_setsampwent: LDAP Query for acb_mask 0x%x will use suffix %s\n", 
                acb_mask, suffix));
 
-       attr_list = get_userattr_list(ldap_state->schema_ver);
+       attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
        rc = smbldap_search(ldap_state->smbldap_state, suffix, LDAP_SCOPE_SUBTREE, filter, 
                            attr_list, 0, &ldap_state->result);
-       free_attr_list( attr_list );
+       talloc_free( attr_list );
 
        if (rc != LDAP_SUCCESS) {
                DEBUG(0, ("ldapsam_setsampwent: LDAP search failed: %s\n", ldap_err2string(rc)));
@@ -1421,10 +1391,12 @@ static void ldapsam_endsampwent(struct pdb_methods *my_methods)
 Get the next entry in the LDAP password database.
 *********************************************************************/
 
-static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT *user)
+static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods,
+                                   SAM_ACCOUNT *user)
 {
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-       struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+       struct ldapsam_privates *ldap_state =
+               (struct ldapsam_privates *)my_methods->private_data;
        BOOL bret = False;
 
        while (!bret) {
@@ -1434,14 +1406,15 @@ static NTSTATUS ldapsam_getsampwent(struct pdb_methods *my_methods, SAM_ACCOUNT
                ldap_state->index++;
                bret = init_sam_from_ldap(ldap_state, user, ldap_state->entry);
                
-               ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
-                                           ldap_state->entry); 
+               ldap_state->entry = ldap_next_entry(priv2ld(ldap_state),
+                                                   ldap_state->entry); 
        }
 
        return NT_STATUS_OK;
 }
 
-static void append_attr(const char ***attr_list, const char *new_attr)
+static void append_attr(TALLOC_CTX *mem_ctx, const char ***attr_list,
+                       const char *new_attr)
 {
        int i;
 
@@ -1453,9 +1426,10 @@ static void append_attr(const char ***attr_list, const char *new_attr)
                ;
        }
 
-       (*attr_list) = SMB_REALLOC_ARRAY((*attr_list), const char *,  i+2);
+       (*attr_list) = TALLOC_REALLOC_ARRAY(mem_ctx, (*attr_list),
+                                           const char *,  i+2);
        SMB_ASSERT((*attr_list) != NULL);
-       (*attr_list)[i] = SMB_STRDUP(new_attr);
+       (*attr_list)[i] = talloc_strdup((*attr_list), new_attr);
        (*attr_list)[i+1] = NULL;
 }
 
@@ -1473,10 +1447,14 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT
        const char ** attr_list;
        int rc;
        
-       attr_list = get_userattr_list( ldap_state->schema_ver );
-       append_attr(&attr_list, get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP));
-       rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
-       free_attr_list( attr_list );
+       attr_list = get_userattr_list( user->mem_ctx, ldap_state->schema_ver );
+       append_attr(user->mem_ctx, &attr_list,
+                   get_userattr_key2string(ldap_state->schema_ver,
+                                           LDAP_ATTR_MOD_TIMESTAMP));
+       append_attr(user->mem_ctx, &attr_list, "uidNumber");
+       rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result,
+                                          attr_list);
+       talloc_free( attr_list );
 
        if ( rc != LDAP_SUCCESS ) 
                return NT_STATUS_NO_SUCH_USER;
@@ -1500,9 +1478,9 @@ static NTSTATUS ldapsam_getsampwnam(struct pdb_methods *my_methods, SAM_ACCOUNT
                        ldap_msgfree(result);
                        return NT_STATUS_NO_SUCH_USER;
                }
-               pdb_set_backend_private_data(user, result, 
-                                            private_data_free_fn, 
+               pdb_set_backend_private_data(user, result, NULL,
                                             my_methods, PDB_CHANGED);
+               talloc_autofree_ldapmsg(user->mem_ctx, result);
                ret = NT_STATUS_OK;
        } else {
                ldap_msgfree(result);
@@ -1518,24 +1496,37 @@ static int ldapsam_get_ldap_user_by_sid(struct ldapsam_privates *ldap_state,
        uint32 rid;
 
        switch ( ldap_state->schema_ver ) {
-               case SCHEMAVER_SAMBASAMACCOUNT:
-                       attr_list = get_userattr_list(ldap_state->schema_ver);
-                       append_attr(&attr_list, get_userattr_key2string(ldap_state->schema_ver,LDAP_ATTR_MOD_TIMESTAMP));
-                       rc = ldapsam_search_suffix_by_sid(ldap_state, sid, result, attr_list);
-                       free_attr_list( attr_list );
+               case SCHEMAVER_SAMBASAMACCOUNT: {
+                       TALLOC_CTX *tmp_ctx = talloc_new(NULL);
+                       if (tmp_ctx == NULL) {
+                               return LDAP_NO_MEMORY;
+                       }
+
+                       attr_list = get_userattr_list(tmp_ctx,
+                                                     ldap_state->schema_ver);
+                       append_attr(tmp_ctx, &attr_list,
+                                   get_userattr_key2string(
+                                           ldap_state->schema_ver,
+                                           LDAP_ATTR_MOD_TIMESTAMP));
+                       append_attr(tmp_ctx, &attr_list, "uidNumber");
+                       rc = ldapsam_search_suffix_by_sid(ldap_state, sid,
+                                                         result, attr_list);
+                       talloc_free(tmp_ctx);
 
                        if ( rc != LDAP_SUCCESS ) 
                                return rc;
                        break;
+               }
                        
                case SCHEMAVER_SAMBAACCOUNT:
                        if (!sid_peek_check_rid(&ldap_state->domain_sid, sid, &rid)) {
                                return rc;
                        }
                
-                       attr_list = get_userattr_list(ldap_state->schema_ver);
+                       attr_list = get_userattr_list(NULL,
+                                                     ldap_state->schema_ver);
                        rc = ldapsam_search_suffix_by_rid(ldap_state, rid, result, attr_list );
-                       free_attr_list( attr_list );
+                       talloc_free( attr_list );
 
                        if ( rc != LDAP_SUCCESS ) 
                                return rc;
@@ -1588,9 +1579,9 @@ static NTSTATUS ldapsam_getsampwsid(struct pdb_methods *my_methods, SAM_ACCOUNT
                return NT_STATUS_NO_SUCH_USER;
        }
 
-       pdb_set_backend_private_data(user, result, 
-                                    private_data_free_fn, 
+       pdb_set_backend_private_data(user, result, NULL,
                                     my_methods, PDB_CHANGED);
+       talloc_autofree_ldapmsg(user->mem_ctx, result);
        return NT_STATUS_OK;
 }      
 
@@ -1639,14 +1630,6 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
                }
                
                if (rc!=LDAP_SUCCESS) {
-                       char *ld_error = NULL;
-                       ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
-                                       &ld_error);
-                       DEBUG(1, ("ldapsam_modify_entry: Failed to %s user dn= %s with: %s\n\t%s\n",
-                              ldap_op == LDAP_MOD_ADD ? "add" : "modify",
-                              dn, ldap_err2string(rc),
-                              ld_error?ld_error:"unknown"));
-                       SAFE_FREE(ld_error);
                        return NT_STATUS_UNSUCCESSFUL;
                }  
        }
@@ -1747,15 +1730,17 @@ static NTSTATUS ldapsam_modify_entry(struct pdb_methods *my_methods,
  Delete entry from LDAP for username.
 *********************************************************************/
 
-static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_ACCOUNT * sam_acct)
+static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods,
+                                          SAM_ACCOUNT * sam_acct)
 {
-       struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+       struct ldapsam_privates *priv =
+               (struct ldapsam_privates *)my_methods->private_data;
        const char *sname;
        int rc;
-       LDAPMessage *result = NULL;
-       NTSTATUS ret;
+       LDAPMessage *msg, *entry;
+       NTSTATUS result = NT_STATUS_NO_MEMORY;
        const char **attr_list;
-       fstring objclass;
+       TALLOC_CTX *mem_ctx;
 
        if (!sam_acct) {
                DEBUG(0, ("ldapsam_delete_sam_account: sam_acct was NULL!\n"));
@@ -1764,35 +1749,42 @@ static NTSTATUS ldapsam_delete_sam_account(struct pdb_methods *my_methods, SAM_A
 
        sname = pdb_get_username(sam_acct);
 
-       DEBUG (3, ("ldapsam_delete_sam_account: Deleting user %s from LDAP.\n", sname));
+       DEBUG(3, ("ldapsam_delete_sam_account: Deleting user %s from "
+                 "LDAP.\n", sname));
 
-       attr_list= get_userattr_delete_list( ldap_state->schema_ver );
-       rc = ldapsam_search_suffix_by_name(ldap_state, sname, &result, attr_list);
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
+               goto done;
+       }
 
-       if (rc != LDAP_SUCCESS)  {
-               free_attr_list( attr_list );
-               return NT_STATUS_NO_SUCH_USER;
+       attr_list = get_userattr_delete_list(mem_ctx, priv->schema_ver );
+       if (attr_list == NULL) {
+               goto done;
        }
-       
-       switch ( ldap_state->schema_ver ) {
-               case SCHEMAVER_SAMBASAMACCOUNT:
-                       fstrcpy( objclass, LDAP_OBJ_SAMBASAMACCOUNT );
-                       break;
-                       
-               case SCHEMAVER_SAMBAACCOUNT:
-                       fstrcpy( objclass, LDAP_OBJ_SAMBAACCOUNT );
-                       break;
-               default:
-                       fstrcpy( objclass, "UNKNOWN" );
-                       DEBUG(0,("ldapsam_delete_sam_account: Unknown schema version specified!\n"));
-                               break;
+
+       rc = ldapsam_search_suffix_by_name(priv, sname, &msg, attr_list);
+
+       if ((rc != LDAP_SUCCESS) ||
+           (ldap_count_entries(priv2ld(priv), msg) != 1) ||
+           ((entry = ldap_first_entry(priv2ld(priv), msg)) == NULL)) {
+               DEBUG(5, ("Could not find user %s\n", sname));
+               result = NT_STATUS_NO_SUCH_USER;
+               goto done;
        }
+       
+       rc = ldapsam_delete_entry(
+               priv, mem_ctx, entry,
+               priv->schema_ver == SCHEMAVER_SAMBASAMACCOUNT ?
+               LDAP_OBJ_SAMBASAMACCOUNT : LDAP_OBJ_SAMBAACCOUNT,
+               attr_list);
 
-       ret = ldapsam_delete_entry(ldap_state, result, objclass, attr_list );
-       ldap_msgfree(result);
-       free_attr_list( attr_list );
+       result = (rc == LDAP_SUCCESS) ?
+               NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
 
-       return ret;
+ done:
+       talloc_free(mem_ctx);
+       return result;
 }
 
 /**********************************************************************
@@ -1823,13 +1815,15 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_A
 
        result = pdb_get_backend_private_data(newpwd, my_methods);
        if (!result) {
-               attr_list = get_userattr_list(ldap_state->schema_ver);
+               attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
                rc = ldapsam_search_suffix_by_name(ldap_state, pdb_get_username(newpwd), &result, attr_list );
-               free_attr_list( attr_list );
+               talloc_free( attr_list );
                if (rc != LDAP_SUCCESS) {
                        return NT_STATUS_UNSUCCESSFUL;
                }
-               pdb_set_backend_private_data(newpwd, result, private_data_free_fn, my_methods, PDB_CHANGED);
+               pdb_set_backend_private_data(newpwd, result, NULL,
+                                            my_methods, PDB_CHANGED);
+               talloc_autofree_ldapmsg(newpwd->mem_ctx, result);
        }
 
        if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
@@ -1866,12 +1860,6 @@ static NTSTATUS ldapsam_update_sam_account(struct pdb_methods *my_methods, SAM_A
        SAFE_FREE(dn);
 
        if (!NT_STATUS_IS_OK(ret)) {
-               char *ld_error = NULL;
-               ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
-                               &ld_error);
-               DEBUG(0,("ldapsam_update_sam_account: failed to modify user with uid = %s, error: %s (%s)\n",
-                        pdb_get_username(newpwd), ld_error?ld_error:"(unknwon)", ldap_err2string(rc)));
-               SAFE_FREE(ld_error);
                return ret;
        }
 
@@ -1966,12 +1954,12 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
        }
 
        /* free this list after the second search or in case we exit on failure */
-       attr_list = get_userattr_list(ldap_state->schema_ver);
+       attr_list = get_userattr_list(NULL, ldap_state->schema_ver);
 
        rc = ldapsam_search_suffix_by_name (ldap_state, username, &result, attr_list);
 
        if (rc != LDAP_SUCCESS) {
-               free_attr_list( attr_list );
+               talloc_free( attr_list );
                return NT_STATUS_UNSUCCESSFUL;
        }
 
@@ -1979,7 +1967,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
                DEBUG(0,("ldapsam_add_sam_account: User '%s' already in the base, with samba attributes\n", 
                         username));
                ldap_msgfree(result);
-               free_attr_list( attr_list );
+               talloc_free( attr_list );
                return NT_STATUS_UNSUCCESSFUL;
        }
        ldap_msgfree(result);
@@ -1992,7 +1980,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
                        if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) != 0) {
                                DEBUG(0,("ldapsam_add_sam_account: SID '%s' already in the base, with samba attributes\n", 
                                         sid_to_string(sid_string, sid)));
-                               free_attr_list( attr_list );
+                               talloc_free( attr_list );
                                ldap_msgfree(result);
                                return NT_STATUS_UNSUCCESSFUL;
                        }
@@ -2011,7 +1999,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
        rc = smbldap_search_suffix(ldap_state->smbldap_state, 
                                   filter, attr_list, &result);
        if ( rc != LDAP_SUCCESS ) {
-               free_attr_list( attr_list );
+               talloc_free( attr_list );
                return NT_STATUS_UNSUCCESSFUL;
        }
 
@@ -2019,7 +2007,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
        
        if (num_result > 1) {
                DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n"));
-               free_attr_list( attr_list );
+               talloc_free( attr_list );
                ldap_msgfree(result);
                return NT_STATUS_UNSUCCESSFUL;
        }
@@ -2033,7 +2021,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
                entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
                tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
                if (!tmp) {
-                       free_attr_list( attr_list );
+                       talloc_free( attr_list );
                        ldap_msgfree(result);
                        return NT_STATUS_UNSUCCESSFUL;
                }
@@ -2059,7 +2047,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
                                           filter, attr_list, &result);
                        
                if ( rc != LDAP_SUCCESS ) {
-                       free_attr_list( attr_list );
+                       talloc_free( attr_list );
                        return NT_STATUS_UNSUCCESSFUL;
                }
                
@@ -2067,7 +2055,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
                
                if (num_result > 1) {
                        DEBUG (0, ("ldapsam_add_sam_account: More than one user with that uid exists: bailing out!\n"));
-                       free_attr_list( attr_list );
+                       talloc_free( attr_list );
                        ldap_msgfree(result);
                        return NT_STATUS_UNSUCCESSFUL;
                }
@@ -2081,7 +2069,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
                        entry = ldap_first_entry (ldap_state->smbldap_state->ldap_struct, result);
                        tmp = smbldap_get_dn (ldap_state->smbldap_state->ldap_struct, entry);
                        if (!tmp) {
-                               free_attr_list( attr_list );
+                               talloc_free( attr_list );
                                ldap_msgfree(result);
                                return NT_STATUS_UNSUCCESSFUL;
                        }
@@ -2090,7 +2078,7 @@ static NTSTATUS ldapsam_add_sam_account(struct pdb_methods *my_methods, SAM_ACCO
                }
        }
        
-       free_attr_list( attr_list );
+       talloc_free( attr_list );
 
        if (num_result == 0) {
                /* Check if we need to add an entry */
@@ -2155,23 +2143,11 @@ static int ldapsam_search_one_group (struct ldapsam_privates *ldap_state,
        int rc;
        const char **attr_list;
 
-       attr_list = get_attr_list(groupmap_attr_list);
+       attr_list = get_attr_list(NULL, groupmap_attr_list);
        rc = smbldap_search(ldap_state->smbldap_state, 
                            lp_ldap_group_suffix (), scope,
                            filter, attr_list, 0, result);
-       free_attr_list( attr_list );
-
-       if (rc != LDAP_SUCCESS) {
-               char *ld_error = NULL;
-               ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
-                               &ld_error);
-               DEBUG(0, ("ldapsam_search_one_group: "
-                         "Problem during the LDAP search: LDAP error: %s (%s)\n",
-                         ld_error?ld_error:"(unknown)", ldap_err2string(rc)));
-               DEBUGADD(3, ("ldapsam_search_one_group: Query was: %s, %s\n",
-                         lp_ldap_group_suffix(), filter));
-               SAFE_FREE(ld_error);
-       }
+       talloc_free(attr_list);
 
        return rc;
 }
@@ -2245,39 +2221,10 @@ for gidNumber(%lu)\n",(unsigned long)map->gid));
        }
        fstrcpy(map->comment, temp);
 
-       return True;
-}
-
-/**********************************************************************
- *********************************************************************/
-
-static BOOL init_ldap_from_group(LDAP *ldap_struct,
-                                LDAPMessage *existing,
-                                LDAPMod ***mods,
-                                const GROUP_MAP *map)
-{
-       pstring tmp;
-
-       if (mods == NULL || map == NULL) {
-               DEBUG(0, ("init_ldap_from_group: NULL parameters found!\n"));
-               return False;
+       if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
+               store_gid_sid_cache(&map->sid, map->gid);
        }
 
-       *mods = NULL;
-
-       sid_to_string(tmp, &map->sid);
-
-       smbldap_make_mod(ldap_struct, existing, mods, 
-               get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_SID), tmp);
-       pstr_sprintf(tmp, "%i", map->sid_name_use);
-       smbldap_make_mod(ldap_struct, existing, mods, 
-               get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GROUP_TYPE), tmp);
-
-       smbldap_make_mod(ldap_struct, existing, mods, 
-               get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DISPLAY_NAME), map->nt_name);
-       smbldap_make_mod(ldap_struct, existing, mods, 
-               get_attr_key2string( groupmap_attr_list, LDAP_ATTR_DESC), map->comment);
-
        return True;
 }
 
@@ -2299,7 +2246,7 @@ static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
                return NT_STATUS_NO_SUCH_GROUP;
        }
 
-       count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
+       count = ldap_count_entries(priv2ld(ldap_state), result);
 
        if (count < 1) {
                DEBUG(4, ("ldapsam_getgroup: Did not find group\n"));
@@ -2308,13 +2255,13 @@ static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
        }
 
        if (count > 1) {
-               DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: count=%d\n",
-                         filter, count));
+               DEBUG(1, ("ldapsam_getgroup: Duplicate entries for filter %s: "
+                         "count=%d\n", filter, count));
                ldap_msgfree(result);
                return NT_STATUS_NO_SUCH_GROUP;
        }
 
-       entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
+       entry = ldap_first_entry(priv2ld(ldap_state), result);
 
        if (!entry) {
                ldap_msgfree(result);
@@ -2322,8 +2269,8 @@ static NTSTATUS ldapsam_getgroup(struct pdb_methods *methods,
        }
 
        if (!init_group_from_ldap(ldap_state, map, entry)) {
-               DEBUG(1, ("ldapsam_getgroup: init_group_from_ldap failed for group filter %s\n",
-                         filter));
+               DEBUG(1, ("ldapsam_getgroup: init_group_from_ldap failed for "
+                         "group filter %s\n", filter));
                ldap_msgfree(result);
                return NT_STATUS_NO_SUCH_GROUP;
        }
@@ -2458,11 +2405,6 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
        char *tmp;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
 
-       if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
-               return pdb_default_enum_group_members(methods, mem_ctx, group,
-                                                     pp_member_rids,
-                                                     p_num_members);
-
        *pp_member_rids = NULL;
        *p_num_members = 0;
 
@@ -2618,9 +2560,10 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods,
 }
 
 static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
-                                              const char *username,
-                                              gid_t primary_gid,
-                                              DOM_SID **pp_sids, gid_t **pp_gids,
+                                              TALLOC_CTX *mem_ctx,
+                                              SAM_ACCOUNT *user,
+                                              DOM_SID **pp_sids,
+                                              gid_t **pp_gids,
                                               size_t *p_num_groups)
 {
        struct ldapsam_privates *ldap_state =
@@ -2634,23 +2577,24 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
        LDAPMessage *entry;
        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
        size_t num_sids, num_gids;
-
-       if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
-               return pdb_default_enum_group_memberships(methods, username,
-                                                         primary_gid, pp_sids,
-                                                         pp_gids, p_num_groups);
+       gid_t primary_gid;
 
        *pp_sids = NULL;
        num_sids = 0;
 
-       escape_name = escape_ldap_string_alloc(username);
+       if (!sid_to_gid(pdb_get_group_sid(user), &primary_gid)) {
+               DEBUG(1, ("sid_to_gid failed for user's primary group\n"));
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+
+       escape_name = escape_ldap_string_alloc(pdb_get_username(user));
 
        if (escape_name == NULL)
                return NT_STATUS_NO_MEMORY;
 
        pstr_sprintf(filter, "(&(objectClass=posixGroup)"
                     "(|(memberUid=%s)(gidNumber=%d)))",
-                    username, primary_gid);
+                    escape_name, primary_gid);
 
        rc = smbldap_search(conn, lp_ldap_group_suffix(),
                            LDAP_SCOPE_SUBTREE, filter, attrs, 0, &msg);
@@ -2666,11 +2610,11 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
 
        /* We need to add the primary group as the first gid/sid */
 
-       add_gid_to_array_unique(NULL, primary_gid, pp_gids, &num_gids);
+       add_gid_to_array_unique(mem_ctx, primary_gid, pp_gids, &num_gids);
 
        /* This sid will be replaced later */
 
-       add_sid_to_array_unique(NULL, &global_sid_NULL, pp_sids, &num_sids);
+       add_sid_to_array_unique(mem_ctx, &global_sid_NULL, pp_sids, &num_sids);
 
        for (entry = ldap_first_entry(conn->ldap_struct, msg);
             entry != NULL;
@@ -2702,13 +2646,16 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
                if (gid == primary_gid) {
                        sid_copy(&(*pp_sids)[0], &sid);
                } else {
-                       add_gid_to_array_unique(NULL, gid, pp_gids, &num_gids);
-                       add_sid_to_array_unique(NULL, &sid, pp_sids, &num_sids);
+                       add_gid_to_array_unique(mem_ctx, gid, pp_gids,
+                                               &num_gids);
+                       add_sid_to_array_unique(mem_ctx, &sid, pp_sids,
+                                               &num_sids);
                }
        }
 
        if (sid_compare(&global_sid_NULL, &(*pp_sids)[0]) == 0) {
-               DEBUG(3, ("primary group of [%s] not found\n", username));
+               DEBUG(3, ("primary group of [%s] not found\n",
+                         pdb_get_username(user)));
                goto done;
        }
 
@@ -2726,143 +2673,203 @@ static NTSTATUS ldapsam_enum_group_memberships(struct pdb_methods *methods,
 }
 
 /**********************************************************************
+ * Augment a posixGroup object with a sambaGroupMapping domgroup
  *********************************************************************/
 
-static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state,
-                                          gid_t gid,
-                                          LDAPMessage **result)
+static NTSTATUS ldapsam_map_posixgroup(TALLOC_CTX *mem_ctx,
+                                      struct ldapsam_privates *ldap_state,
+                                      GROUP_MAP *map)
 {
-       pstring filter;
+       const char *filter, *dn;
+       LDAPMessage *msg, *entry;
+       LDAPMod **mods;
+       int rc;
 
-       pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%lu))", 
-               LDAP_OBJ_POSIXGROUP, LDAP_OBJ_IDMAP_ENTRY,
-               get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER),
-               (unsigned long)gid);
+       filter = talloc_asprintf(mem_ctx,
+                                "(&(objectClass=posixGroup)(gidNumber=%u))",
+                                map->gid);
+       if (filter == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       return ldapsam_search_one_group(ldap_state, filter, result);
-}
+       rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
+                                  get_attr_list(mem_ctx, groupmap_attr_list),
+                                  &msg);
+       talloc_autofree_ldapmsg(mem_ctx, msg);
 
-/**********************************************************************
- *********************************************************************/
+       if ((rc != LDAP_SUCCESS) ||
+           (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) != 1) ||
+           ((entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg)) == NULL)) {
+               return NT_STATUS_NO_SUCH_GROUP;
+       }
+
+       dn = smbldap_talloc_dn(mem_ctx, ldap_state->smbldap_state->ldap_struct, entry);
+       if (dn == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       mods = NULL;
+       smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass",
+                       "sambaGroupMapping");
+       smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "sambaSid",
+                        sid_string_static(&map->sid));
+       smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "sambaGroupType",
+                        talloc_asprintf(mem_ctx, "%d", map->sid_name_use));
+       smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "displayName",
+                        map->nt_name);
+       smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "description",
+                        map->comment);
+       talloc_autofree_ldapmod(mem_ctx, mods);
+
+       rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
+       if (rc != LDAP_SUCCESS) {
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
+       return NT_STATUS_OK;
+}
 
 static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods,
                                                GROUP_MAP *map)
 {
        struct ldapsam_privates *ldap_state =
                (struct ldapsam_privates *)methods->private_data;
-       LDAPMessage *result = NULL;
+       LDAPMessage *msg = NULL;
        LDAPMod **mods = NULL;
-       int count;
+       const char *attrs[] = { NULL };
+       char *filter;
 
-       char *tmp;
-       pstring dn;
-       LDAPMessage *entry;
+       char *dn;
+       TALLOC_CTX *mem_ctx;
+       NTSTATUS result;
 
-       GROUP_MAP dummy;
+       DOM_SID sid;
 
        int rc;
 
-       if (NT_STATUS_IS_OK(ldapsam_getgrgid(methods, &dummy,
-                                            map->gid))) {
-               DEBUG(0, ("ldapsam_add_group_mapping_entry: Group %ld already exists in LDAP\n", (unsigned long)map->gid));
-               return NT_STATUS_UNSUCCESSFUL;
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
+               return NT_STATUS_NO_MEMORY;
        }
 
-       rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
-       if (rc != LDAP_SUCCESS) {
-               ldap_msgfree(result);
-               return NT_STATUS_UNSUCCESSFUL;
+       filter = talloc_asprintf(mem_ctx, "(sambaSid=%s)",
+                                sid_string_static(&map->sid));
+       if (filter == NULL) {
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
        }
 
-       count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
+       rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_suffix(),
+                           LDAP_SCOPE_SUBTREE, filter, attrs, True, &msg);
+       talloc_autofree_ldapmsg(mem_ctx, msg);
 
-       if ( count == 0 ) {
-               /* There's no posixGroup account, let's try to find an
-                * appropriate idmap entry for aliases */
-
-               pstring suffix;
-               pstring filter;
-               const char **attr_list;
-
-               ldap_msgfree(result);
+       if ((rc == LDAP_SUCCESS) &&
+           (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) > 0)) {
 
-               pstrcpy( suffix, lp_ldap_idmap_suffix() );
-               pstr_sprintf(filter, "(&(objectClass=%s)(%s=%u))",
-                            LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_GIDNUMBER,
-                            map->gid);
-               
-               attr_list = get_attr_list( sidmap_attr_list );
-               rc = smbldap_search(ldap_state->smbldap_state, suffix,
-                                   LDAP_SCOPE_SUBTREE, filter, attr_list,
-                                   0, &result);
+               DEBUG(3, ("SID %s already present in LDAP, refusing to add "
+                         "group mapping entry\n",
+                         sid_string_static(&map->sid)));
+               result = NT_STATUS_GROUP_EXISTS;
+               goto done;
+       }
 
-               free_attr_list(attr_list);
+       switch (map->sid_name_use) {
 
-               if (rc != LDAP_SUCCESS) {
-                       DEBUG(3,("Failure looking up entry (%s)\n",
-                                ldap_err2string(rc) ));
-                       ldap_msgfree(result);
-                       return NT_STATUS_UNSUCCESSFUL;
+       case SID_NAME_DOM_GRP:
+               /* To map a domain group we need to have a posix group
+                  to attach to. */
+               result = ldapsam_map_posixgroup(mem_ctx, ldap_state, map);
+               goto done;
+               break;
+
+       case SID_NAME_ALIAS:
+               if (!sid_check_is_in_our_domain(&map->sid)) {
+                       DEBUG(3, ("Refusing to map sid %s as an alias, not "
+                                 "in our domain\n",
+                                 sid_string_static(&map->sid)));
+                       result = NT_STATUS_INVALID_PARAMETER;
+                       goto done;
                }
-       }
-                          
-       count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
-       if ( count == 0 ) {
-               ldap_msgfree(result);
-               return NT_STATUS_UNSUCCESSFUL;
-       }
+               break;
+
+       case SID_NAME_WKN_GRP:
+               if (!sid_check_is_in_builtin(&map->sid)) {
+                       DEBUG(3, ("Refusing to map sid %s as an alias, not "
+                                 "in builtin domain\n",
+                                 sid_string_static(&map->sid)));
+                       result = NT_STATUS_INVALID_PARAMETER;
+                       goto done;
+               }
+               break;
 
-       if (count > 1) {
-               DEBUG(2, ("ldapsam_add_group_mapping_entry: Group %lu must exist exactly once in LDAP\n",
-                         (unsigned long)map->gid));
-               ldap_msgfree(result);
-               return NT_STATUS_UNSUCCESSFUL;
+       default:
+               DEBUG(3, ("Got invalid use '%s' for mapping\n",
+                         sid_type_lookup(map->sid_name_use)));
+               result = NT_STATUS_INVALID_PARAMETER;
+               goto done;
        }
 
-       entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
-       tmp = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
-       if (!tmp) {
-               ldap_msgfree(result);
-               return NT_STATUS_UNSUCCESSFUL;
+       /* Domain groups have been mapped in a separate routine, we have to
+        * create an alias now */
+
+       if (map->gid == -1) {
+               DEBUG(10, ("Refusing to map gid==-1\n"));
+               result = NT_STATUS_INVALID_PARAMETER;
+               goto done;
        }
-       pstrcpy(dn, tmp);
-       SAFE_FREE(tmp);
 
-       if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct,
-                                 result, &mods, map)) {
-               DEBUG(0, ("ldapsam_add_group_mapping_entry: init_ldap_from_group failed!\n"));
-               ldap_mods_free(mods, True);
-               ldap_msgfree(result);
-               return NT_STATUS_UNSUCCESSFUL;
+       if (pdb_gid_to_sid(map->gid, &sid)) {
+               DEBUG(3, ("Gid %d is already mapped to SID %s, refusing to "
+                         "add\n", map->gid, sid_string_static(&sid)));
+               result = NT_STATUS_GROUP_EXISTS;
+               goto done;
        }
 
-       ldap_msgfree(result);
+       /* Ok, enough checks done. It's still racy to go ahead now, but that's
+        * the best we can get out of LDAP. */
 
-       if (mods == NULL) {
-               DEBUG(0, ("ldapsam_add_group_mapping_entry: mods is empty\n"));
-               return NT_STATUS_UNSUCCESSFUL;
+       dn = talloc_asprintf(mem_ctx, "sambaSid=%s,%s",
+                            sid_string_static(&map->sid),
+                            lp_ldap_group_suffix());
+       if (dn == NULL) {
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
        }
 
-       smbldap_set_mod(&mods, LDAP_MOD_ADD, "objectClass", LDAP_OBJ_GROUPMAP );
+       mods = NULL;
 
-       rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
-       ldap_mods_free(mods, True);
+       smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "objectClass",
+                        "sambaSidEntry");
+       smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "objectClass",
+                        "sambaGroupMapping");
 
-       if (rc != LDAP_SUCCESS) {
-               char *ld_error = NULL;
-               ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
-                               &ld_error);
-               DEBUG(0, ("ldapsam_add_group_mapping_entry: failed to add group %lu error: %s (%s)\n", (unsigned long)map->gid, 
-                         ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
-               SAFE_FREE(ld_error);
-               return NT_STATUS_UNSUCCESSFUL;
-       }
+       smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "sambaSid",
+                        sid_string_static(&map->sid));
+       smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "sambaGroupType",
+                        talloc_asprintf(mem_ctx, "%d", map->sid_name_use));
+       smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "displayName",
+                        map->nt_name);
+       smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "description",
+                        map->comment);
+       smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, NULL, &mods, "gidNumber",
+                        talloc_asprintf(mem_ctx, "%u", map->gid));
+       talloc_autofree_ldapmod(mem_ctx, mods);
 
-       DEBUG(2, ("ldapsam_add_group_mapping_entry: successfully modified group %lu in LDAP\n", (unsigned long)map->gid));
-       return NT_STATUS_OK;
+       rc = smbldap_add(ldap_state->smbldap_state, dn, mods);
+
+       result = (rc == LDAP_SUCCESS) ?
+               NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
+
+ done:
+       talloc_free(mem_ctx);
+       return result;
 }
 
 /**********************************************************************
+ * Update a group mapping entry. We're quite strict about what can be changed:
+ * Only the description and displayname may be changed. It simply does not
+ * make any sense to change the SID, gid or the type in a mapping.
  *********************************************************************/
 
 static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
@@ -2871,63 +2878,80 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
        struct ldapsam_privates *ldap_state =
                (struct ldapsam_privates *)methods->private_data;
        int rc;
-       char *dn = NULL;
-       LDAPMessage *result = NULL;
+       const char *filter, *dn;
+       LDAPMessage *msg = NULL;
        LDAPMessage *entry = NULL;
        LDAPMod **mods = NULL;
+       TALLOC_CTX *mem_ctx;
+       NTSTATUS result;
 
-       rc = ldapsam_search_one_group_by_gid(ldap_state, map->gid, &result);
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       if (rc != LDAP_SUCCESS) {
-               return NT_STATUS_UNSUCCESSFUL;
+       /* Make 100% sure that sid, gid and type are not changed by looking up
+        * exactly the values we're given in LDAP. */
+
+       filter = talloc_asprintf(mem_ctx, "(&(objectClass=sambaGroupMapping)"
+                                "(sambaSid=%s)(gidNumber=%u)"
+                                "(sambaGroupType=%d))",
+                                sid_string_static(&map->sid), map->gid,
+                                map->sid_name_use);
+       if (filter == NULL) {
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
        }
 
-       if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
-               DEBUG(0, ("ldapsam_update_group_mapping_entry: No group to modify!\n"));
-               ldap_msgfree(result);
-               return NT_STATUS_UNSUCCESSFUL;
+       rc = smbldap_search_suffix(ldap_state->smbldap_state, filter,
+                                  get_attr_list(mem_ctx, groupmap_attr_list),
+                                  &msg);
+       talloc_autofree_ldapmsg(mem_ctx, msg);
+
+       if ((rc != LDAP_SUCCESS) ||
+           (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg) != 1) ||
+           ((entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg)) == NULL)) {
+               result = NT_STATUS_NO_SUCH_GROUP;
+               goto done;
        }
 
-       entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
+       dn = smbldap_talloc_dn(mem_ctx, ldap_state->smbldap_state->ldap_struct, entry);
 
-       if (!init_ldap_from_group(ldap_state->smbldap_state->ldap_struct,
-                                 result, &mods, map)) {
-               DEBUG(0, ("ldapsam_update_group_mapping_entry: init_ldap_from_group failed\n"));
-               ldap_msgfree(result);
-               if (mods != NULL)
-                       ldap_mods_free(mods,True);
-               return NT_STATUS_UNSUCCESSFUL;
+       if (dn == NULL) {
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
        }
 
+       mods = NULL;
+       smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "displayName",
+                        map->nt_name);
+       smbldap_make_mod(ldap_state->smbldap_state->ldap_struct, entry, &mods, "description",
+                        map->comment);
+       talloc_autofree_ldapmod(mem_ctx, mods);
+
        if (mods == NULL) {
-               DEBUG(4, ("ldapsam_update_group_mapping_entry: mods is empty: nothing to do\n"));
-               ldap_msgfree(result);
-               return NT_STATUS_OK;
+               DEBUG(4, ("ldapsam_update_group_mapping_entry: mods is empty: "
+                         "nothing to do\n"));
+               result = NT_STATUS_OK;
+               goto done;
        }
 
-       dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry);
-       if (!dn) {
-               ldap_msgfree(result);
-               return NT_STATUS_UNSUCCESSFUL;
-       }
        rc = smbldap_modify(ldap_state->smbldap_state, dn, mods);
-       SAFE_FREE(dn);
-
-       ldap_mods_free(mods, True);
-       ldap_msgfree(result);
 
        if (rc != LDAP_SUCCESS) {
-               char *ld_error = NULL;
-               ldap_get_option(ldap_state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING,
-                               &ld_error);
-               DEBUG(0, ("ldapsam_update_group_mapping_entry: failed to modify group %lu error: %s (%s)\n", (unsigned long)map->gid, 
-                         ld_error ? ld_error : "(unknown)", ldap_err2string(rc)));
-               SAFE_FREE(ld_error);
-               return NT_STATUS_UNSUCCESSFUL;
+               result = NT_STATUS_ACCESS_DENIED;
+               goto done;
        }
 
-       DEBUG(2, ("ldapsam_update_group_mapping_entry: successfully modified group %lu in LDAP\n", (unsigned long)map->gid));
-       return NT_STATUS_OK;
+       DEBUG(2, ("ldapsam_update_group_mapping_entry: successfully modified "
+                 "group %lu in LDAP\n", (unsigned long)map->gid));
+
+       result = NT_STATUS_OK;
+
+ done:
+       talloc_free(mem_ctx);
+       return result;
 }
 
 /**********************************************************************
@@ -2936,53 +2960,103 @@ static NTSTATUS ldapsam_update_group_mapping_entry(struct pdb_methods *methods,
 static NTSTATUS ldapsam_delete_group_mapping_entry(struct pdb_methods *methods,
                                                   DOM_SID sid)
 {
-       struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)methods->private_data;
-       pstring sidstring, filter;
-       LDAPMessage *result = NULL;
+       struct ldapsam_privates *priv =
+               (struct ldapsam_privates *)methods->private_data;
+       LDAPMessage *msg, *entry;
        int rc;
-       NTSTATUS ret;
-       const char **attr_list;
+       NTSTATUS result;
+       TALLOC_CTX *mem_ctx;
+       char *filter;
 
-       sid_to_string(sidstring, &sid);
-       
-       pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))", 
-               LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID, sidstring);
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
 
-       rc = ldapsam_search_one_group(ldap_state, filter, &result);
+       filter = talloc_asprintf(mem_ctx, "(&(objectClass=%s)(%s=%s))",
+                                LDAP_OBJ_GROUPMAP, LDAP_ATTRIBUTE_SID,
+                                sid_string_static(&sid));
+       if (filter == NULL) {
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+       rc = smbldap_search_suffix(priv->smbldap_state, filter,
+                                  get_attr_list(mem_ctx, groupmap_attr_list),
+                                  &msg);
+       talloc_autofree_ldapmsg(mem_ctx, msg);
 
-       if (rc != LDAP_SUCCESS) {
-               return NT_STATUS_NO_SUCH_GROUP;
+       if ((rc != LDAP_SUCCESS) ||
+           (ldap_count_entries(priv2ld(priv), msg) != 1) ||
+           ((entry = ldap_first_entry(priv2ld(priv), msg)) == NULL)) {
+               result = NT_STATUS_NO_SUCH_GROUP;
+               goto done;
+       }
+
+       rc = ldapsam_delete_entry(priv, mem_ctx, entry, LDAP_OBJ_GROUPMAP,
+                                 get_attr_list(mem_ctx,
+                                               groupmap_attr_list_to_delete));
+       if ((rc == LDAP_NAMING_VIOLATION) ||
+           (rc == LDAP_OBJECT_CLASS_VIOLATION)) {
+               const char *attrs[] = { "sambaGroupType", "description",
+                                       "displayName", "sambaSIDList",
+                                       NULL };
+
+               /* Second try. Don't delete the sambaSID attribute, this is
+                  for "old" entries that are tacked on a winbind
+                  sambaIdmapEntry. */
+
+               rc = ldapsam_delete_entry(priv, mem_ctx, entry,
+                                         LDAP_OBJ_GROUPMAP, attrs);
        }
 
-       attr_list = get_attr_list( groupmap_attr_list_to_delete );
-       ret = ldapsam_delete_entry(ldap_state, result, LDAP_OBJ_GROUPMAP, attr_list);
-       free_attr_list ( attr_list );
+       if ((rc == LDAP_NAMING_VIOLATION) ||
+           (rc == LDAP_OBJECT_CLASS_VIOLATION)) {
+               const char *attrs[] = { "sambaGroupType", "description",
+                                       "displayName", "sambaSIDList",
+                                       "gidNumber", NULL };
 
-       ldap_msgfree(result);
+               /* Third try. This is a post-3.0.21 alias (containing only
+                * sambaSidEntry and sambaGroupMapping classes), we also have
+                * to delete the gidNumber attribute, only the sambaSidEntry
+                * remains */
 
-       return ret;
-}
+               rc = ldapsam_delete_entry(priv, mem_ctx, entry,
+                                         LDAP_OBJ_GROUPMAP, attrs);
+       }
+
+       result = (rc == LDAP_SUCCESS) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+
+ done:
+       talloc_free(mem_ctx);
+       return result;
+ }
 
 /**********************************************************************
  *********************************************************************/
 
-static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update)
+static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods,
+                                   BOOL update)
 {
-       struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+       struct ldapsam_privates *ldap_state =
+               (struct ldapsam_privates *)my_methods->private_data;
        fstring filter;
        int rc;
        const char **attr_list;
 
        pstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_GROUPMAP);
-       attr_list = get_attr_list( groupmap_attr_list );
+       attr_list = get_attr_list( NULL, groupmap_attr_list );
        rc = smbldap_search(ldap_state->smbldap_state, lp_ldap_group_suffix(),
                            LDAP_SCOPE_SUBTREE, filter,
                            attr_list, 0, &ldap_state->result);
-       free_attr_list( attr_list );
+       talloc_free(attr_list);
 
        if (rc != LDAP_SUCCESS) {
-               DEBUG(0, ("ldapsam_setsamgrent: LDAP search failed: %s\n", ldap_err2string(rc)));
-               DEBUG(3, ("ldapsam_setsamgrent: Query was: %s, %s\n", lp_ldap_group_suffix(), filter));
+               DEBUG(0, ("ldapsam_setsamgrent: LDAP search failed: %s\n",
+                         ldap_err2string(rc)));
+               DEBUG(3, ("ldapsam_setsamgrent: Query was: %s, %s\n",
+                         lp_ldap_group_suffix(), filter));
                ldap_msgfree(ldap_state->result);
                ldap_state->result = NULL;
                return NT_STATUS_UNSUCCESSFUL;
@@ -2992,7 +3066,9 @@ static NTSTATUS ldapsam_setsamgrent(struct pdb_methods *my_methods, BOOL update)
                  ldap_count_entries(ldap_state->smbldap_state->ldap_struct,
                                     ldap_state->result)));
 
-       ldap_state->entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, ldap_state->result);
+       ldap_state->entry =
+               ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
+                                ldap_state->result);
        ldap_state->index = 0;
 
        return NT_STATUS_OK;
@@ -3013,7 +3089,8 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
                                    GROUP_MAP *map)
 {
        NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-       struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data;
+       struct ldapsam_privates *ldap_state =
+               (struct ldapsam_privates *)my_methods->private_data;
        BOOL bret = False;
 
        while (!bret) {
@@ -3021,10 +3098,12 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
                        return ret;
                
                ldap_state->index++;
-               bret = init_group_from_ldap(ldap_state, map, ldap_state->entry);
+               bret = init_group_from_ldap(ldap_state, map,
+                                           ldap_state->entry);
                
-               ldap_state->entry = ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
-                                           ldap_state->entry); 
+               ldap_state->entry =
+                       ldap_next_entry(ldap_state->smbldap_state->ldap_struct,
+                                       ldap_state->entry);     
        }
 
        return NT_STATUS_OK;
@@ -3035,7 +3114,8 @@ static NTSTATUS ldapsam_getsamgrent(struct pdb_methods *my_methods,
 
 static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
                                           enum SID_NAME_USE sid_name_use,
-                                          GROUP_MAP **pp_rmap, size_t *p_num_entries,
+                                          GROUP_MAP **pp_rmap,
+                                          size_t *p_num_entries,
                                           BOOL unix_only)
 {
        GROUP_MAP map;
@@ -3046,24 +3126,28 @@ static NTSTATUS ldapsam_enum_group_mapping(struct pdb_methods *methods,
        *pp_rmap = NULL;
 
        if (!NT_STATUS_IS_OK(ldapsam_setsamgrent(methods, False))) {
-               DEBUG(0, ("ldapsam_enum_group_mapping: Unable to open passdb\n"));
+               DEBUG(0, ("ldapsam_enum_group_mapping: Unable to open "
+                         "passdb\n"));
                return NT_STATUS_ACCESS_DENIED;
        }
 
        while (NT_STATUS_IS_OK(ldapsam_getsamgrent(methods, &map))) {
                if (sid_name_use != SID_NAME_UNKNOWN &&
                    sid_name_use != map.sid_name_use) {
-                       DEBUG(11,("ldapsam_enum_group_mapping: group %s is not of the requested type\n", map.nt_name));
+                       DEBUG(11,("ldapsam_enum_group_mapping: group %s is "
+                                 "not of the requested type\n", map.nt_name));
                        continue;
                }
                if (unix_only==ENUM_ONLY_MAPPED && map.gid==-1) {
-                       DEBUG(11,("ldapsam_enum_group_mapping: group %s is non mapped\n", map.nt_name));
+                       DEBUG(11,("ldapsam_enum_group_mapping: group %s is "
+                                 "non mapped\n", map.nt_name));
                        continue;
                }
 
                mapt=SMB_REALLOC_ARRAY((*pp_rmap), GROUP_MAP, entries+1);
                if (!mapt) {
-                       DEBUG(0,("ldapsam_enum_group_mapping: Unable to enlarge group map!\n"));
+                       DEBUG(0,("ldapsam_enum_group_mapping: Unable to "
+                                "enlarge group map!\n"));
                        SAFE_FREE(*pp_rmap);
                        return NT_STATUS_UNSUCCESSFUL;
                }
@@ -3095,14 +3179,28 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
        int count;
        LDAPMod **mods = NULL;
        int rc;
+       enum SID_NAME_USE type = SID_NAME_USE_NONE;
 
        pstring filter;
 
-       pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%s))",
-                    LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY,
-                    get_attr_key2string(groupmap_attr_list,
-                                        LDAP_ATTR_GROUP_SID),
-                    sid_string_static(alias));
+       if (sid_check_is_in_builtin(alias)) {
+               type = SID_NAME_WKN_GRP;
+       }
+
+       if (sid_check_is_in_our_domain(alias)) {
+               type = SID_NAME_ALIAS;
+       }
+
+       if (type == SID_NAME_USE_NONE) {
+               DEBUG(5, ("SID %s is neither in builtin nor in our domain!\n",
+                         sid_string_static(alias)));
+               return NT_STATUS_NO_SUCH_ALIAS;
+       }
+
+       pstr_sprintf(filter,
+                    "(&(objectClass=%s)(sambaSid=%s)(sambaGroupType=%d))",
+                    LDAP_OBJ_GROUPMAP, sid_string_static(alias),
+                    type);
 
        if (ldapsam_search_one_group(ldap_state, filter,
                                     &result) != LDAP_SUCCESS)
@@ -3118,8 +3216,8 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
        }
 
        if (count > 1) {
-               DEBUG(1, ("ldapsam_modify_aliasmem: Duplicate entries for filter %s: "
-                         "count=%d\n", filter, count));
+               DEBUG(1, ("ldapsam_modify_aliasmem: Duplicate entries for "
+                         "filter %s: count=%d\n", filter, count));
                ldap_msgfree(result);
                return NT_STATUS_NO_SUCH_ALIAS;
        }
@@ -3147,22 +3245,20 @@ static NTSTATUS ldapsam_modify_aliasmem(struct pdb_methods *methods,
 
        ldap_mods_free(mods, True);
        ldap_msgfree(result);
+       SAFE_FREE(dn);
+
+       if (rc == LDAP_TYPE_OR_VALUE_EXISTS) {
+               return NT_STATUS_MEMBER_IN_ALIAS;
+       }
+
+       if (rc == LDAP_NO_SUCH_ATTRIBUTE) {
+               return NT_STATUS_MEMBER_NOT_IN_ALIAS;
+       }
 
        if (rc != LDAP_SUCCESS) {
-               char *ld_error = NULL;
-               ldap_get_option(ldap_state->smbldap_state->ldap_struct,
-                               LDAP_OPT_ERROR_STRING,&ld_error);
-               
-               DEBUG(0, ("ldapsam_modify_aliasmem: Could not modify alias "
-                         "for %s, error: %s (%s)\n", dn, ldap_err2string(rc),
-                         ld_error?ld_error:"unknown"));
-               SAFE_FREE(ld_error);
-               SAFE_FREE(dn);
                return NT_STATUS_UNSUCCESSFUL;
        }
 
-       SAFE_FREE(dn);
-
        return NT_STATUS_OK;
 }
 
@@ -3182,7 +3278,8 @@ static NTSTATUS ldapsam_del_aliasmem(struct pdb_methods *methods,
 }
 
 static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
-                                     const DOM_SID *alias, DOM_SID **pp_members,
+                                     const DOM_SID *alias,
+                                     DOM_SID **pp_members,
                                      size_t *p_num_members)
 {
        struct ldapsam_privates *ldap_state =
@@ -3194,15 +3291,29 @@ static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
        int i;
        pstring filter;
        size_t num_members = 0;
+       enum SID_NAME_USE type = SID_NAME_USE_NONE;
 
        *pp_members = NULL;
        *p_num_members = 0;
 
-       pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%s))",
-                    LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY,
-                    get_attr_key2string(groupmap_attr_list,
-                                        LDAP_ATTR_GROUP_SID),
-                    sid_string_static(alias));
+       if (sid_check_is_in_builtin(alias)) {
+               type = SID_NAME_WKN_GRP;
+       }
+
+       if (sid_check_is_in_our_domain(alias)) {
+               type = SID_NAME_ALIAS;
+       }
+
+       if (type == SID_NAME_USE_NONE) {
+               DEBUG(5, ("SID %s is neither in builtin nor in our domain!\n",
+                         sid_string_static(alias)));
+               return NT_STATUS_NO_SUCH_ALIAS;
+       }
+
+       pstr_sprintf(filter,
+                    "(&(objectClass=%s)(sambaSid=%s)(sambaGroupType=%d))",
+                    LDAP_OBJ_GROUPMAP, sid_string_static(alias),
+                    type);
 
        if (ldapsam_search_one_group(ldap_state, filter,
                                     &result) != LDAP_SUCCESS)
@@ -3218,8 +3329,8 @@ static NTSTATUS ldapsam_enum_aliasmem(struct pdb_methods *methods,
        }
 
        if (count > 1) {
-               DEBUG(1, ("ldapsam_enum_aliasmem: Duplicate entries for filter %s: "
-                         "count=%d\n", filter, count));
+               DEBUG(1, ("ldapsam_enum_aliasmem: Duplicate entries for "
+                         "filter %s: count=%d\n", filter, count));
                ldap_msgfree(result);
                return NT_STATUS_NO_SUCH_ALIAS;
        }
@@ -3279,14 +3390,25 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
        int i;
        int rc;
        char *filter;
+       enum SID_NAME_USE type = SID_NAME_USE_NONE;
+
+       if (sid_check_is_builtin(domain_sid)) {
+               type = SID_NAME_WKN_GRP;
+       }
 
-       /* This query could be further optimized by adding a
-          (&(sambaSID=<domain-sid>*)) so that only those aliases that are
-          asked for in the getuseraliases are returned. */        
+       if (sid_check_is_domain(domain_sid)) {
+               type = SID_NAME_ALIAS;
+       }
+
+       if (type == SID_NAME_USE_NONE) {
+               DEBUG(5, ("SID %s is neither builtin nor domain!\n",
+                         sid_string_static(domain_sid)));
+               return NT_STATUS_UNSUCCESSFUL;
+       }
 
        filter = talloc_asprintf(mem_ctx,
-                                "(&(|(objectclass=%s)(objectclass=%s))(|",
-                                LDAP_OBJ_GROUPMAP, LDAP_OBJ_IDMAP_ENTRY);
+                                "(&(|(objectclass=%s)(sambaGroupType=%d))(|",
+                                LDAP_OBJ_GROUPMAP, type);
 
        for (i=0; i<num_members; i++)
                filter = talloc_asprintf(mem_ctx, "%s(sambaSIDList=%s)",
@@ -3331,7 +3453,9 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods,
        return NT_STATUS_OK;
 }
 
-static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods, int policy_index, uint32 value)
+static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
+                                                  int policy_index,
+                                                  uint32 value)
 {
        NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
        int rc;
@@ -3352,7 +3476,8 @@ static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
 
        policy_attr = get_account_policy_attr(policy_index);
        if (policy_attr == NULL) {
-               DEBUG(0,("ldapsam_set_account_policy_in_ldap: invalid policy\n"));
+               DEBUG(0,("ldapsam_set_account_policy_in_ldap: invalid "
+                        "policy\n"));
                return ntstatus;
        }
 
@@ -3363,40 +3488,39 @@ static NTSTATUS ldapsam_set_account_policy_in_ldap(struct pdb_methods *methods,
 
        smbldap_set_mod(&mods, LDAP_MOD_REPLACE, policy_attr, value_string);
 
-       rc = smbldap_modify(ldap_state->smbldap_state, ldap_state->domain_dn, mods);
+       rc = smbldap_modify(ldap_state->smbldap_state, ldap_state->domain_dn,
+                           mods);
 
        ldap_mods_free(mods, True);
 
        if (rc != LDAP_SUCCESS) {
-               char *ld_error = NULL;
-               ldap_get_option(ldap_state->smbldap_state->ldap_struct,
-                               LDAP_OPT_ERROR_STRING,&ld_error);
-               
-               DEBUG(0, ("ldapsam_set_account_policy_in_ldap: Could not set account policy "
-                         "for %s, error: %s (%s)\n", ldap_state->domain_dn, ldap_err2string(rc),
-                         ld_error?ld_error:"unknown"));
-               SAFE_FREE(ld_error);
                return ntstatus;
        }
 
        if (!cache_account_policy_set(policy_index, value)) {
-               DEBUG(0,("ldapsam_set_account_policy_in_ldap: failed to update local tdb cache\n"));
+               DEBUG(0,("ldapsam_set_account_policy_in_ldap: failed to "
+                        "update local tdb cache\n"));
                return ntstatus;
        }
 
        return NT_STATUS_OK;
 }
 
-static NTSTATUS ldapsam_set_account_policy(struct pdb_methods *methods, int policy_index, uint32 value)
+static NTSTATUS ldapsam_set_account_policy(struct pdb_methods *methods,
+                                          int policy_index, uint32 value)
 {
        if (!account_policy_migrated(False)) {
-               return (account_policy_set(policy_index, value)) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+               return (account_policy_set(policy_index, value)) ?
+                       NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
        }
 
-       return ldapsam_set_account_policy_in_ldap(methods, policy_index, value);
+       return ldapsam_set_account_policy_in_ldap(methods, policy_index,
+                                                 value);
 }
 
-static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods, int policy_index, uint32 *value)
+static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods,
+                                                    int policy_index,
+                                                    uint32 *value)
 {
        NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
        LDAPMessage *result = NULL;
@@ -3419,7 +3543,8 @@ static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods
 
        policy_attr = get_account_policy_attr(policy_index);
        if (!policy_attr) {
-               DEBUG(0,("ldapsam_get_account_policy_from_ldap: invalid policy index: %d\n", policy_index));
+               DEBUG(0,("ldapsam_get_account_policy_from_ldap: invalid "
+                        "policy index: %d\n", policy_index));
                return ntstatus;
        }
 
@@ -3427,31 +3552,24 @@ static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods
        attrs[1] = NULL;
 
        rc = smbldap_search(ldap_state->smbldap_state, ldap_state->domain_dn,
-                           LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, &result);
+                           LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0,
+                           &result);
 
        if (rc != LDAP_SUCCESS) {
-               char *ld_error = NULL;
-               ldap_get_option(ldap_state->smbldap_state->ldap_struct,
-                               LDAP_OPT_ERROR_STRING,&ld_error);
-               
-               DEBUG(3, ("ldapsam_get_account_policy_from_ldap: Could not get account policy "
-                         "for %s, error: %s (%s)\n", ldap_state->domain_dn, ldap_err2string(rc),
-                         ld_error?ld_error:"unknown"));
-               SAFE_FREE(ld_error);
                return ntstatus;
        }
 
-       count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result);
+       count = ldap_count_entries(priv2ld(ldap_state), result);
        if (count < 1) {
                goto out;
        }
 
-       entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
+       entry = ldap_first_entry(priv2ld(ldap_state), result);
        if (entry == NULL) {
                goto out;
        }
 
-       vals = ldap_get_values(ldap_state->smbldap_state->ldap_struct, entry, policy_attr);
+       vals = ldap_get_values(priv2ld(ldap_state), entry, policy_attr);
        if (vals == NULL) {
                goto out;
        }
@@ -3470,7 +3588,8 @@ out:
 
 /* wrapper around ldapsam_get_account_policy_from_ldap(), handles tdb as cache 
 
-   - if user hasn't decided to use account policies inside LDAP just reuse the old tdb values
+   - if user hasn't decided to use account policies inside LDAP just reuse the
+     old tdb values
    
    - if there is a valid cache entry, return that
    - if there is an LDAP entry, update cache and return 
@@ -3478,32 +3597,38 @@ out:
 
    Guenther
 */
-static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods, int policy_index, uint32 *value)
+static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods,
+                                          int policy_index, uint32 *value)
 {
        NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL;
 
        if (!account_policy_migrated(False)) {
-               return (account_policy_get(policy_index, value)) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+               return (account_policy_get(policy_index, value))
+                       ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
        }
 
        if (cache_account_policy_get(policy_index, value)) {
-               DEBUG(11,("ldapsam_get_account_policy: got valid value from cache\n"));
+               DEBUG(11,("ldapsam_get_account_policy: got valid value from "
+                         "cache\n"));
                return NT_STATUS_OK;
        }
 
-       ntstatus = ldapsam_get_account_policy_from_ldap(methods, policy_index, value);
+       ntstatus = ldapsam_get_account_policy_from_ldap(methods, policy_index,
+                                                       value);
        if (NT_STATUS_IS_OK(ntstatus)) {
                goto update_cache;
        }
 
-       DEBUG(10,("ldapsam_get_account_policy: failed to retrieve from ldap\n"));
+       DEBUG(10,("ldapsam_get_account_policy: failed to retrieve from "
+                 "ldap\n"));
 
 #if 0
        /* should we automagically migrate old tdb value here ? */
        if (account_policy_get(policy_index, value))
                goto update_ldap;
 
-       DEBUG(10,("ldapsam_get_account_policy: no tdb for %d, trying default\n", policy_index));
+       DEBUG(10,("ldapsam_get_account_policy: no tdb for %d, trying "
+                 "default\n", policy_index));
 #endif
 
        if (!account_policy_get_default(policy_index, value)) {
@@ -3520,7 +3645,8 @@ static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods, int poli
  update_cache:
  
        if (!cache_account_policy_set(policy_index, *value)) {
-               DEBUG(0,("ldapsam_get_account_policy: failed to update local tdb as a cache\n"));
+               DEBUG(0,("ldapsam_get_account_policy: failed to update local "
+                        "tdb as a cache\n"));
                return NT_STATUS_UNSUCCESSFUL;
        }
 
@@ -3536,39 +3662,44 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
 {
        struct ldapsam_privates *ldap_state =
                (struct ldapsam_privates *)methods->private_data;
-       LDAP *ldap_struct = ldap_state->smbldap_state->ldap_struct;
        LDAPMessage *msg = NULL;
        LDAPMessage *entry;
        char *allsids = NULL;
-       char *tmp;
        int i, rc, num_mapped;
-       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       NTSTATUS result = NT_STATUS_NO_MEMORY;
+       TALLOC_CTX *mem_ctx;
+       LDAP *ld;
+       BOOL is_builtin;
 
-       if (!lp_parm_bool(-1, "ldapsam", "trusted", False))
-               return pdb_default_lookup_rids(methods, domain_sid,
-                                              num_rids, rids, names, attrs);
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
+               goto done;
+       }
 
-       if (!sid_equal(domain_sid, get_global_sam_sid())) {
-               /* TODO: Sooner or later we need to look up BUILTIN rids as
-                * well. -- vl */
+       if (!sid_check_is_builtin(domain_sid) &&
+           !sid_check_is_domain(domain_sid)) {
+               result = NT_STATUS_INVALID_PARAMETER;
                goto done;
        }
 
        for (i=0; i<num_rids; i++)
                attrs[i] = SID_NAME_UNKNOWN;
 
-       allsids = SMB_STRDUP("");
-       if (allsids == NULL) return NT_STATUS_NO_MEMORY;
+       allsids = talloc_strdup(mem_ctx, "");
+       if (allsids == NULL) {
+               goto done;
+       }
 
        for (i=0; i<num_rids; i++) {
                DOM_SID sid;
                sid_copy(&sid, domain_sid);
                sid_append_rid(&sid, rids[i]);
-               tmp = allsids;
-               asprintf(&allsids, "%s(sambaSid=%s)", allsids,
-                        sid_string_static(&sid));
-               if (allsids == NULL) return NT_STATUS_NO_MEMORY;
-               free(tmp);
+               allsids = talloc_asprintf_append(allsids, "(sambaSid=%s)",
+                                                sid_string_static(&sid));
+               if (allsids == NULL) {
+                       goto done;
+               }
        }
 
        /* First look for users */
@@ -3577,40 +3708,43 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
                char *filter;
                const char *ldap_attrs[] = { "uid", "sambaSid", NULL };
 
-               asprintf(&filter, ("(&(objectClass=sambaSamAccount)(|%s))"),
-                        allsids);
-               if (filter == NULL) return NT_STATUS_NO_MEMORY;
+               filter = talloc_asprintf(
+                       mem_ctx, ("(&(objectClass=sambaSamAccount)(|%s))"),
+                       allsids);
+
+               if (filter == NULL) {
+                       goto done;
+               }
 
                rc = smbldap_search(ldap_state->smbldap_state,
                                    lp_ldap_user_suffix(),
                                    LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
                                    &msg);
-
-               SAFE_FREE(filter);
+               talloc_autofree_ldapmsg(mem_ctx, msg);
        }
 
        if (rc != LDAP_SUCCESS)
                goto done;
 
+       ld = ldap_state->smbldap_state->ldap_struct;
        num_mapped = 0;
 
-       for (entry = ldap_first_entry(ldap_struct, msg);
+       for (entry = ldap_first_entry(ld, msg);
             entry != NULL;
-            entry = ldap_next_entry(ldap_struct, entry))
-       {
+            entry = ldap_next_entry(ld, entry)) {
                uint32 rid;
                int rid_index;
-               fstring str;
+               const char *name;
 
-               if (!ldapsam_extract_rid_from_entry(ldap_struct, entry,
-                                                   get_global_sam_sid(),
+               if (!ldapsam_extract_rid_from_entry(ld, entry, domain_sid,
                                                    &rid)) {
                        DEBUG(2, ("Could not find sid from ldap entry\n"));
                        continue;
                }
 
-               if (!smbldap_get_single_attribute(ldap_struct, entry,
-                                                 "uid", str, sizeof(str)-1)) {
+               name = smbldap_talloc_single_attribute(ld, entry, "uid",
+                                                      names);
+               if (name == NULL) {
                        DEBUG(2, ("Could not retrieve uid attribute\n"));
                        continue;
                }
@@ -3626,9 +3760,7 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
                }
 
                attrs[rid_index] = SID_NAME_USER;
-               names[rid_index] = talloc_strdup(names, str);
-               if (names[rid_index] == NULL) return NT_STATUS_NO_MEMORY;
-
+               names[rid_index] = name;
                num_mapped += 1;
        }
 
@@ -3638,49 +3770,83 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
                goto done;
        }
 
-       if (msg != NULL) {
-               ldap_msgfree(msg);
-       }
-
        /* Same game for groups */
 
        {
                char *filter;
-               const char *ldap_attrs[] = { "cn", "sambaSid", NULL };
+               const char *ldap_attrs[] = { "cn", "displayName", "sambaSid",
+                                            "sambaGroupType", NULL };
 
-               asprintf(&filter, ("(&(objectClass=sambaGroupMapping)(|%s))"),
-                        allsids);
-               if (filter == NULL) return NT_STATUS_NO_MEMORY;
+               filter = talloc_asprintf(
+                       mem_ctx, "(&(objectClass=sambaGroupMapping)(|%s))",
+                       allsids);
+               if (filter == NULL) {
+                       goto done;
+               }
 
                rc = smbldap_search(ldap_state->smbldap_state,
                                    lp_ldap_group_suffix(),
                                    LDAP_SCOPE_SUBTREE, filter, ldap_attrs, 0,
                                    &msg);
-
-               SAFE_FREE(filter);
+               talloc_autofree_ldapmsg(mem_ctx, msg);
        }
 
        if (rc != LDAP_SUCCESS)
                goto done;
 
-       for (entry = ldap_first_entry(ldap_struct, msg);
+       /* ldap_struct might have changed due to a reconnect */
+
+       ld = ldap_state->smbldap_state->ldap_struct;
+
+       /* For consistency checks, we already checked we're only domain or builtin */
+
+       is_builtin = sid_check_is_builtin(domain_sid);
+
+       for (entry = ldap_first_entry(ld, msg);
             entry != NULL;
-            entry = ldap_next_entry(ldap_struct, entry))
+            entry = ldap_next_entry(ld, entry))
        {
                uint32 rid;
                int rid_index;
-               fstring str;
+               const char *attr;
+               enum SID_NAME_USE type;
+               const char *dn = smbldap_talloc_dn(mem_ctx, ld, entry);
+
+               attr = smbldap_talloc_single_attribute(ld, entry, "sambaGroupType",
+                                                      mem_ctx);
+               if (attr == NULL) {
+                       DEBUG(2, ("Could not extract type from ldap entry %s\n",
+                                 dn));
+                       continue;
+               }
 
-               if (!ldapsam_extract_rid_from_entry(ldap_struct, entry,
-                                                   get_global_sam_sid(),
+               type = atol(attr);
+
+               /* Consistency checks */
+               if ((is_builtin && (type != SID_NAME_WKN_GRP)) ||
+                   (!is_builtin && ((type != SID_NAME_ALIAS) &&
+                                    (type != SID_NAME_DOM_GRP)))) {
+                       DEBUG(2, ("Rejecting invalid group mapping entry %s\n", dn));
+               }
+
+               if (!ldapsam_extract_rid_from_entry(ld, entry, domain_sid,
                                                    &rid)) {
-                       DEBUG(2, ("Could not find sid from ldap entry\n"));
+                       DEBUG(2, ("Could not find sid from ldap entry %s\n", dn));
                        continue;
                }
 
-               if (!smbldap_get_single_attribute(ldap_struct, entry,
-                                                 "cn", str, sizeof(str)-1)) {
-                       DEBUG(2, ("Could not retrieve cn attribute\n"));
+               attr = smbldap_talloc_single_attribute(ld, entry, "cn", names);
+
+               if (attr == NULL) {
+                       DEBUG(10, ("Could not retrieve 'cn' attribute from %s\n",
+                                  dn));
+                       attr = smbldap_talloc_single_attribute(
+                               ld, entry, "displayName", names);
+               }
+
+               if (attr == NULL) {
+                       DEBUG(2, ("Could not retrieve naming attribute from %s\n",
+                                 dn));
                        continue;
                }
 
@@ -3694,9 +3860,8 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
                        continue;
                }
 
-               attrs[rid_index] = SID_NAME_DOM_GRP;
-               names[rid_index] = talloc_strdup(names, str);
-               if (names[rid_index] == NULL) return NT_STATUS_NO_MEMORY;
+               attrs[rid_index] = type;
+               names[rid_index] = attr;
                num_mapped += 1;
        }
 
@@ -3706,11 +3871,7 @@ static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods,
                result = (num_mapped == num_rids) ?
                        NT_STATUS_OK : STATUS_SOME_UNMAPPED;
  done:
-       SAFE_FREE(allsids);
-
-       if (msg != NULL)
-               ldap_msgfree(msg);
-
+       talloc_free(mem_ctx);
        return result;
 }
 
@@ -3833,7 +3994,6 @@ static BOOL ldapsam_search_firstpage(struct pdb_search *search)
 static BOOL ldapsam_search_nextpage(struct pdb_search *search)
 {
        struct ldap_search_state *state = search->private_data;
-       LDAP *ld = state->connection->ldap_struct;
        int rc;
 
        if (!state->connection->paged_results) {
@@ -3850,7 +4010,7 @@ static BOOL ldapsam_search_nextpage(struct pdb_search *search)
        if ((rc != LDAP_SUCCESS) || (state->entries == NULL))
                return False;
 
-       state->current_entry = ldap_first_entry(ld, state->entries);
+       state->current_entry = ldap_first_entry(state->connection->ldap_struct, state->entries);
 
        if (state->current_entry == NULL) {
                ldap_msgfree(state->entries);
@@ -3864,7 +4024,6 @@ static BOOL ldapsam_search_next_entry(struct pdb_search *search,
                                      struct samr_displayentry *entry)
 {
        struct ldap_search_state *state = search->private_data;
-       LDAP *ld = state->connection->ldap_struct;
        BOOL result;
 
  retry:
@@ -3875,17 +4034,17 @@ static BOOL ldapsam_search_next_entry(struct pdb_search *search,
            !ldapsam_search_nextpage(search))
                    return False;
 
-       result = state->ldap2displayentry(state, search->mem_ctx, ld,
+       result = state->ldap2displayentry(state, search->mem_ctx, state->connection->ldap_struct,
                                          state->current_entry, entry);
 
        if (!result) {
                char *dn;
-               dn = ldap_get_dn(ld, state->current_entry);
+               dn = ldap_get_dn(state->connection->ldap_struct, state->current_entry);
                DEBUG(5, ("Skipping entry %s\n", dn != NULL ? dn : "<NULL>"));
                if (dn != NULL) ldap_memfree(dn);
        }
 
-       state->current_entry = ldap_next_entry(ld, state->current_entry);
+       state->current_entry = ldap_next_entry(state->connection->ldap_struct, state->current_entry);
 
        if (state->current_entry == NULL) {
                ldap_msgfree(state->entries);
@@ -4002,7 +4161,8 @@ static BOOL ldapuser2displayentry(struct ldap_search_state *state,
        ldap_value_free(vals);
 
        if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid)) {
-               DEBUG(0, ("sid %s does not belong to our domain\n", sid_string_static(&sid)));
+               DEBUG(0, ("sid %s does not belong to our domain\n",
+                         sid_string_static(&sid)));
                return False;
        }
 
@@ -4102,10 +4262,14 @@ static BOOL ldapgroup2displayentry(struct ldap_search_state *state,
                        DEBUG(5, ("\"cn\" not found\n"));
                        return False;
                }
-               pull_utf8_talloc(mem_ctx, CONST_DISCARD(char **, &result->account_name), vals[0]);
+               pull_utf8_talloc(mem_ctx,
+                                CONST_DISCARD(char **, &result->account_name),
+                                vals[0]);
        }
        else {
-               pull_utf8_talloc(mem_ctx, CONST_DISCARD(char **, &result->account_name), vals[0]);
+               pull_utf8_talloc(mem_ctx,
+                                CONST_DISCARD(char **, &result->account_name),
+                                vals[0]);
        }
 
        ldap_value_free(vals);
@@ -4146,17 +4310,21 @@ static BOOL ldapgroup2displayentry(struct ldap_search_state *state,
                case SID_NAME_DOM_GRP:
                case SID_NAME_ALIAS:
 
-                       if (!sid_peek_check_rid(get_global_sam_sid(), &sid, &result->rid)) {
-                               DEBUG(0, ("%s is not in our domain\n", sid_string_static(&sid)));
+                       if (!sid_peek_check_rid(get_global_sam_sid(), &sid,
+                                               &result->rid)) {
+                               DEBUG(0, ("%s is not in our domain\n",
+                                         sid_string_static(&sid)));
                                return False;
                        }
                        break;
        
                case SID_NAME_WKN_GRP:
 
-                       if (!sid_peek_check_rid(&global_sid_Builtin, &sid, &result->rid)) {
+                       if (!sid_peek_check_rid(&global_sid_Builtin, &sid,
+                                               &result->rid)) {
 
-                               DEBUG(0, ("%s is not in builtin sid\n", sid_string_static(&sid)));
+                               DEBUG(0, ("%s is not in builtin sid\n",
+                                         sid_string_static(&sid)));
                                return False;
                        }
                        break;
@@ -4191,7 +4359,8 @@ static BOOL ldapsam_search_grouptype(struct pdb_methods *methods,
                                        "(&(objectclass=sambaGroupMapping)"
                                        "(sambaGroupType=%d))", type);
        state->attrs = talloc_attrs(search->mem_ctx, "cn", "sambaSid",
-                                   "displayName", "description", "sambaGroupType", NULL);
+                                   "displayName", "description",
+                                   "sambaGroupType", NULL);
        state->attrsonly = 0;
        state->pagedresults_cookie = NULL;
        state->entries = NULL;
@@ -4232,6 +4401,214 @@ static BOOL ldapsam_search_aliases(struct pdb_methods *methods,
        return False;
 }
 
+static BOOL ldapsam_rid_algorithm(struct pdb_methods *methods)
+{
+       return False;
+}
+
+static NTSTATUS ldapsam_get_new_rid(struct ldapsam_privates *priv,
+                                   uint32 *rid)
+{
+       struct smbldap_state *smbldap_state = priv->smbldap_state;
+
+       LDAPMessage *result = NULL;
+       LDAPMessage *entry = NULL;
+       LDAPMod **mods = NULL;
+       NTSTATUS status;
+       char *value;
+       int rc;
+       uint32 nextRid = 0;
+
+       TALLOC_CTX *mem_ctx;
+
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       status = smbldap_search_domain_info(smbldap_state, &result,
+                                           get_global_sam_name(), False);
+       if (!NT_STATUS_IS_OK(status)) {
+               DEBUG(3, ("Could not get domain info: %s\n",
+                         nt_errstr(status)));
+               goto done;
+       }
+
+       talloc_autofree_ldapmsg(mem_ctx, result);
+
+       entry = ldap_first_entry(priv2ld(priv), result);
+       if (entry == NULL) {
+               DEBUG(0, ("Could not get domain info entry\n"));
+               status = NT_STATUS_INTERNAL_DB_CORRUPTION;
+               goto done;
+       }
+
+       /* Find the largest of the three attributes "sambaNextRid",
+          "sambaNextGroupRid" and "sambaNextUserRid". I gave up on the
+          concept of differentiating between user and group rids, and will
+          use only "sambaNextRid" in the future. But for compatibility
+          reasons I look if others have chosen different strategies -- VL */
+
+       value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+                                               "sambaNextRid", mem_ctx);
+       if (value != NULL) {
+               uint32 tmp = (uint32)strtoul(value, NULL, 10);
+               nextRid = MAX(nextRid, tmp);
+       }
+
+       value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+                                               "sambaNextUserRid", mem_ctx);
+       if (value != NULL) {
+               uint32 tmp = (uint32)strtoul(value, NULL, 10);
+               nextRid = MAX(nextRid, tmp);
+       }
+
+       value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+                                               "sambaNextGroupRid", mem_ctx);
+       if (value != NULL) {
+               uint32 tmp = (uint32)strtoul(value, NULL, 10);
+               nextRid = MAX(nextRid, tmp);
+       }
+
+       if (nextRid == 0) {
+               nextRid = BASE_RID-1;
+       }
+
+       nextRid += 1;
+
+       smbldap_make_mod(priv2ld(priv), entry, &mods, "sambaNextRid",
+                        talloc_asprintf(mem_ctx, "%d", nextRid));
+       talloc_autofree_ldapmod(mem_ctx, mods);
+
+       rc = smbldap_modify(smbldap_state,
+                           smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry),
+                           mods);
+
+       /* ACCESS_DENIED is used as a placeholder for "the modify failed,
+        * please retry" */
+
+       status = (rc == LDAP_SUCCESS) ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
+
+ done:
+       if (NT_STATUS_IS_OK(status)) {
+               *rid = nextRid;
+       }
+
+       talloc_free(mem_ctx);
+       return status;
+}
+
+static BOOL ldapsam_new_rid(struct pdb_methods *methods, uint32 *rid)
+{
+       int i;
+
+       for (i=0; i<10; i++) {
+               NTSTATUS result = ldapsam_get_new_rid(methods->private_data,
+                                                     rid);
+               if (NT_STATUS_IS_OK(result)) {
+                       return True;
+               }
+
+               if (!NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED)) {
+                       return False;
+               }
+
+               /* The ldap update failed (maybe a race condition), retry */
+       }
+
+       /* Tried 10 times, fail. */
+       return False;
+}
+
+static BOOL ldapsam_sid_to_id(struct pdb_methods *methods,
+                             const DOM_SID *sid,
+                             union unid_t *id, enum SID_NAME_USE *type)
+{
+       struct ldapsam_privates *priv = methods->private_data;
+       char *filter;
+       const char *attrs[] = { "sambaGroupType", "gidNumber", "uidNumber",
+                               NULL };
+       LDAPMessage *result = NULL;
+       LDAPMessage *entry = NULL;
+       BOOL ret = False;
+       char *value;
+       int rc;
+
+       TALLOC_CTX *mem_ctx;
+
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
+               return False;
+       }
+
+       filter = talloc_asprintf(mem_ctx,
+                                "(&(sambaSid=%s)"
+                                "(|(objectClass=sambaGroupMapping)"
+                                "(objectClass=sambaSamAccount)))",
+                                sid_string_static(sid));
+       if (filter == NULL) {
+               DEBUG(5, ("talloc_asprintf failed\n"));
+               goto done;
+       }
+
+       rc = smbldap_search_suffix(priv->smbldap_state, filter,
+                                  attrs, &result);
+       if (rc != LDAP_SUCCESS) {
+               goto done;
+       }
+       talloc_autofree_ldapmsg(mem_ctx, result);
+
+       if (ldap_count_entries(priv2ld(priv), result) != 1) {
+               DEBUG(10, ("Got %d entries, expected one\n",
+                          ldap_count_entries(priv2ld(priv), result)));
+               goto done;
+       }
+
+       entry = ldap_first_entry(priv2ld(priv), result);
+
+       value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+                                               "sambaGroupType", mem_ctx);
+
+       if (value != NULL) {
+               const char *gid_str;
+               /* It's a group */
+
+               gid_str = smbldap_talloc_single_attribute(
+                       priv2ld(priv), entry, "gidNumber", mem_ctx);
+               if (gid_str == NULL) {
+                       DEBUG(1, ("%s has sambaGroupType but no gidNumber\n",
+                                 smbldap_talloc_dn(mem_ctx, priv2ld(priv),
+                                                   entry)));
+                       goto done;
+               }
+
+               id->gid = strtoul(gid_str, NULL, 10);
+               *type = strtoul(value, NULL, 10);
+               ret = True;
+               goto done;
+       }
+
+       /* It must be a user */
+
+       value = smbldap_talloc_single_attribute(priv2ld(priv), entry,
+                                               "uidNumber", mem_ctx);
+       if (value == NULL) {
+               DEBUG(1, ("Could not find uidNumber in %s\n",
+                         smbldap_talloc_dn(mem_ctx, priv2ld(priv), entry)));
+               goto done;
+       }
+
+       id->uid = strtoul(value, NULL, 10);
+       *type = SID_NAME_USER;
+
+       ret = True;
+ done:
+       talloc_free(mem_ctx);
+       return ret;
+}
+
 /**********************************************************************
  Housekeeping
  *********************************************************************/
@@ -4288,15 +4665,15 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS **
        (*pdb_method)->update_group_mapping_entry = ldapsam_update_group_mapping_entry;
        (*pdb_method)->delete_group_mapping_entry = ldapsam_delete_group_mapping_entry;
        (*pdb_method)->enum_group_mapping = ldapsam_enum_group_mapping;
-       (*pdb_method)->enum_group_members = ldapsam_enum_group_members;
-       (*pdb_method)->enum_group_memberships = ldapsam_enum_group_memberships;
-       (*pdb_method)->lookup_rids = ldapsam_lookup_rids;
 
        (*pdb_method)->get_account_policy = ldapsam_get_account_policy;
        (*pdb_method)->set_account_policy = ldapsam_set_account_policy;
 
        (*pdb_method)->get_seq_num = ldapsam_get_seq_num;
 
+       (*pdb_method)->rid_algorithm = ldapsam_rid_algorithm;
+       (*pdb_method)->new_rid = ldapsam_new_rid;
+
        /* TODO: Setup private data and free */
 
        ldap_state = TALLOC_ZERO_P(pdb_context->mem_ctx, struct ldapsam_privates);
@@ -4377,7 +4754,8 @@ NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, co
        pstring domain_sid_string;
        char *dn;
 
-       if (!NT_STATUS_IS_OK(nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location))) {
+       nt_status = pdb_init_ldapsam_common(pdb_context, pdb_method, location);
+       if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
        }
 
@@ -4391,27 +4769,41 @@ NTSTATUS pdb_init_ldapsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_method, co
        (*pdb_method)->search_groups = ldapsam_search_groups;
        (*pdb_method)->search_aliases = ldapsam_search_aliases;
 
+       if (lp_parm_bool(-1, "ldapsam", "trusted", False)) {
+               (*pdb_method)->enum_group_members = ldapsam_enum_group_members;
+               (*pdb_method)->enum_group_memberships =
+                       ldapsam_enum_group_memberships;
+               (*pdb_method)->lookup_rids = ldapsam_lookup_rids;
+               (*pdb_method)->sid_to_id = ldapsam_sid_to_id;
+       }
+
        ldap_state = (*pdb_method)->private_data;
        ldap_state->schema_ver = SCHEMAVER_SAMBASAMACCOUNT;
 
        /* Try to setup the Domain Name, Domain SID, algorithmic rid base */
        
-       nt_status = smbldap_search_domain_info(ldap_state->smbldap_state, &result, 
+       nt_status = smbldap_search_domain_info(ldap_state->smbldap_state,
+                                              &result, 
                                               ldap_state->domain_name, True);
        
        if ( !NT_STATUS_IS_OK(nt_status) ) {
-               DEBUG(2, ("pdb_init_ldapsam: WARNING: Could not get domain info, nor add one to the domain\n"));
-               DEBUGADD(2, ("pdb_init_ldapsam: Continuing on regardless, will be unable to allocate new users/groups, \
-and will risk BDCs having inconsistant SIDs\n"));
+               DEBUG(2, ("pdb_init_ldapsam: WARNING: Could not get domain "
+                         "info, nor add one to the domain\n"));
+               DEBUGADD(2, ("pdb_init_ldapsam: Continuing on regardless, "
+                            "will be unable to allocate new users/groups, "
+                            "and will risk BDCs having inconsistant SIDs\n"));
                sid_copy(&ldap_state->domain_sid, get_global_sam_sid());
                return NT_STATUS_OK;
        }
 
-       /* Given that the above might fail, everything below this must be optional */
+       /* Given that the above might fail, everything below this must be
+        * optional */
        
-       entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result);
+       entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct,
+                                result);
        if (!entry) {
-               DEBUG(0, ("pdb_init_ldapsam: Could not get domain info entry\n"));
+               DEBUG(0, ("pdb_init_ldapsam: Could not get domain info "
+                         "entry\n"));
                ldap_msgfree(result);
                return NT_STATUS_UNSUCCESSFUL;
        }
@@ -4424,35 +4816,51 @@ and will risk BDCs having inconsistant SIDs\n"));
        ldap_state->domain_dn = smb_xstrdup(dn);
        ldap_memfree(dn);
 
-       if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
-                                get_userattr_key2string(ldap_state->schema_ver, LDAP_ATTR_USER_SID), 
-                                domain_sid_string)) {
+       if (smbldap_get_single_pstring(
+                   ldap_state->smbldap_state->ldap_struct,
+                   entry, 
+                   get_userattr_key2string(ldap_state->schema_ver,
+                                           LDAP_ATTR_USER_SID), 
+                   domain_sid_string)) {
                BOOL found_sid;
                if (!string_to_sid(&ldap_domain_sid, domain_sid_string)) {
-                       DEBUG(1, ("pdb_init_ldapsam: SID [%s] could not be read as a valid SID\n", domain_sid_string));
+                       DEBUG(1, ("pdb_init_ldapsam: SID [%s] could not be "
+                                 "read as a valid SID\n", domain_sid_string));
                        return NT_STATUS_INVALID_PARAMETER;
                }
-               found_sid = secrets_fetch_domain_sid(ldap_state->domain_name, &secrets_domain_sid);
-               if (!found_sid || !sid_equal(&secrets_domain_sid, &ldap_domain_sid)) {
+               found_sid = secrets_fetch_domain_sid(ldap_state->domain_name,
+                                                    &secrets_domain_sid);
+               if (!found_sid || !sid_equal(&secrets_domain_sid,
+                                            &ldap_domain_sid)) {
                        fstring new_sid_str, old_sid_str;
-                       DEBUG(1, ("pdb_init_ldapsam: Resetting SID for domain %s based on pdb_ldap results %s -> %s\n",
-                                 ldap_state->domain_name, 
-                                 sid_to_string(old_sid_str, &secrets_domain_sid),
-                                 sid_to_string(new_sid_str, &ldap_domain_sid)));
+                       DEBUG(1, ("pdb_init_ldapsam: Resetting SID for domain "
+                                 "%s based on pdb_ldap results %s -> %s\n",
+                                 ldap_state->domain_name,
+                                 sid_to_string(old_sid_str,
+                                               &secrets_domain_sid),
+                                 sid_to_string(new_sid_str,
+                                               &ldap_domain_sid)));
                        
                        /* reset secrets.tdb sid */
-                       secrets_store_domain_sid(ldap_state->domain_name, &ldap_domain_sid);
-                       DEBUG(1, ("New global sam SID: %s\n", sid_to_string(new_sid_str, get_global_sam_sid())));
+                       secrets_store_domain_sid(ldap_state->domain_name,
+                                                &ldap_domain_sid);
+                       DEBUG(1, ("New global sam SID: %s\n",
+                                 sid_to_string(new_sid_str,
+                                               get_global_sam_sid())));
                }
                sid_copy(&ldap_state->domain_sid, &ldap_domain_sid);
        }
 
-       if (smbldap_get_single_pstring(ldap_state->smbldap_state->ldap_struct, entry, 
-                                get_attr_key2string( dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE ),
-                                alg_rid_base_string)) {
+       if (smbldap_get_single_pstring(
+                   ldap_state->smbldap_state->ldap_struct,
+                   entry, 
+                   get_attr_key2string( dominfo_attr_list,
+                                        LDAP_ATTR_ALGORITHMIC_RID_BASE ),
+                   alg_rid_base_string)) {
                alg_rid_base = (uint32)atol(alg_rid_base_string);
                if (alg_rid_base != algorithmic_rid_base()) {
-                       DEBUG(0, ("The value of 'algorithmic RID base' has changed since the LDAP\n"
+                       DEBUG(0, ("The value of 'algorithmic RID base' has "
+                                 "changed since the LDAP\n"
                                  "database was initialised.  Aborting. \n"));
                        ldap_msgfree(result);
                        return NT_STATUS_UNSUCCESSFUL;
index cf2d1d7c8a8b86215130a1e6d2edeca2947c094b..49c3c9db06405ae96a19757dcfee704c3db0d8ef 100644 (file)
@@ -771,13 +771,16 @@ static NTSTATUS pdb_nds_update_login_attempts(struct pdb_methods *methods,
 
                result = pdb_get_backend_private_data(sam_acct, methods);
                if (!result) {
-                       attr_list = get_userattr_list(ldap_state->schema_ver);
+                       attr_list = get_userattr_list(NULL,
+                                                     ldap_state->schema_ver);
                        rc = ldapsam_search_suffix_by_name(ldap_state, username, &result, attr_list );
-                       free_attr_list( attr_list );
+                       talloc_free( attr_list );
                        if (rc != LDAP_SUCCESS) {
                                return NT_STATUS_OBJECT_NAME_NOT_FOUND;
                        }
-                       pdb_set_backend_private_data(sam_acct, result, private_data_free_fn, methods, PDB_CHANGED);
+                       pdb_set_backend_private_data(sam_acct, result, NULL,
+                                                    methods, PDB_CHANGED);
+                       talloc_autofree_ldapmsg(sam_acct->mem_ctx, result);
                }
 
                if (ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result) == 0) {
index 487df96e9539c916f5c1cde0df9f13923e82bc77..06a3f4f4a138b4f3191ad9ee1877401021b2a52e 100644 (file)
@@ -594,7 +594,6 @@ static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, str
        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, &smbpasswd_state->pw_file_lock_depth);
@@ -619,11 +618,6 @@ static BOOL add_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, str
                        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 */
@@ -1161,14 +1155,13 @@ static BOOL build_smb_pass (struct smb_passwd *smb_pw, const SAM_ACCOUNT *sampas
                
                /* If the user specified a RID, make sure its able to be both stored and retreived */
                if (rid == DOMAIN_USER_RID_GUEST) {
-                       struct passwd *passwd = getpwnam_alloc(lp_guestaccount());
+                       struct passwd *passwd = getpwnam_alloc(NULL, lp_guestaccount());
                        if (!passwd) {
                                DEBUG(0, ("Could not find gest account via getpwnam()! (%s)\n", lp_guestaccount()));
                                return False;
                        }
                        smb_pw->smb_userid=passwd->pw_uid;
-                       passwd_free(&passwd);
-
+                       talloc_free(passwd);
                } else if (algorithmic_pdb_rid_is_user(rid)) {
                        smb_pw->smb_userid=algorithmic_pdb_user_rid_to_uid(rid);
                } else {
@@ -1204,7 +1197,7 @@ static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state,
 
        /* verify the user account exists */
                        
-       if ( !(pwfile = getpwnam_alloc(pw_buf->smb_name)) ) {
+       if ( !(pwfile = getpwnam_alloc(NULL, pw_buf->smb_name)) ) {
                DEBUG(0,("build_sam_account: smbpasswd database is corrupt!  username %s with uid "
                "%u is not in unix passwd database!\n", pw_buf->smb_name, pw_buf->smb_userid));
                        return False;
@@ -1213,7 +1206,7 @@ static BOOL build_sam_account(struct smbpasswd_privates *smbpasswd_state,
        if (!NT_STATUS_IS_OK(pdb_fill_sam_pw(sam_pass, pwfile)))
                return False;
                
-       passwd_free(&pwfile);
+       talloc_free(pwfile);
 
        /* set remaining fields */
                
@@ -1532,6 +1525,11 @@ done:
        return (ret);   
 }
 
+static BOOL smbpasswd_rid_algorithm(struct pdb_methods *methods)
+{
+       return True;
+}
+
 static void free_private_data(void **vp) 
 {
        struct smbpasswd_privates **privates = (struct smbpasswd_privates**)vp;
@@ -1563,6 +1561,8 @@ static NTSTATUS pdb_init_smbpasswd(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_m
        (*pdb_method)->delete_sam_account = smbpasswd_delete_sam_account;
        (*pdb_method)->rename_sam_account = smbpasswd_rename_sam_account;
 
+       (*pdb_method)->rid_algorithm = smbpasswd_rid_algorithm;
+
        /* Setup private data and free function */
 
        privates = TALLOC_ZERO_P(pdb_context->mem_ctx, struct smbpasswd_privates);
index 370c8adc7dc988f3349359d2832120a77d34b860..74f47e70dca9bee9cafade3a63f95b28b28794e4 100644 (file)
@@ -864,7 +864,98 @@ done:
        
        return (ret);   
 }
-       
+
+static BOOL tdbsam_rid_algorithm(struct pdb_methods *methods)
+{
+       return False;
+}
+
+/*
+ * Historically, winbind was responsible for allocating RIDs, so the next RID
+ * value was stored in winbindd_idmap.tdb. It has been moved to passdb now,
+ * but for compatibility reasons we still keep the the next RID counter in
+ * winbindd_idmap.tdb.
+ */
+
+/*****************************************************************************
+ Initialise idmap database. For now (Dec 2005) this is a copy of the code in
+ sam/idmap_tdb.c. Maybe at a later stage we can remove that capability from
+ winbind completely and store the RID counter in passdb.tdb.
+
+ Dont' fully initialize with the HWM values, if it's new, we're only
+ interested in the RID counter.
+*****************************************************************************/
+
+static BOOL init_idmap_tdb(TDB_CONTEXT *tdb)
+{
+       int32 version;
+
+       if (tdb_lock_bystring(tdb, "IDMAP_VERSION", 0) != 0) {
+               DEBUG(0, ("Could not lock IDMAP_VERSION\n"));
+               return False;
+       }
+
+       version = tdb_fetch_int32(tdb, "IDMAP_VERSION");
+
+       if (version == -1) {
+               /* No key found, must be a new db */
+               if (tdb_store_int32(tdb, "IDMAP_VERSION",
+                                   IDMAP_VERSION) != 0) {
+                       DEBUG(0, ("Could not store IDMAP_VERSION\n"));
+                       tdb_unlock_bystring(tdb, "IDMAP_VERSION");
+                       return False;
+               }
+               version = IDMAP_VERSION;
+       }
+
+       if (version != IDMAP_VERSION) {
+               DEBUG(0, ("Expected IDMAP_VERSION=%d, found %d. Please "
+                         "start winbind once\n", IDMAP_VERSION, version));
+               tdb_unlock_bystring(tdb, "IDMAP_VERSION");
+               return False;
+       }
+
+       tdb_unlock_bystring(tdb, "IDMAP_VERSION");
+       return True;
+}
+
+static BOOL tdbsam_new_rid(struct pdb_methods *methods, uint32 *prid)
+{
+       TDB_CONTEXT *tdb;
+       uint32 rid;
+       BOOL ret = False;
+
+       tdb = tdb_open_log(lock_path("winbindd_idmap.tdb"), 0,
+                          TDB_DEFAULT, O_RDWR | O_CREAT, 0644);
+
+       if (tdb == NULL) {
+               DEBUG(1, ("Could not open idmap: %s\n", strerror(errno)));
+               goto done;
+       }
+
+       if (!init_idmap_tdb(tdb)) {
+               DEBUG(1, ("Could not init idmap\n"));
+               goto done;
+       }
+
+       rid = BASE_RID;         /* Default if not set */
+
+       if (!tdb_change_uint32_atomic(tdb, "RID_COUNTER", &rid, 1)) {
+               DEBUG(3, ("tdbsam_new_rid: Failed to increase RID_COUNTER\n"));
+               goto done;
+       }
+
+       *prid = rid;
+       ret = True;
+
+ done:
+       if ((tdb != NULL) && (tdb_close(tdb) != 0)) {
+               smb_panic("tdb_close(idmap_tdb) failed\n");
+       }
+
+       return ret;
+}
+
 static void free_private_data(void **vp) 
 {
        struct tdbsam_privates **tdb_state = (struct tdbsam_privates **)vp;
@@ -908,6 +999,9 @@ static NTSTATUS pdb_init_tdbsam(PDB_CONTEXT *pdb_context, PDB_METHODS **pdb_meth
        (*pdb_method)->delete_sam_account = tdbsam_delete_sam_account;
        (*pdb_method)->rename_sam_account = tdbsam_rename_sam_account;
 
+       (*pdb_method)->rid_algorithm = tdbsam_rid_algorithm;
+       (*pdb_method)->new_rid = tdbsam_new_rid;
+
        tdb_state = TALLOC_ZERO_P(pdb_context->mem_ctx, struct tdbsam_privates);
 
        if (!tdb_state) {
index 88dabbd64433e2837df1551d9eda6b1e3c8aaf02..69bafc7ce5707c60180cea5fa468ce22ad5013de 100644 (file)
@@ -388,10 +388,11 @@ BOOL secrets_store_trust_account_password(const char *domain, uint8 new_pwd[16])
  * @return true if succeeded
  **/
 
-BOOL secrets_store_trusted_domain_password(const char* domain, smb_ucs2_t *uni_dom_name,
-                                           size_t uni_name_len, const char* pwd,
-                                           DOM_SID sid)
-{      
+BOOL secrets_store_trusted_domain_password(const char* domain, const char* pwd,
+                                           const DOM_SID *sid)
+{
+       smb_ucs2_t *uni_dom_name;
+
        /* packing structures */
        pstring pass_buf;
        int pass_len = 0;
@@ -399,13 +400,15 @@ BOOL secrets_store_trusted_domain_password(const char* domain, smb_ucs2_t *uni_d
        
        struct trusted_dom_pass pass;
        ZERO_STRUCT(pass);
-       
-       /* unicode domain name and its length */
-       if (!uni_dom_name)
+
+       if (push_ucs2_allocate(&uni_dom_name, domain) < 0) {
+               DEBUG(0, ("Could not convert domain name %s to unicode\n",
+                         domain));
                return False;
-               
+       }
+       
        strncpy_w(pass.uni_name, uni_dom_name, sizeof(pass.uni_name) - 1);
-       pass.uni_name_len = uni_name_len;
+       pass.uni_name_len = strlen_w(uni_dom_name)+1;
 
        /* last change time */
        pass.mod_time = time(NULL);
@@ -415,7 +418,7 @@ BOOL secrets_store_trusted_domain_password(const char* domain, smb_ucs2_t *uni_d
        fstrcpy(pass.pass, pwd);
 
        /* domain sid */
-       sid_copy(&pass.domain_sid, &sid);
+       sid_copy(&pass.domain_sid, sid);
        
        pass_len = tdb_trusted_dom_pass_pack(pass_buf, pass_buf_len, &pass);
 
@@ -658,138 +661,97 @@ BOOL fetch_ldap_pw(char **dn, char** pw)
 
 /**
  * Get trusted domains info from secrets.tdb.
- *
- * The linked list is allocated on the supplied talloc context, caller gets to destroy
- * when done.
- *
- * @param ctx Allocation context
- * @param enum_ctx Starting index, eg. we can start fetching at third
- *        or sixth trusted domain entry. Zero is the first index.
- *        Value it is set to is the enum context for the next enumeration.
- * @param num_domains Number of domain entries to fetch at one call
- * @param domains Pointer to array of trusted domain structs to be filled up
- *
- * @return nt status code of rpc response
  **/ 
 
-NTSTATUS secrets_get_trusted_domains(TALLOC_CTX* ctx, int* enum_ctx, unsigned int max_num_domains,
-                                     int *num_domains, TRUSTDOM ***domains)
+NTSTATUS secrets_trusted_domains(TALLOC_CTX *mem_ctx, uint32 *num_domains,
+                                struct trustdom_info ***domains)
 {
        TDB_LIST_NODE *keys, *k;
-       TRUSTDOM *dom = NULL;
        char *pattern;
-       unsigned int start_idx;
-       uint32 idx = 0;
-       size_t size = 0, packed_size = 0;
-       fstring dom_name;
-       char *packed_pass;
-       struct trusted_dom_pass *pass = TALLOC_ZERO_P(ctx, struct trusted_dom_pass);
-       NTSTATUS status;
 
        if (!secrets_init()) return NT_STATUS_ACCESS_DENIED;
        
-       if (!pass) {
-               DEBUG(0, ("talloc_zero failed!\n"));
-               return NT_STATUS_NO_MEMORY;
-       }
-                               
-       *num_domains = 0;
-       start_idx = *enum_ctx;
-
        /* generate searching pattern */
-       if (!(pattern = talloc_asprintf(ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS))) {
-               DEBUG(0, ("secrets_get_trusted_domains: talloc_asprintf() failed!\n"));
+       pattern = talloc_asprintf(mem_ctx, "%s/*", SECRETS_DOMTRUST_ACCT_PASS);
+       if (pattern == NULL) {
+               DEBUG(0, ("secrets_trusted_domains: talloc_asprintf() "
+                         "failed!\n"));
                return NT_STATUS_NO_MEMORY;
        }
 
-       DEBUG(5, ("secrets_get_trusted_domains: looking for %d domains, starting at index %d\n", 
-                 max_num_domains, *enum_ctx));
-
-       *domains = TALLOC_ZERO_ARRAY(ctx, TRUSTDOM *, max_num_domains);
+       *domains = NULL;
+       *num_domains = 0;
 
        /* fetching trusted domains' data and collecting them in a list */
        keys = tdb_search_keys(tdb, pattern);
 
-       /* 
-        * if there's no keys returned ie. no trusted domain,
-        * return "no more entries" code
-        */
-       status = NT_STATUS_NO_MORE_ENTRIES;
-
        /* searching for keys in secrets db -- way to go ... */
        for (k = keys; k; k = k->next) {
+               char *packed_pass;
+               size_t size = 0, packed_size = 0;
+               struct trusted_dom_pass pass;
                char *secrets_key;
+               struct trustdom_info *dom_info;
                
                /* important: ensure null-termination of the key string */
-               secrets_key = SMB_STRNDUP(k->node_key.dptr, k->node_key.dsize);
+               secrets_key = talloc_strndup(mem_ctx,
+                                            k->node_key.dptr,
+                                            k->node_key.dsize);
                if (!secrets_key) {
                        DEBUG(0, ("strndup failed!\n"));
                        return NT_STATUS_NO_MEMORY;
                }
 
                packed_pass = secrets_fetch(secrets_key, &size);
-               packed_size = tdb_trusted_dom_pass_unpack(packed_pass, size, pass);
+               packed_size = tdb_trusted_dom_pass_unpack(packed_pass, size,
+                                                         &pass);
                /* packed representation isn't needed anymore */
                SAFE_FREE(packed_pass);
                
                if (size != packed_size) {
-                       DEBUG(2, ("Secrets record %s is invalid!\n", secrets_key));
+                       DEBUG(2, ("Secrets record %s is invalid!\n",
+                                 secrets_key));
                        continue;
                }
-               
-               pull_ucs2_fstring(dom_name, pass->uni_name);
-               DEBUG(18, ("Fetched secret record num %d.\nDomain name: %s, SID: %s\n",
-                          idx, dom_name, sid_string_static(&pass->domain_sid)));
-
-               SAFE_FREE(secrets_key);
-
-               if (idx >= start_idx && idx < start_idx + max_num_domains) {
-                       dom = TALLOC_ZERO_P(ctx, TRUSTDOM);
-                       if (!dom) {
-                               /* free returned tdb record */
-                               return NT_STATUS_NO_MEMORY;
-                       }
-                       
-                       /* copy domain sid */
-                       SMB_ASSERT(sizeof(dom->sid) == sizeof(pass->domain_sid));
-                       memcpy(&(dom->sid), &(pass->domain_sid), sizeof(dom->sid));
-                       
-                       /* copy unicode domain name */
-                       dom->name = TALLOC_MEMDUP(ctx, pass->uni_name,
-                                                 (strlen_w(pass->uni_name) + 1) * sizeof(smb_ucs2_t));
-                       
-                       (*domains)[idx - start_idx] = dom;
-                       
-                       DEBUG(18, ("Secret record is in required range.\n \
-                                  start_idx = %d, max_num_domains = %d. Added to returned array.\n",
-                                  start_idx, max_num_domains));
 
-                       *enum_ctx = idx + 1;
-                       (*num_domains)++;
-               
-                       /* set proper status code to return */
-                       if (k->next) {
-                               /* there are yet some entries to enumerate */
-                               status = STATUS_MORE_ENTRIES;
-                       } else {
-                               /* this is the last entry in the whole enumeration */
-                               status = NT_STATUS_OK;
-                       }
-               } else {
-                       DEBUG(18, ("Secret is outside the required range.\n \
-                                  start_idx = %d, max_num_domains = %d. Not added to returned array\n",
-                                  start_idx, max_num_domains));
+               if (pass.domain_sid.num_auths != 4) {
+                       DEBUG(0, ("SID %s is not a domain sid, has %d "
+                                 "auths instead of 4\n",
+                                 sid_string_static(&pass.domain_sid),
+                                 pass.domain_sid.num_auths));
+                       continue;
                }
-               
-               idx++;          
+
+               dom_info = TALLOC_P(mem_ctx, struct trustdom_info);
+               if (dom_info == NULL) {
+                       DEBUG(0, ("talloc failed\n"));
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               if (pull_ucs2_talloc(mem_ctx, &dom_info->name,
+                                    pass.uni_name) < 0) {
+                       DEBUG(2, ("pull_ucs2_talloc failed\n"));
+                       return NT_STATUS_NO_MEMORY;
+               }
+
+               sid_copy(&dom_info->sid, &pass.domain_sid);
+
+               ADD_TO_ARRAY(mem_ctx, struct trustdom_info *, dom_info,
+                            domains, num_domains);
+
+               if (*domains == NULL) {
+                       return NT_STATUS_NO_MEMORY;
+               }
+               talloc_steal(*domains, dom_info);
        }
        
-       DEBUG(5, ("secrets_get_trusted_domains: got %d domains\n", *num_domains));
+       DEBUG(5, ("secrets_get_trusted_domains: got %d domains\n",
+                 *num_domains));
 
        /* free the results of searching the keys */
        tdb_search_list_free(keys);
 
-       return status;
+       return NT_STATUS_OK;
 }
 
 /*******************************************************************************
index 12a98d24ddb97a40ed6f46b087a04fb687351675..9c59df1f68743ff853c44e83aeb4de8010e92b79 100644 (file)
@@ -105,6 +105,6 @@ BOOL sid_check_is_in_builtin(const DOM_SID *sid)
        sid_copy(&dom_sid, sid);
        sid_split_rid(&dom_sid, &rid);
        
-       return sid_equal(&dom_sid, &global_sid_Builtin);
+       return sid_check_is_builtin(&dom_sid);
 }
 
diff --git a/source3/passdb/util_unixsids.c b/source3/passdb/util_unixsids.c
new file mode 100644 (file)
index 0000000..ee8cf2d
--- /dev/null
@@ -0,0 +1,94 @@
+/* 
+   Unix SMB/CIFS implementation.
+   Translate unix-defined names to SIDs and vice versa
+   Copyright (C) Volker Lendecke 2005
+      
+   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"
+
+BOOL sid_check_is_unix_users(const DOM_SID *sid)
+{
+       return sid_equal(sid, &global_sid_Unix_Users);
+}
+
+BOOL sid_check_is_in_unix_users(const DOM_SID *sid)
+{
+       DOM_SID dom_sid;
+       uint32 rid;
+
+       sid_copy(&dom_sid, sid);
+       sid_split_rid(&dom_sid, &rid);
+       
+       return sid_check_is_unix_users(&dom_sid);
+}
+
+const char *unix_users_domain_name(void)
+{
+       return "Unix User";
+}
+
+BOOL lookup_unix_user_name(const char *name, DOM_SID *sid)
+{
+       struct passwd *pwd;
+
+       pwd = getpwnam_alloc(NULL, name);
+       if (pwd == NULL) {
+               return False;
+       }
+
+       sid_copy(sid, &global_sid_Unix_Users);
+       sid_append_rid(sid, pwd->pw_uid); /* For 64-bit uid's we have enough
+                                         * space ... */
+       talloc_free(pwd);
+       return True;
+}
+
+BOOL sid_check_is_unix_groups(const DOM_SID *sid)
+{
+       return sid_equal(sid, &global_sid_Unix_Groups);
+}
+
+BOOL sid_check_is_in_unix_groups(const DOM_SID *sid)
+{
+       DOM_SID dom_sid;
+       uint32 rid;
+
+       sid_copy(&dom_sid, sid);
+       sid_split_rid(&dom_sid, &rid);
+       
+       return sid_check_is_unix_groups(&dom_sid);
+}
+
+const char *unix_groups_domain_name(void)
+{
+       return "Unix Group";
+}
+
+BOOL lookup_unix_group_name(const char *name, DOM_SID *sid)
+{
+       struct group *grp;
+
+       grp = getgrnam(name);
+       if (grp == NULL) {
+               return False;
+       }
+
+       sid_copy(sid, &global_sid_Unix_Groups);
+       sid_append_rid(sid, grp->gr_gid); /* For 64-bit uid's we have enough
+                                          * space ... */
+       return True;
+}
index 8caae3b2a01fe259bd92975cadb6977017352d4d..be3cf3744695005752c0c1f50b2817c8d9ba0246 100644 (file)
@@ -70,6 +70,21 @@ static struct sid_name_map_info special_domains[] = {
        { &global_sid_NT_Authority, "NT Authority", nt_authority_users },
        { NULL, NULL, NULL }};
 
+BOOL sid_check_is_wellknown_domain(const DOM_SID *sid, const char **name)
+{
+       int i;
+
+       for (i=0; special_domains[i].sid != NULL; i++) {
+               if (sid_equal(sid, special_domains[i].sid)) {
+                       if (name != NULL) {
+                               *name = special_domains[i].name;
+                       }
+                       return True;
+               }
+       }
+       return False;
+}
+
 /**************************************************************************
  Looks up a known username from one of the known domains.
 ***************************************************************************/
index a91c2a5c70b1a26fba2790a10ba7ee767c38fd3a..e6c6f7d3dc86b5862a7327b2aa63087305d85b26 100644 (file)
@@ -3140,7 +3140,11 @@ WERROR nt_printer_publish(Printer_entry *print_hnd, int snum, int action)
                win_rc = WERR_SERVER_UNAVAILABLE;
                goto done;
        }
+#ifdef HAVE_KCM
+       setenv(KRB5_ENV_CCNAME, "KCM:SYSTEM", 1);
+#else
        setenv(KRB5_ENV_CCNAME, "MEMORY:prtpub_cache", 1);
+#endif
        SAFE_FREE(ads->auth.password);
        ads->auth.password = secrets_fetch_machine_password(lp_workgroup(),
                NULL, NULL);
@@ -3545,7 +3549,7 @@ static void map_to_os2_driver(fstring drivername)
                return;
        }
 
-       lines = file_lines_load(mapfile, &numlines);
+       lines = file_lines_load(mapfile, &numlines,0);
        if (numlines == 0) {
                DEBUG(0,("No entries in OS/2 driver map %s\n",mapfile));
                return;
@@ -5326,9 +5330,11 @@ BOOL print_access_check(struct current_user *user, int snum, int access_type)
 
         /* see if we need to try the printer admin list */
 
-        if ( access_granted == 0 ) {
-                if ( user_in_list(uidtoname(user->ut.uid), lp_printer_admin(snum), user->ut.groups, user->ut.ngroups) )
-                        return True;
+        if ((access_granted == 0) &&
+           (token_contains_name_in_list(uidtoname(user->ut.uid), NULL,
+                                        user->nt_user_token,
+                                        lp_printer_admin(snum)))) {
+               return True;
         }
 
        talloc_destroy(mem_ctx);
index b2484d5b433245552af6f3d57f4f640dc4dd1252..18fca67860098be0c5c4285dd0657406e40fb6f3 100644 (file)
@@ -187,7 +187,7 @@ static int generic_queue_get(const char *printer_name,
        }
        
        numlines = 0;
-       qlines = fd_lines_load(fd, &numlines);
+       qlines = fd_lines_load(fd, &numlines,0);
        close(fd);
 
        /* turn the lpq output into a series of job structures */
index 4f809520bc3a878270edb4d2ead45e3191bb26c8..a4e8254e0d15b072081598345bb0d126cd89e514 100644 (file)
@@ -186,8 +186,8 @@ static PyObject *lsa_lookup_names(PyObject *self, PyObject *args)
        }
 
        ntstatus = rpccli_lsa_lookup_names(
-               hnd->cli, mem_ctx, &hnd->pol, num_names, names, &sids, 
-               &name_types);
+               hnd->cli, mem_ctx, &hnd->pol, num_names, names, 
+               NULL, &sids, &name_types);
 
        if (!NT_STATUS_IS_OK(ntstatus) && NT_STATUS_V(ntstatus) != 0x107) {
                PyErr_SetObject(lsa_ntstatus, py_ntstatus_tuple(ntstatus));
index 78df220ac2a3ecdbf7ac1ac3a8303cb49ea462c2..8b94d6ed9d4ac11a3c71f2023dcbc401f46a4f21 100644 (file)
-/* 
-   Unix SMB/CIFS implementation.
-   RPC pipe client
-   Copyright (C) Tim Potter                        2000-2001,
-   Copyright (C) Jeremy Allison                                2005.
-   
-   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.
-*/
+/*
+ * Unix SMB/CIFS implementation.
+ * client auto-generated by pidl. DO NOT MODIFY!
+ */
 
 #include "includes.h"
 
-/* Query DFS support */
-
-NTSTATUS rpccli_dfs_exist(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
-                       BOOL *dfs_exists)
+NTSTATUS rpccli_dfs_GetManagerVersion(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 *exist_flag)
 {
        prs_struct qbuf, rbuf;
-       DFS_Q_DFS_EXIST q;
-       DFS_R_DFS_EXIST r;
-       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-
+       NETDFS_Q_DFS_GETMANAGERVERSION q;
+       NETDFS_R_DFS_GETMANAGERVERSION r;
+       
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
-
+       
        /* Marshall data and send request */
-
-        init_dfs_q_dfs_exist(&q);
-
-       CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_EXIST,
+       
+       if (!init_netdfs_q_dfs_GetManagerVersion(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_GETMANAGERVERSION,
                q, r,
-               qbuf, rbuf,
-               dfs_io_q_dfs_exist,
-               dfs_io_r_dfs_exist,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_GetManagerVersion,
+               netdfs_io_r_dfs_GetManagerVersion,
                NT_STATUS_UNSUCCESSFUL);
-
+       
+       /* Return variables */
+       *exist_flag = r.exist_flag;
+       
        /* Return result */
-
-       *dfs_exists = (r.status != 0);
-
-       result = NT_STATUS_OK;
-
-       return result;
+       return NT_STATUS_OK;
 }
 
-NTSTATUS rpccli_dfs_add(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
-                     const char *entrypath, const char *servername, 
-                    const char *sharename, const char *comment, uint32 flags)
+NTSTATUS rpccli_dfs_Add(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *path, const char *server, const char *share, const char *comment, uint32 flags)
 {
        prs_struct qbuf, rbuf;
-       DFS_Q_DFS_ADD q;
-       DFS_R_DFS_ADD r;
-       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-
+       NETDFS_Q_DFS_ADD q;
+       NETDFS_R_DFS_ADD r;
+       
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
-
+       
        /* Marshall data and send request */
-
-        init_dfs_q_dfs_add(&q, entrypath, servername, sharename, comment,
-                          flags);
-
-       CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_ADD,
+       
+       if (!init_netdfs_q_dfs_Add(&q, path, server, share, comment, flags))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_ADD,
                q, r,
-               qbuf, rbuf,
-               dfs_io_q_dfs_add,
-               dfs_io_r_dfs_add,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_Add,
+               netdfs_io_r_dfs_Add,
                NT_STATUS_UNSUCCESSFUL);
-
+       
+       /* Return variables */
+       
        /* Return result */
-
-        result = werror_to_ntstatus(r.status);
-
-       return result;
+       return werror_to_ntstatus(r.status);
 }
 
-NTSTATUS rpccli_dfs_remove(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
-                        const char *entrypath, const char *servername, 
-                       const char *sharename)
+NTSTATUS rpccli_dfs_Remove(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *path, const char *server, const char *share)
 {
        prs_struct qbuf, rbuf;
-       DFS_Q_DFS_REMOVE q;
-       DFS_R_DFS_REMOVE r;
-       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
-
+       NETDFS_Q_DFS_REMOVE q;
+       NETDFS_R_DFS_REMOVE r;
+       
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
-
+       
        /* Marshall data and send request */
-
-        init_dfs_q_dfs_remove(&q, entrypath, servername, sharename);
-
-       CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_REMOVE,
+       
+       if (!init_netdfs_q_dfs_Remove(&q, path, server, share))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_REMOVE,
                q, r,
-               qbuf, rbuf,
-               dfs_io_q_dfs_remove,
-               dfs_io_r_dfs_remove,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_Remove,
+               netdfs_io_r_dfs_Remove,
                NT_STATUS_UNSUCCESSFUL);
-
+       
+       /* Return variables */
+       
        /* Return result */
+       return werror_to_ntstatus(r.status);
+}
 
-       result = werror_to_ntstatus(r.status);
+NTSTATUS rpccli_dfs_SetInfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+       prs_struct qbuf, rbuf;
+       NETDFS_Q_DFS_SETINFO q;
+       NETDFS_R_DFS_SETINFO r;
+       
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+       
+       /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_SetInfo(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_SETINFO,
+               q, r,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_SetInfo,
+               netdfs_io_r_dfs_SetInfo,
+               NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       
+       /* Return result */
+       return werror_to_ntstatus(r.status);
+}
 
-       return result;
+NTSTATUS rpccli_dfs_GetInfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *path, const char *server, const char *share, uint32 level, NETDFS_DFS_INFO_CTR *info)
+{
+       prs_struct qbuf, rbuf;
+       NETDFS_Q_DFS_GETINFO q;
+       NETDFS_R_DFS_GETINFO r;
+       
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+       
+       /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_GetInfo(&q, path, server, share, level))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_GETINFO,
+               q, r,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_GetInfo,
+               netdfs_io_r_dfs_GetInfo,
+               NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       *info = r.info;
+       
+       /* Return result */
+       return werror_to_ntstatus(r.status);
 }
 
-NTSTATUS rpccli_dfs_get_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
-                          const char *entrypath, const char *servername, 
-                         const char *sharename, uint32 info_level, 
-                         DFS_INFO_CTR *ctr)
+NTSTATUS rpccli_dfs_Enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 level, uint32 bufsize, NETDFS_DFS_ENUMSTRUCT *info, uint32 *unknown, uint32 *total)
+{
+       prs_struct qbuf, rbuf;
+       NETDFS_Q_DFS_ENUM q;
+       NETDFS_R_DFS_ENUM r;
+       
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+       
+       /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_Enum(&q, level, bufsize, info, unknown, total))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_ENUM,
+               q, r,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_Enum,
+               netdfs_io_r_dfs_Enum,
+               NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       *info = r.info;
+       *total = r.total;
+       
+       /* Return result */
+       return werror_to_ntstatus(r.status);
+}
 
+NTSTATUS rpccli_dfs_Rename(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
 {
        prs_struct qbuf, rbuf;
-       DFS_Q_DFS_GET_INFO q;
-       DFS_R_DFS_GET_INFO r;
-       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       NETDFS_Q_DFS_RENAME q;
+       NETDFS_R_DFS_RENAME r;
+       
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+       
+       /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_Rename(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_RENAME,
+               q, r,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_Rename,
+               netdfs_io_r_dfs_Rename,
+               NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       
+       /* Return result */
+       return werror_to_ntstatus(r.status);
+}
 
+NTSTATUS rpccli_dfs_Move(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+       prs_struct qbuf, rbuf;
+       NETDFS_Q_DFS_MOVE q;
+       NETDFS_R_DFS_MOVE r;
+       
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
+       
+       /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_Move(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_MOVE,
+               q, r,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_Move,
+               netdfs_io_r_dfs_Move,
+               NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       
+       /* Return result */
+       return werror_to_ntstatus(r.status);
+}
 
+NTSTATUS rpccli_dfs_ManagerGetConfigInfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+       prs_struct qbuf, rbuf;
+       NETDFS_Q_DFS_MANAGERGETCONFIGINFO q;
+       NETDFS_R_DFS_MANAGERGETCONFIGINFO r;
+       
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+       
        /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_ManagerGetConfigInfo(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_MANAGERGETCONFIGINFO,
+               q, r,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_ManagerGetConfigInfo,
+               netdfs_io_r_dfs_ManagerGetConfigInfo,
+               NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       
+       /* Return result */
+       return werror_to_ntstatus(r.status);
+}
 
-        init_dfs_q_dfs_get_info(&q, entrypath, servername, sharename,
-                               info_level);
+NTSTATUS rpccli_dfs_ManagerSendSiteInfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+       prs_struct qbuf, rbuf;
+       NETDFS_Q_DFS_MANAGERSENDSITEINFO q;
+       NETDFS_R_DFS_MANAGERSENDSITEINFO r;
+       
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+       
+       /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_ManagerSendSiteInfo(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_MANAGERSENDSITEINFO,
+               q, r,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_ManagerSendSiteInfo,
+               netdfs_io_r_dfs_ManagerSendSiteInfo,
+               NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       
+       /* Return result */
+       return werror_to_ntstatus(r.status);
+}
 
-       CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_GET_INFO,
+NTSTATUS rpccli_dfs_AddFtRoot(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+       prs_struct qbuf, rbuf;
+       NETDFS_Q_DFS_ADDFTROOT q;
+       NETDFS_R_DFS_ADDFTROOT r;
+       
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+       
+       /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_AddFtRoot(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_ADDFTROOT,
                q, r,
-               qbuf, rbuf,
-               dfs_io_q_dfs_get_info,
-               dfs_io_r_dfs_get_info,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_AddFtRoot,
+               netdfs_io_r_dfs_AddFtRoot,
                NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       
+       /* Return result */
+       return werror_to_ntstatus(r.status);
+}
 
+NTSTATUS rpccli_dfs_RemoveFtRoot(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+       prs_struct qbuf, rbuf;
+       NETDFS_Q_DFS_REMOVEFTROOT q;
+       NETDFS_R_DFS_REMOVEFTROOT r;
+       
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+       
+       /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_RemoveFtRoot(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_REMOVEFTROOT,
+               q, r,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_RemoveFtRoot,
+               netdfs_io_r_dfs_RemoveFtRoot,
+               NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       
        /* Return result */
+       return werror_to_ntstatus(r.status);
+}
 
-       result = werror_to_ntstatus(r.status);
-       *ctr = r.ctr;
+NTSTATUS rpccli_dfs_AddStdRoot(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+       prs_struct qbuf, rbuf;
+       NETDFS_Q_DFS_ADDSTDROOT q;
+       NETDFS_R_DFS_ADDSTDROOT r;
+       
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
        
-       return result;
+       /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_AddStdRoot(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_ADDSTDROOT,
+               q, r,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_AddStdRoot,
+               netdfs_io_r_dfs_AddStdRoot,
+               NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       
+       /* Return result */
+       return werror_to_ntstatus(r.status);
 }
 
-/* Enumerate dfs shares */
+NTSTATUS rpccli_dfs_RemoveStdRoot(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+       prs_struct qbuf, rbuf;
+       NETDFS_Q_DFS_REMOVESTDROOT q;
+       NETDFS_R_DFS_REMOVESTDROOT r;
+       
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+       
+       /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_RemoveStdRoot(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_REMOVESTDROOT,
+               q, r,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_RemoveStdRoot,
+               netdfs_io_r_dfs_RemoveStdRoot,
+               NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       
+       /* Return result */
+       return werror_to_ntstatus(r.status);
+}
 
-NTSTATUS rpccli_dfs_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
-                      uint32 info_level, DFS_INFO_CTR *ctr)
+NTSTATUS rpccli_dfs_ManagerInitialize(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
 {
        prs_struct qbuf, rbuf;
-       DFS_Q_DFS_ENUM q;
-       DFS_R_DFS_ENUM r;
-        NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       NETDFS_Q_DFS_MANAGERINITIALIZE q;
+       NETDFS_R_DFS_MANAGERINITIALIZE r;
+       
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+       
+       /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_ManagerInitialize(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_MANAGERINITIALIZE,
+               q, r,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_ManagerInitialize,
+               netdfs_io_r_dfs_ManagerInitialize,
+               NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       
+       /* Return result */
+       return werror_to_ntstatus(r.status);
+}
 
+NTSTATUS rpccli_dfs_AddStdRootForced(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+       prs_struct qbuf, rbuf;
+       NETDFS_Q_DFS_ADDSTDROOTFORCED q;
+       NETDFS_R_DFS_ADDSTDROOTFORCED r;
+       
        ZERO_STRUCT(q);
        ZERO_STRUCT(r);
+       
+       /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_AddStdRootForced(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_ADDSTDROOTFORCED,
+               q, r,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_AddStdRootForced,
+               netdfs_io_r_dfs_AddStdRootForced,
+               NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       
+       /* Return result */
+       return werror_to_ntstatus(r.status);
+}
 
+NTSTATUS rpccli_dfs_GetDcAddress(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+       prs_struct qbuf, rbuf;
+       NETDFS_Q_DFS_GETDCADDRESS q;
+       NETDFS_R_DFS_GETDCADDRESS r;
+       
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+       
        /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_GetDcAddress(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_GETDCADDRESS,
+               q, r,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_GetDcAddress,
+               netdfs_io_r_dfs_GetDcAddress,
+               NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       
+       /* Return result */
+       return werror_to_ntstatus(r.status);
+}
 
-        init_dfs_q_dfs_enum(&q, info_level, ctr);
+NTSTATUS rpccli_dfs_SetDcAddress(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+       prs_struct qbuf, rbuf;
+       NETDFS_Q_DFS_SETDCADDRESS q;
+       NETDFS_R_DFS_SETDCADDRESS r;
+       
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+       
+       /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_SetDcAddress(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_SETDCADDRESS,
+               q, r,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_SetDcAddress,
+               netdfs_io_r_dfs_SetDcAddress,
+               NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       
+       /* Return result */
+       return werror_to_ntstatus(r.status);
+}
 
-       r.ctr = ctr;
+NTSTATUS rpccli_dfs_FlushFtTable(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+       prs_struct qbuf, rbuf;
+       NETDFS_Q_DFS_FLUSHFTTABLE q;
+       NETDFS_R_DFS_FLUSHFTTABLE r;
+       
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+       
+       /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_FlushFtTable(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_FLUSHFTTABLE,
+               q, r,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_FlushFtTable,
+               netdfs_io_r_dfs_FlushFtTable,
+               NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       
+       /* Return result */
+       return werror_to_ntstatus(r.status);
+}
 
-       CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_ENUM,
+NTSTATUS rpccli_dfs_Add2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+       prs_struct qbuf, rbuf;
+       NETDFS_Q_DFS_ADD2 q;
+       NETDFS_R_DFS_ADD2 r;
+       
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+       
+       /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_Add2(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_ADD2,
                q, r,
-               qbuf, rbuf,
-               dfs_io_q_dfs_enum,
-               dfs_io_r_dfs_enum,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_Add2,
+               netdfs_io_r_dfs_Add2,
                NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       
+       /* Return result */
+       return werror_to_ntstatus(r.status);
+}
 
+NTSTATUS rpccli_dfs_Remove2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+       prs_struct qbuf, rbuf;
+       NETDFS_Q_DFS_REMOVE2 q;
+       NETDFS_R_DFS_REMOVE2 r;
+       
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+       
+       /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_Remove2(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_REMOVE2,
+               q, r,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_Remove2,
+               netdfs_io_r_dfs_Remove2,
+               NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       
        /* Return result */
+       return werror_to_ntstatus(r.status);
+}
 
-       result = werror_to_ntstatus(r.status);
+NTSTATUS rpccli_dfs_EnumEx(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+       prs_struct qbuf, rbuf;
+       NETDFS_Q_DFS_ENUMEX q;
+       NETDFS_R_DFS_ENUMEX r;
+       
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+       
+       /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_EnumEx(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_ENUMEX,
+               q, r,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_EnumEx,
+               netdfs_io_r_dfs_EnumEx,
+               NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       
+       /* Return result */
+       return werror_to_ntstatus(r.status);
+}
 
-       return result;
+NTSTATUS rpccli_dfs_SetInfo2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx)
+{
+       prs_struct qbuf, rbuf;
+       NETDFS_Q_DFS_SETINFO2 q;
+       NETDFS_R_DFS_SETINFO2 r;
+       
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+       
+       /* Marshall data and send request */
+       
+       if (!init_netdfs_q_dfs_SetInfo2(&q))
+               return NT_STATUS_INVALID_PARAMETER;
+       
+       CLI_DO_RPC(cli, mem_ctx, PI_NETDFS, DFS_SETINFO2,
+               q, r,
+               qbuf, rbuf, 
+               netdfs_io_q_dfs_SetInfo2,
+               netdfs_io_r_dfs_SetInfo2,
+               NT_STATUS_UNSUCCESSFUL);
+       
+       /* Return variables */
+       
+       /* Return result */
+       return werror_to_ntstatus(r.status);
 }
+
index aa1cb95fda14ea0067ad399d8dc89f1936f396d7..9331d090931ee89809bc9b8b799725080ee522a5 100644 (file)
@@ -277,7 +277,9 @@ NTSTATUS rpccli_lsa_lookup_sids(struct rpc_pipe_client *cli,
 NTSTATUS rpccli_lsa_lookup_names(struct rpc_pipe_client *cli,
                                 TALLOC_CTX *mem_ctx,
                                 POLICY_HND *pol, int num_names, 
-                                const char **names, DOM_SID **sids, 
+                                const char **names,
+                                const char ***dom_names,
+                                DOM_SID **sids,
                                 uint32 **types)
 {
        prs_struct qbuf, rbuf;
@@ -331,6 +333,15 @@ NTSTATUS rpccli_lsa_lookup_names(struct rpc_pipe_client *cli,
                goto done;
        }
 
+       if (dom_names != NULL) {
+               *dom_names = TALLOC_ARRAY(mem_ctx, const char *, num_names);
+               if (*dom_names == NULL) {
+                       DEBUG(0, ("cli_lsa_lookup_sids(): out of memory\n"));
+                       result = NT_STATUS_NO_MEMORY;
+                       goto done;
+               }
+       }
+
        for (i = 0; i < num_names; i++) {
                DOM_RID2 *t_rids = r.dom_rid;
                uint32 dom_idx = t_rids[i].rid_idx;
@@ -339,19 +350,27 @@ NTSTATUS rpccli_lsa_lookup_names(struct rpc_pipe_client *cli,
 
                /* Translate optimised sid through domain index array */
 
-               if (dom_idx != 0xffffffff) {
+               if (dom_idx == 0xffffffff) {
+                       /* Nothing to do, this is unknown */
+                       ZERO_STRUCTP(sid);
+                       (*types)[i] = SID_NAME_UNKNOWN;
+                       continue;
+               }
 
-                       sid_copy(sid, &ref.ref_dom[dom_idx].ref_dom.sid);
+               sid_copy(sid, &ref.ref_dom[dom_idx].ref_dom.sid);
 
-                       if (dom_rid != 0xffffffff) {
-                               sid_append_rid(sid, dom_rid);
-                       }
+               if (dom_rid != 0xffffffff) {
+                       sid_append_rid(sid, dom_rid);
+               }
 
-                       (*types)[i] = t_rids[i].type;
-               } else {
-                       ZERO_STRUCTP(sid);
-                       (*types)[i] = SID_NAME_UNKNOWN;
+               (*types)[i] = t_rids[i].type;
+
+               if (dom_names == NULL) {
+                       continue;
                }
+
+               (*dom_names)[i] = rpcstr_pull_unistr2_talloc(
+                       *dom_names, &ref.ref_dom[dom_idx].uni_dom_name);
        }
 
  done:
@@ -1298,6 +1317,42 @@ done:
        return result;
 }
 
+NTSTATUS rpccli_lsa_open_trusted_domain_by_name(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                                               POLICY_HND *pol, const char *name, uint32 access_mask,
+                                               POLICY_HND *trustdom_pol)
+{
+       prs_struct qbuf, rbuf;
+       LSA_Q_OPEN_TRUSTED_DOMAIN_BY_NAME q;
+       LSA_R_OPEN_TRUSTED_DOMAIN_BY_NAME r;
+       NTSTATUS result;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Initialise input parameters */
+
+       init_lsa_q_open_trusted_domain_by_name(&q, pol, name, access_mask);
+
+       /* Marshall data and send request */
+
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_OPENTRUSTDOMBYNAME,
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_open_trusted_domain_by_name,
+               lsa_io_r_open_trusted_domain_by_name,
+               NT_STATUS_UNSUCCESSFUL);
+
+       /* Return output parameters */
+       
+       result = r.status;
+
+       if (NT_STATUS_IS_OK(result)) {
+               *trustdom_pol = r.handle;
+       }
+
+       return result;
+}
+
 
 NTSTATUS rpccli_lsa_query_trusted_domain_info_by_sid(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                                  POLICY_HND *pol, 
@@ -1372,3 +1427,39 @@ done:
        
        return result;
 }
+
+NTSTATUS cli_lsa_query_domain_info_policy(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
+                                         POLICY_HND *pol, 
+                                         uint16 info_class, LSA_DOM_INFO_UNION **info)
+{
+       prs_struct qbuf, rbuf;
+       LSA_Q_QUERY_DOM_INFO_POLICY q;
+       LSA_R_QUERY_DOM_INFO_POLICY r;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+
+       ZERO_STRUCT(q);
+       ZERO_STRUCT(r);
+
+       /* Marshall data and send request */
+
+       init_q_query_dom_info(&q, pol, info_class); 
+
+       CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_QUERYDOMINFOPOL, 
+               q, r,
+               qbuf, rbuf,
+               lsa_io_q_query_dom_info,
+               lsa_io_r_query_dom_info,
+               NT_STATUS_UNSUCCESSFUL);
+
+       result = r.status;
+
+       if (!NT_STATUS_IS_OK(result)) {
+               goto done;
+       }
+
+       *info = r.info;
+
+done:
+       return result;
+}
+
index b5addf3375167d554e4601ac55c2252ebc7b484b..3dc26f61c9394834a1bf3175002ff58307fe7b83 100644 (file)
@@ -468,8 +468,8 @@ WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
 
        if (dc_unc != NULL) {
                char *tmp;
-               if (rpcstr_pull_unistr2_talloc(mem_ctx, &tmp,
-                                              &r.uni_dc_unc) < 0) {
+               tmp = rpcstr_pull_unistr2_talloc(mem_ctx, &r.uni_dc_unc);
+               if (tmp == NULL) {
                        return WERR_GENERAL_FAILURE;
                }
                if (*tmp == '\\') tmp += 1;
@@ -485,8 +485,8 @@ WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
 
        if (dc_address != NULL) {
                char *tmp;
-               if (rpcstr_pull_unistr2_talloc(mem_ctx, &tmp,
-                                              &r.uni_dc_address) < 0) {
+               tmp = rpcstr_pull_unistr2_talloc(mem_ctx, &r.uni_dc_address);
+               if (tmp == NULL) {
                        return WERR_GENERAL_FAILURE;
                }
                if (*tmp == '\\') tmp += 1;
@@ -509,14 +509,14 @@ WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
        }
 
        if ((domain_name_out != NULL) &&
-           (rpcstr_pull_unistr2_talloc(mem_ctx, domain_name_out,
-                                       &r.uni_domain_name) < 1)) {
+           ((*domain_name_out = rpcstr_pull_unistr2_talloc(
+                   mem_ctx, &r.uni_domain_name)) == NULL)) {
                return WERR_GENERAL_FAILURE;
        }
 
        if ((forest_name != NULL) &&
-           (rpcstr_pull_unistr2_talloc(mem_ctx, forest_name,
-                                       &r.uni_forest_name) < 1)) {
+           ((*forest_name = rpcstr_pull_unistr2_talloc(
+                     mem_ctx, &r.uni_forest_name)) == NULL)) {
                return WERR_GENERAL_FAILURE;
        }
 
@@ -525,14 +525,14 @@ WERROR rpccli_netlogon_dsr_getdcname(struct rpc_pipe_client *cli,
        }
 
        if ((dc_site_name != NULL) &&
-           (rpcstr_pull_unistr2_talloc(mem_ctx, dc_site_name,
-                                       &r.uni_dc_site_name) < 1)) {
+           ((*dc_site_name = rpcstr_pull_unistr2_talloc(
+                     mem_ctx, &r.uni_dc_site_name)) == NULL)) {
                return WERR_GENERAL_FAILURE;
        }
 
        if ((client_site_name != NULL) &&
-           (rpcstr_pull_unistr2_talloc(mem_ctx, client_site_name,
-                                       &r.uni_client_site_name) < 1)) {
+           ((*client_site_name = rpcstr_pull_unistr2_talloc(
+                     mem_ctx, &r.uni_client_site_name)) == NULL)) {
                return WERR_GENERAL_FAILURE;
        }
 
@@ -571,8 +571,8 @@ WERROR rpccli_netlogon_dsr_getsitename(struct rpc_pipe_client *cli,
        }
 
        if ((site_name != NULL) &&
-           (rpcstr_pull_unistr2_talloc(mem_ctx, site_name,
-                                       &r.uni_site_name) < 1)) {
+           ((*site_name = rpcstr_pull_unistr2_talloc(
+                     mem_ctx, &r.uni_site_name)) == NULL)) {
                return WERR_GENERAL_FAILURE;
        }
 
index 23c66acf26ec9e2dd8e2e78df0da494602af93ca..9cc350bef1b2bdd992ce042dd97b7fc8b5927cdf 100644 (file)
@@ -927,7 +927,7 @@ static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli,
        /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */
 
        ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt,
-                       &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED);
+                       &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED, NULL);
 
        if (ret) {
                DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s "
@@ -2699,7 +2699,7 @@ struct rpc_pipe_client *cli_rpc_pipe_open_krb5(struct cli_state *cli,
 
        /* Only get a new TGT if username/password are given. */
        if (username && password) {
-               int ret = kerberos_kinit_password(username, password, 0, NULL, NULL);
+               int ret = kerberos_kinit_password(username, password, 0, NULL, NULL, NULL, False, 0);
                if (ret) {
                        cli_rpc_pipe_close(result);
                        return NULL;
@@ -2737,7 +2737,7 @@ struct rpc_pipe_client *cli_rpc_pipe_open_krb5(struct cli_state *cli,
  Close an open named pipe over SMB. Free any authentication data.
  ****************************************************************************/
 
-void cli_rpc_pipe_close(struct rpc_pipe_client *cli)
+ void cli_rpc_pipe_close(struct rpc_pipe_client *cli)
 {
        if (!cli_close(cli->cli, cli->fnum)) {
                DEBUG(0,("cli_rpc_pipe_close: cli_close failed on pipe %s "
index fb95da97aefe23f2073339e743c4e772ed5c31bc..744d8174a0a0e5a167fdb555cf5b2bcf1ebb65a8 100644 (file)
@@ -360,7 +360,8 @@ NTSTATUS rpccli_samr_del_groupmem(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
 
 NTSTATUS rpccli_samr_query_userinfo(struct rpc_pipe_client *cli,
                                    TALLOC_CTX *mem_ctx,
-                                   POLICY_HND *user_pol, uint16 switch_value, 
+                                   const POLICY_HND *user_pol,
+                                   uint16 switch_value, 
                                    SAM_USERINFO_CTR **ctr)
 {
        prs_struct qbuf, rbuf;
@@ -1549,7 +1550,7 @@ NTSTATUS rpccli_samr_create_dom_user(struct rpc_pipe_client *cli, TALLOC_CTX *me
 /* Set userinfo */
 
 NTSTATUS rpccli_samr_set_userinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
-                               POLICY_HND *user_pol, uint16 switch_value,
+                               const POLICY_HND *user_pol, uint16 switch_value,
                                DATA_BLOB *sess_key, SAM_USERINFO_CTR *ctr)
 {
        prs_struct qbuf, rbuf;
@@ -1600,7 +1601,7 @@ NTSTATUS rpccli_samr_set_userinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_c
 /* Set userinfo2 */
 
 NTSTATUS rpccli_samr_set_userinfo2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, 
-                                POLICY_HND *user_pol, uint16 switch_value,
+                                  const POLICY_HND *user_pol, uint16 switch_value,
                                 DATA_BLOB *sess_key, SAM_USERINFO_CTR *ctr)
 {
        prs_struct qbuf, rbuf;
index f102e950042be73287d1299458561c45bf33d873..f1d070530250b881a6db07d61a959ae227b18a9c 100644 (file)
@@ -1,24 +1,6 @@
-/* 
- *  Unix SMB/CIFS implementation.
- *  MSDfs RPC Pipe client / server routines
- *  Copyright (C) Andrew Tridgell              1992-2000,
- *  Copyright (C) Luke Kenneth Casson Leighton 1996-2000,
- *  Copyright (C) Shirish Kalele               2000.
- *  Copyright (C) Jeremy Allison                               2001.
- *  
- *  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.
+/*
+ * Unix SMB/CIFS implementation.
+ * parser auto-generated by pidl. DO NOT MODIFY!
  */
 
 #include "includes.h"
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_PARSE
 
-/******************************************************************* 
-Make a DFS_Q_DFS_QUERY structure
-*******************************************************************/
-
-void init_dfs_q_dfs_exist(DFS_Q_DFS_EXIST *q_d)
+/* netdfs structures */
+BOOL init_netdfs_dfs_Info0(NETDFS_DFS_INFO0 *v)
 {
-       q_d->dummy = 0;
+       DEBUG(5,("init_netdfs_dfs_Info0\n"));
+       
+       return True;
 }
 
-/*************************************************************
- Read/write a DFS_Q_DFS_EXIST structure - dummy...
- ************************************************************/
+BOOL netdfs_io_dfs_Info0_p(const char *desc, NETDFS_DFS_INFO0 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info0_p");
+       depth++;
+       return True;
+}
 
-BOOL dfs_io_q_dfs_exist(const char *desc, DFS_Q_DFS_EXIST *q_d, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_Info0_d(const char *desc, NETDFS_DFS_INFO0 *v, prs_struct *ps, int depth)
 {
-       if(q_d == NULL)
+       if (v == NULL)
                return False;
-  
-       prs_debug(ps, depth, desc, "dfs_io_q_dfs_exist");
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info0_d");
+       depth++;
+       return True;
+}
 
+BOOL init_netdfs_dfs_Info1(NETDFS_DFS_INFO1 *v, const char *path)
+{
+       DEBUG(5,("init_netdfs_dfs_Info1\n"));
+       
+       if (path) {
+               v->ptr0_path = 1;
+               init_unistr2(&v->path, path, UNI_FLAGS_NONE);
+       } else {
+               v->ptr0_path = 0;
+       }
+       
        return True;
 }
-  
-/*************************************************************
- Read/write a DFS_R_DFS_EXIST structure
- ************************************************************/
 
-BOOL dfs_io_r_dfs_exist(const char *desc, DFS_R_DFS_EXIST *q_d, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_Info1_p(const char *desc, NETDFS_DFS_INFO1 *v, prs_struct *ps, int depth)
 {
-       if(q_d == NULL)
+       if (v == NULL)
                return False;
-  
-       prs_debug(ps, depth, desc, "dfs_io_r_dfs_exist");
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info1_p");
        depth++;
-
-       if(!prs_align(ps))
+       if (!prs_uint32("ptr0_path", ps, depth, &v->ptr0_path))
                return False;
+       
+       
+       return True;
+}
 
-       if(!prs_uint32("exist flag", ps, 0, &q_d->status))
+BOOL netdfs_io_dfs_Info1_d(const char *desc, NETDFS_DFS_INFO1 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
                return False;
-
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info1_d");
+       depth++;
+       if (v->ptr0_path) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!smb_io_unistr2("path", &v->path, 1, ps, depth))
+                       return False;
+       }
+       
        return True;
 }
-  
-/******************************************************************* 
-Make a DFS_Q_DFS_REMOVE structure
-*******************************************************************/
 
-BOOL init_dfs_q_dfs_remove(DFS_Q_DFS_REMOVE *q_d, const char *entrypath, 
-                          const char *servername, const char *sharename)
+BOOL init_netdfs_dfs_Info2(NETDFS_DFS_INFO2 *v, const char *path, const char *comment, uint32 state, uint32 num_stores)
 {
-       DEBUG(5,("init_dfs_q_dfs_remove\n"));
-       init_unistr2(&q_d->DfsEntryPath, entrypath, UNI_STR_TERMINATE);
-       init_unistr2(&q_d->ServerName, servername, UNI_STR_TERMINATE);
-       init_unistr2(&q_d->ShareName, sharename, UNI_STR_TERMINATE);
-       q_d->ptr_ServerName = q_d->ptr_ShareName = 1;
+       DEBUG(5,("init_netdfs_dfs_Info2\n"));
+       
+       if (path) {
+               v->ptr0_path = 1;
+               init_unistr2(&v->path, path, UNI_FLAGS_NONE);
+       } else {
+               v->ptr0_path = 0;
+       }
+       
+       if (comment) {
+               v->ptr0_comment = 1;
+               init_unistr2(&v->comment, comment, UNI_FLAGS_NONE);
+       } else {
+               v->ptr0_comment = 0;
+       }
+       
+       v->state = state;
+       
+       v->num_stores = num_stores;
+       
        return True;
 }
 
-/******************************************************************* 
-Read/write a DFS_Q_DFS_REMOVE structure
-*******************************************************************/
-
-BOOL dfs_io_q_dfs_remove(const char *desc, DFS_Q_DFS_REMOVE *q_d, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_Info2_p(const char *desc, NETDFS_DFS_INFO2 *v, prs_struct *ps, int depth)
 {
-       if(q_d == NULL)
+       if (v == NULL)
                return False;
-
-       prs_debug(ps, depth, desc, "dfs_io_q_dfs_remove");
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info2_p");
        depth++;
-  
-       if(!prs_align(ps))
-               return False;
-  
-       if(!smb_io_unistr2("DfsEntryPath",&q_d->DfsEntryPath, 1, ps, depth))
-               return False;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!prs_uint32("ptr_ServerName", ps, depth, &q_d->ptr_ServerName))
+       if (!prs_uint32("ptr0_path", ps, depth, &v->ptr0_path))
                return False;
-       if(q_d->ptr_ServerName)
-               if (!smb_io_unistr2("ServerName",&q_d->ServerName, q_d->ptr_ServerName, ps, depth))
-                       return False;
-       if(!prs_align(ps))
+       
+       
+       if (!prs_uint32("ptr0_comment", ps, depth, &v->ptr0_comment))
                return False;
-
-       if(!prs_uint32("ptr_ShareName", ps, depth, &q_d->ptr_ShareName))
+       
+       
+       if (!prs_uint32("state", ps, depth, &v->state))
                return False;
-       if(q_d->ptr_ShareName)
-               if (!smb_io_unistr2("ShareName",&q_d->ShareName,  q_d->ptr_ShareName, ps, depth))
-                       return False;
-       if(!prs_align(ps))
+       
+       if (!prs_uint32("num_stores", ps, depth, &v->num_stores))
                return False;
-
+       
        return True;
 }
 
-/******************************************************************* 
-Read/write a DFS_R_DFS_REMOVE structure
-*******************************************************************/
-
-BOOL dfs_io_r_dfs_remove(const char *desc, DFS_R_DFS_REMOVE *r_d, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_Info2_d(const char *desc, NETDFS_DFS_INFO2 *v, prs_struct *ps, int depth)
 {
-       if(r_d == NULL) 
+       if (v == NULL)
                return False;
-
-       prs_debug(ps, depth, desc, "dfs_io_r_dfs_remove");
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info2_d");
        depth++;
-
-       if(!prs_werror("status", ps, depth, &r_d->status))
-               return False;
-
+       if (v->ptr0_path) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!smb_io_unistr2("path", &v->path, 1, ps, depth))
+                       return False;
+       }
+       
+       if (v->ptr0_comment) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!smb_io_unistr2("comment", &v->comment, 1, ps, depth))
+                       return False;
+       }
+       
+       
+       
        return True;
 }
 
-/******************************************************************* 
-Make a DFS_Q_DFS_ADD structure
-*******************************************************************/
-
-BOOL init_dfs_q_dfs_add(DFS_Q_DFS_ADD *q_d, const char *entrypath, 
-                       const char *servername, const char *sharename, 
-                       const char *comment, uint32 flags)
+BOOL init_netdfs_dfs_StorageInfo(NETDFS_DFS_STORAGEINFO *v, uint32 state, const char *server, const char *share)
 {
-       DEBUG(5,("init_dfs_q_dfs_add\n"));
-       q_d->ptr_DfsEntryPath = q_d->ptr_ServerName = q_d->ptr_ShareName = 1;
-       init_unistr2(&q_d->DfsEntryPath, entrypath, UNI_STR_TERMINATE);
-       init_unistr2(&q_d->ServerName, servername, UNI_STR_TERMINATE);
-       init_unistr2(&q_d->ShareName, sharename, UNI_STR_TERMINATE);
-       if(comment != NULL) {
-               init_unistr2(&q_d->Comment, comment,UNI_STR_TERMINATE);
-               q_d->ptr_Comment = 1;
+       DEBUG(5,("init_netdfs_dfs_StorageInfo\n"));
+       
+       v->state = state;
+       
+       if (server) {
+               v->ptr0_server = 1;
+               init_unistr2(&v->server, server, UNI_FLAGS_NONE);
        } else {
-               q_d->ptr_Comment = 0;
+               v->ptr0_server = 0;
        }
-
-       q_d->Flags = flags;
+       
+       if (share) {
+               v->ptr0_share = 1;
+               init_unistr2(&v->share, share, UNI_FLAGS_NONE);
+       } else {
+               v->ptr0_share = 0;
+       }
+       
        return True;
 }
 
-/************************************************************
- Read/write a DFS_Q_DFS_ADD structure
- ************************************************************/
-
-BOOL dfs_io_q_dfs_add(const char *desc, DFS_Q_DFS_ADD *q_d, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_StorageInfo_p(const char *desc, NETDFS_DFS_STORAGEINFO *v, prs_struct *ps, int depth)
 {
-       if(q_d == NULL)
+       if (v == NULL)
                return False;
-
-       prs_debug(ps, depth, desc, "dfs_io_q_dfs_add");
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_StorageInfo_p");
        depth++;
-  
-       if(!prs_align(ps))
-               return False;
-  
-       if(!smb_io_unistr2("DfsEntryPath",&q_d->DfsEntryPath, 1, ps, depth))
-               return False;
-       if(!prs_align(ps))
-               return False;
-
-       if(!smb_io_unistr2("ServerName",&q_d->ServerName, 1, ps, depth))
-               return False;
-       if(!prs_align(ps))
-               return False;
-
-       if(!prs_uint32("ptr_ShareName", ps, depth, &q_d->ptr_ShareName))
-               return False;
-       if(!smb_io_unistr2("ShareName",&q_d->ShareName,  1, ps, depth))
-               return False;
-       if(!prs_align(ps))
-               return False;
-
-       if(!prs_uint32("ptr_Comment", ps, depth, &q_d->ptr_Comment))
+       if (!prs_uint32("state", ps, depth, &v->state))
                return False;
-       if(!smb_io_unistr2("",&q_d->Comment, q_d->ptr_Comment , ps, depth))
+       
+       if (!prs_uint32("ptr0_server", ps, depth, &v->ptr0_server))
                return False;
-       if(!prs_align(ps))
+       
+       
+       if (!prs_uint32("ptr0_share", ps, depth, &v->ptr0_share))
                return False;
-
-       if(!prs_uint32("Flags", ps, depth, &q_d->Flags))
-               return True;
-
+       
+       
        return True;
 }
 
-/************************************************************
- Read/write a DFS_R_DFS_ADD structure 
- ************************************************************/
-
-BOOL dfs_io_r_dfs_add(const char *desc, DFS_R_DFS_ADD *r_d, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_StorageInfo_d(const char *desc, NETDFS_DFS_STORAGEINFO *v, prs_struct *ps, int depth)
 {
-       if(r_d == NULL)
+       if (v == NULL)
                return False;
-
-       prs_debug(ps, depth, desc, "dfs_io_r_dfs_add");
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_StorageInfo_d");
        depth++;
-
-       if(!prs_werror("status", ps, depth, &r_d->status))
-               return False;
-
+       
+       if (v->ptr0_server) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!smb_io_unistr2("server", &v->server, 1, ps, depth))
+                       return False;
+       }
+       
+       if (v->ptr0_share) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!smb_io_unistr2("share", &v->share, 1, ps, depth))
+                       return False;
+       }
+       
        return True;
 }
 
-BOOL init_dfs_q_dfs_get_info(DFS_Q_DFS_GET_INFO *q_d, const char *entrypath,
-                            const char *servername, const char *sharename, 
-                            uint32 info_level)
+BOOL init_netdfs_dfs_Info3(NETDFS_DFS_INFO3 *v, const char *path, const char *comment, uint32 state, uint32 num_stores, NETDFS_DFS_STORAGEINFO **stores)
 {
-       DEBUG(5,("init_dfs_q2_get_info\n"));
-       init_unistr2(&q_d->uni_path, entrypath, UNI_STR_TERMINATE);
-       init_unistr2(&q_d->uni_server, servername, UNI_STR_TERMINATE);
-       init_unistr2(&q_d->uni_share, sharename, UNI_STR_TERMINATE);
-       q_d->level = info_level;
-       q_d->ptr_server = q_d->ptr_share = 1;
+       DEBUG(5,("init_netdfs_dfs_Info3\n"));
+       
+       if (path) {
+               v->ptr0_path = 1;
+               init_unistr2(&v->path, path, UNI_FLAGS_NONE);
+       } else {
+               v->ptr0_path = 0;
+       }
+       
+       if (comment) {
+               v->ptr0_comment = 1;
+               init_unistr2(&v->comment, comment, UNI_FLAGS_NONE);
+       } else {
+               v->ptr0_comment = 0;
+       }
+       
+       v->state = state;
+       
+       v->num_stores = num_stores;
+       
+       if (stores) {
+               v->ptr0_stores = 1;
+               v->stores = *stores;
+       } else {
+               v->ptr0_stores = 0;
+       }
+       
        return True;
 }
 
-/************************************************************
- Read/write a DFS_Q_GET_INFO structure
- ************************************************************/
-
-BOOL dfs_io_q_dfs_get_info(const char *desc, DFS_Q_DFS_GET_INFO* q_i, prs_struct* ps, int depth)
+BOOL netdfs_io_dfs_Info3_p(const char *desc, NETDFS_DFS_INFO3 *v, prs_struct *ps, int depth)
 {
-       if(q_i == NULL)
+       if (v == NULL)
                return False;
-
-       prs_debug(ps, depth, desc, "dfs_io_q_dfs_get_info");
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info3_p");
        depth++;
-
-       if(!smb_io_unistr2("",&q_i->uni_path, 1, ps, depth))
-               return False;
-
-       if(!prs_align(ps))
-               return False;
-
-       if(!prs_uint32("ptr_server", ps, depth, &q_i->ptr_server))
+       if (!prs_uint32("ptr0_path", ps, depth, &v->ptr0_path))
                return False;
-
-       if(q_i->ptr_server)
-               if (!smb_io_unistr2("",&q_i->uni_server, q_i->ptr_server, ps, depth))
-                       return False;
-       if(!prs_align(ps))
+       
+       
+       if (!prs_uint32("ptr0_comment", ps, depth, &v->ptr0_comment))
                return False;
-
-       if(!prs_uint32("ptr_share", ps, depth, &q_i->ptr_share))
+       
+       
+       if (!prs_uint32("state", ps, depth, &v->state))
                return False;
-       if(q_i->ptr_share)
-               if(!smb_io_unistr2("", &q_i->uni_share, q_i->ptr_share, ps, depth))
-                       return False;
-       if(!prs_align(ps))
+       
+       if (!prs_uint32("num_stores", ps, depth, &v->num_stores))
                return False;
-
-       if(!prs_uint32("level", ps, depth, &q_i->level))
+       
+       if (!prs_uint32("ptr0_stores", ps, depth, &v->ptr0_stores))
                return False;
+       
+       
        return True;
 }
 
-/************************************************************
- Read/write a DFS_R_GET_INFO structure
- ************************************************************/
-
-BOOL dfs_io_r_dfs_get_info(const char *desc, DFS_R_DFS_GET_INFO* r_i, prs_struct* ps, int depth)
+BOOL netdfs_io_dfs_Info3_d(const char *desc, NETDFS_DFS_INFO3 *v, prs_struct *ps, int depth)
 {
-       if(r_i == NULL)
-               return False;
-  
-       if(!prs_uint32("level", ps, depth, &r_i->level))
-               return False;
-       if(!prs_uint32("ptr_ctr", ps, depth, &r_i->ptr_ctr))
-               return False;
-
-       if(!dfs_io_dfs_info_ctr("", &r_i->ctr, 1, r_i->level, ps, depth))
-               return False;
-       if(!prs_werror("status", ps, depth, &r_i->status))
+       uint32 i_stores_1;
+       
+       if (v == NULL)
                return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info3_d");
+       depth++;
+       if (v->ptr0_path) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!smb_io_unistr2("path", &v->path, 1, ps, depth))
+                       return False;
+       }
+       
+       if (v->ptr0_comment) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!smb_io_unistr2("comment", &v->comment, 1, ps, depth))
+                       return False;
+       }
+       
+       
+       
+       if (v->ptr0_stores) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!prs_uint32("size_stores", ps, depth, &v->size_stores))
+                       return False;
+               
+               if (UNMARSHALLING(ps)) {
+                       v->stores = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*v->stores)*v->num_stores);
+               }
+               for (i_stores_1=0; i_stores_1<v->num_stores;i_stores_1++) {
+                       if (!netdfs_io_dfs_StorageInfo_p("stores", &v->stores[i_stores_1], ps, depth))
+                               return False;
+               }
+               for (i_stores_1=0; i_stores_1<v->num_stores;i_stores_1++) {
+                       if (!netdfs_io_dfs_StorageInfo_d("stores", &v->stores[i_stores_1], ps, depth))
+                               return False;
+               }
+       }
+       
        return True;
 }
-                          
-/************************************************************
- Make a DFS_Q_DFS_ENUM structure
- ************************************************************/
-BOOL init_dfs_q_dfs_enum(DFS_Q_DFS_ENUM *q_d, uint32 level, DFS_INFO_CTR *ctr)
+
+BOOL init_netdfs_dfs_Info4(NETDFS_DFS_INFO4 *v, const char *path, const char *comment, uint32 state, uint32 timeout, struct uuid guid, uint32 num_stores, NETDFS_DFS_STORAGEINFO **stores)
 {
-       q_d->level = level;
-       q_d->maxpreflen = -1;
-       q_d->ptr_buffer = 1;
-       q_d->level2 = level;
-  
-       q_d->ptr_num_entries = 1;
-       q_d->num_entries = 0;
-       q_d->num_entries2 = 0;
-       q_d->reshnd.ptr_hnd = 1;
-       q_d->reshnd.handle = 0;
+       DEBUG(5,("init_netdfs_dfs_Info4\n"));
+       
+       if (path) {
+               v->ptr0_path = 1;
+               init_unistr2(&v->path, path, UNI_FLAGS_NONE);
+       } else {
+               v->ptr0_path = 0;
+       }
+       
+       if (comment) {
+               v->ptr0_comment = 1;
+               init_unistr2(&v->comment, comment, UNI_FLAGS_NONE);
+       } else {
+               v->ptr0_comment = 0;
+       }
+       
+       v->state = state;
+       
+       v->timeout = timeout;
+       
+       
+       
+       v->num_stores = num_stores;
+       
+       if (stores) {
+               v->ptr0_stores = 1;
+               v->stores = *stores;
+       } else {
+               v->ptr0_stores = 0;
+       }
+       
        return True;
 }
-  
-/************************************************************
- Read or write the DFS_Q_DFS_ENUM structure 
- ************************************************************/
 
-BOOL dfs_io_q_dfs_enum(const char *desc, DFS_Q_DFS_ENUM *q_d, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_Info4_p(const char *desc, NETDFS_DFS_INFO4 *v, prs_struct *ps, int depth)
 {
-       if(q_d == NULL)
+       if (v == NULL)
                return False;
-
-       prs_debug(ps, depth, desc, "dfs_io_q_dfs_enum");
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info4_p");
        depth++;
-  
-       if(!prs_align(ps))
-               return False;
-  
-       if(!prs_uint32("level", ps, depth, &q_d->level))
-               return False;
-       if(!prs_uint32("maxpreflen", ps, depth, &q_d->maxpreflen))
-               return False;
-       if(!prs_uint32("ptr_buffer", ps, depth, &q_d->ptr_buffer))
+       if (!prs_uint32("ptr0_path", ps, depth, &v->ptr0_path))
                return False;
-       if(!prs_uint32("level2", ps, depth, &q_d->level2))
+       
+       
+       if (!prs_uint32("ptr0_comment", ps, depth, &v->ptr0_comment))
                return False;
-       if(!prs_uint32("level3", ps, depth, &q_d->level2))
+       
+       
+       if (!prs_uint32("state", ps, depth, &v->state))
                return False;
-  
-       if(!prs_uint32("ptr_num_entries", ps, depth, &q_d->ptr_num_entries))
+       
+       if (!prs_uint32("timeout", ps, depth, &v->timeout))
                return False;
-       if(!prs_uint32("num_entries", ps, depth, &q_d->num_entries))
+       
+       if (!smb_io_uuid("guid", &v->guid, ps, depth))
                return False;
-       if(!prs_uint32("num_entries2", ps, depth, &q_d->num_entries2))
+       
+       if (!prs_uint32("num_stores", ps, depth, &v->num_stores))
                return False;
-       if(!smb_io_enum_hnd("resume_hnd",&q_d->reshnd, ps, depth))
+       
+       if (!prs_uint32("ptr0_stores", ps, depth, &v->ptr0_stores))
                return False;
+       
+       
        return True;
 }
 
-/************************************************************
- Read/write a DFS_INFO_CTR structure
- ************************************************************/
-
-BOOL dfs_io_dfs_info_ctr(const char *desc, DFS_INFO_CTR* ctr, uint32 num_entries, uint32 level, prs_struct* ps, int depth)
+BOOL netdfs_io_dfs_Info4_d(const char *desc, NETDFS_DFS_INFO4 *v, prs_struct *ps, int depth)
 {
-       int i=0;
-
-       switch(level) {
-       case 1:
-               depth++;
-               /* should depend on whether marshalling or unmarshalling! */
-               if(UNMARSHALLING(ps)) {
-                       ctr->dfs.info1 = PRS_ALLOC_MEM(ps, DFS_INFO_1, num_entries);
-                       if (!ctr->dfs.info1)
-                               return False;
-               }
-
-               for(i=0;i<num_entries;i++) {
-                       if(!prs_uint32("ptr_entrypath",ps, depth, &ctr->dfs.info1[i].ptr_entrypath))
-                               return False;
-               }
-               for(i=0;i<num_entries;i++) {
-                       if(!smb_io_unistr2("", &ctr->dfs.info1[i].entrypath, ctr->dfs.info1[i].ptr_entrypath, ps, depth))
-                               return False;
-                       if(!prs_align(ps))
-                               return False;
-               }
-               depth--;
-               break;
-       case 2:
-               depth++;
-               if(UNMARSHALLING(ps)) {
-                       ctr->dfs.info2 = PRS_ALLOC_MEM(ps, DFS_INFO_2, num_entries);
-                       if (!ctr->dfs.info2)
-                               return False;
-               }
-
-               for(i=0;i<num_entries;i++) {
-                       if(!prs_uint32("ptr_entrypath", ps, depth, &ctr->dfs.info2[i].ptr_entrypath))
-                               return False;
-                       if(!prs_uint32("ptr_comment", ps, depth, &ctr->dfs.info2[i].ptr_comment))
-                               return False;
-                       if(!prs_uint32("state", ps, depth, &ctr->dfs.info2[i].state))
-                               return False;
-                       if(!prs_uint32("num_storages", ps, depth, &ctr->dfs.info2[i].num_storages))
-                               return False;
-               }
-               for(i=0;i<num_entries;i++) {
-                       if(!smb_io_unistr2("", &ctr->dfs.info2[i].entrypath, ctr->dfs.info2[i].ptr_entrypath, ps, depth))
-                               return False;
-                       if(!prs_align(ps))
-                               return False;
-                       if(!smb_io_unistr2("",&ctr->dfs.info2[i].comment, ctr->dfs.info2[i].ptr_comment, ps, depth))
-                               return False;
-                       if(!prs_align(ps))
-                               return False;
-               }
-               depth--;
-               break;
-       case 3:
-               depth++;
-               if(UNMARSHALLING(ps)) {
-                       ctr->dfs.info3 = PRS_ALLOC_MEM(ps, DFS_INFO_3, num_entries);
-                       if (!ctr->dfs.info3)
-                               return False;
+       uint32 i_stores_1;
+       
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info4_d");
+       depth++;
+       if (v->ptr0_path) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!smb_io_unistr2("path", &v->path, 1, ps, depth))
+                       return False;
+       }
+       
+       if (v->ptr0_comment) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!smb_io_unistr2("comment", &v->comment, 1, ps, depth))
+                       return False;
+       }
+       
+       
+       
+       
+       
+       if (v->ptr0_stores) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!prs_uint32("size_stores", ps, depth, &v->size_stores))
+                       return False;
+               
+               if (UNMARSHALLING(ps)) {
+                       v->stores = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*v->stores)*v->num_stores);
                }
-
-               for(i=0;i<num_entries;i++) {
-                       if(!prs_uint32("ptr_entrypath", ps, depth, &ctr->dfs.info3[i].ptr_entrypath))
-                               return False;
-                       if(!prs_uint32("ptr_comment", ps, depth, &ctr->dfs.info3[i].ptr_comment))
-                               return False;
-                       if(!prs_uint32("state", ps, depth, &ctr->dfs.info3[i].state))
-                               return False;
-                       if(!prs_uint32("num_storages", ps, depth, &ctr->dfs.info3[i].num_storages))
-                               return False;
-                       if(!prs_uint32("ptr_storages", ps, depth, &ctr->dfs.info3[i].ptr_storages))
+               for (i_stores_1=0; i_stores_1<v->num_stores;i_stores_1++) {
+                       if (!netdfs_io_dfs_StorageInfo_p("stores", &v->stores[i_stores_1], ps, depth))
                                return False;
                }
-               for(i=0;i<num_entries;i++) {
-                       if(!smb_io_unistr2("", &ctr->dfs.info3[i].entrypath, ctr->dfs.info3[i].ptr_entrypath, ps, depth))
-                               return False;
-                       if(!prs_align(ps))
-                               return False;
-                       if(!smb_io_unistr2("", &ctr->dfs.info3[i].comment, ctr->dfs.info3[i].ptr_comment, ps, depth))
-                               return False;
-                       if(!prs_align(ps))
-                               return False;
-                       if(!prs_uint32("num_storage_infos", ps, depth, &ctr->dfs.info3[i].num_storage_infos))
-                               return False;
-
-                       if(!dfs_io_dfs_storage_info("storage_info", &ctr->dfs.info3[i], ps, depth))
+               for (i_stores_1=0; i_stores_1<v->num_stores;i_stores_1++) {
+                       if (!netdfs_io_dfs_StorageInfo_d("stores", &v->stores[i_stores_1], ps, depth))
                                return False;
                }
        }
-
+       
        return True;
 }
 
-/************************************************************
- Read/write a DFS_R_DFS_ENUM structure
- ************************************************************/
+BOOL init_netdfs_dfs_Info100(NETDFS_DFS_INFO100 *v, const char *comment)
+{
+       DEBUG(5,("init_netdfs_dfs_Info100\n"));
+       
+       if (comment) {
+               v->ptr0_comment = 1;
+               init_unistr2(&v->comment, comment, UNI_FLAGS_NONE);
+       } else {
+               v->ptr0_comment = 0;
+       }
+       
+       return True;
+}
 
-BOOL dfs_io_r_dfs_enum(const char *desc, DFS_R_DFS_ENUM *q_d, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_Info100_p(const char *desc, NETDFS_DFS_INFO100 *v, prs_struct *ps, int depth)
 {
-       DFS_INFO_CTR *ctr;
-       if(q_d == NULL)
+       if (v == NULL)
                return False;
-       ctr = q_d->ctr;
-       if(ctr == NULL)
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info100_p");
+       depth++;
+       if (!prs_uint32("ptr0_comment", ps, depth, &v->ptr0_comment))
                return False;
+       
+       
+       return True;
+}
 
-       prs_debug(ps, depth, desc, "dfs_io_r_dfs_enum");
+BOOL netdfs_io_dfs_Info100_d(const char *desc, NETDFS_DFS_INFO100 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info100_d");
        depth++;
+       if (v->ptr0_comment) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!smb_io_unistr2("comment", &v->comment, 1, ps, depth))
+                       return False;
+       }
+       
+       return True;
+}
 
-       if(!prs_align(ps))
-               return False;
+BOOL init_netdfs_dfs_Info101(NETDFS_DFS_INFO101 *v, uint32 state)
+{
+       DEBUG(5,("init_netdfs_dfs_Info101\n"));
+       
+       v->state = state;
+       
+       return True;
+}
 
-       if(!prs_uint32("ptr_buffer", ps, depth, &q_d->ptr_buffer))
+BOOL netdfs_io_dfs_Info101_p(const char *desc, NETDFS_DFS_INFO101 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
                return False;
-       if(!prs_uint32("level", ps, depth, &q_d->level))
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info101_p");
+       depth++;
+       if (!prs_uint32("state", ps, depth, &v->state))
                return False;
-       if(!prs_uint32("level2", ps, depth, &ctr->switch_value))
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_Info101_d(const char *desc, NETDFS_DFS_INFO101 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
                return False;
-       if(!prs_uint32("ptr_num_entries", ps, depth, &q_d->ptr_num_entries))
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info101_d");
+       depth++;
+       
+       return True;
+}
+
+BOOL init_netdfs_dfs_Info102(NETDFS_DFS_INFO102 *v, uint32 timeout)
+{
+       DEBUG(5,("init_netdfs_dfs_Info102\n"));
+       
+       v->timeout = timeout;
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_Info102_p(const char *desc, NETDFS_DFS_INFO102 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
                return False;
-       if(q_d->ptr_num_entries)
-               if(!prs_uint32("num_entries", ps, depth, &q_d->num_entries))
-                       return False;
-       if(!prs_uint32("ptr_num_entries2", ps, depth, &q_d->ptr_num_entries2))
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info102_p");
+       depth++;
+       if (!prs_uint32("timeout", ps, depth, &v->timeout))
                return False;
-       if(q_d->ptr_num_entries2)
-               if(!prs_uint32("num_entries2", ps, depth, &ctr->num_entries))
-                       return False;
+       
+       return True;
+}
 
-       if(!dfs_io_dfs_info_ctr("", ctr, q_d->num_entries, q_d->level, ps, depth))
+BOOL netdfs_io_dfs_Info102_d(const char *desc, NETDFS_DFS_INFO102 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
                return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info102_d");
+       depth++;
+       
+       return True;
+}
+
+BOOL init_netdfs_dfs_Info200(NETDFS_DFS_INFO200 *v, const char *dom_root)
+{
+       DEBUG(5,("init_netdfs_dfs_Info200\n"));
+       
+       if (dom_root) {
+               v->ptr0_dom_root = 1;
+               init_unistr2(&v->dom_root, dom_root, UNI_FLAGS_NONE);
+       } else {
+               v->ptr0_dom_root = 0;
+       }
+       
+       return True;
+}
 
-       if(!smb_io_enum_hnd("resume_hnd", &q_d->reshnd, ps, depth))
+BOOL netdfs_io_dfs_Info200_p(const char *desc, NETDFS_DFS_INFO200 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
                return False;
-       if(!prs_werror("status", ps, depth, &q_d->status))
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info200_p");
+       depth++;
+       if (!prs_uint32("ptr0_dom_root", ps, depth, &v->ptr0_dom_root))
                return False;
+       
+       
        return True;
 }
 
-BOOL dfs_io_dfs_storage_info(const char *desc, DFS_INFO_3* info3, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_Info200_d(const char *desc, NETDFS_DFS_INFO200 *v, prs_struct *ps, int depth)
 {
-       int i=0;
-       if(info3 == NULL)
+       if (v == NULL)
                return False;
-  
-       prs_debug(ps, depth, desc, "smb_io_dfs_storage_info");
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info200_d");
        depth++;
-
-       if(UNMARSHALLING(ps)) {
-               info3->storages = PRS_ALLOC_MEM(ps, DFS_STORAGE_INFO, info3->num_storage_infos);
-               if (!info3->storages)
+       if (v->ptr0_dom_root) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!smb_io_unistr2("dom_root", &v->dom_root, 1, ps, depth))
                        return False;
        }
+       
+       return True;
+}
 
-       for(i=0;i<info3->num_storage_infos;i++) {
-               if(!prs_uint32("storage_state", ps, depth, &info3->storages[i].state))
-                       return False;
-               if(!prs_uint32("ptr_servername", ps, depth, &info3->storages[i].ptr_servername))
-                       return False;
-               if(!prs_uint32("ptr_sharename", ps, depth, &info3->storages[i].ptr_sharename))
-                       return False;
+BOOL init_netdfs_dfs_Info300(NETDFS_DFS_INFO300 *v, uint32 flags, const char *dom_root)
+{
+       DEBUG(5,("init_netdfs_dfs_Info300\n"));
+       
+       v->flags = flags;
+       
+       if (dom_root) {
+               v->ptr0_dom_root = 1;
+               init_unistr2(&v->dom_root, dom_root, UNI_FLAGS_NONE);
+       } else {
+               v->ptr0_dom_root = 0;
        }
+       
+       return True;
+}
 
-       for(i=0;i<info3->num_storage_infos;i++) {
-               if(!smb_io_unistr2("servername", &info3->storages[i].servername, info3->storages[i].ptr_servername, ps, depth))
-                       return False;
-               if(!prs_align(ps))
-                       return False;
-               if(!smb_io_unistr2("sharename", &info3->storages[i].sharename, info3->storages[i].ptr_sharename, ps, depth))
+BOOL netdfs_io_dfs_Info300_p(const char *desc, NETDFS_DFS_INFO300 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info300_p");
+       depth++;
+       if (!prs_uint32("flags", ps, depth, &v->flags))
+               return False;
+       
+       if (!prs_uint32("ptr0_dom_root", ps, depth, &v->ptr0_dom_root))
+               return False;
+       
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_Info300_d(const char *desc, NETDFS_DFS_INFO300 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_Info300_d");
+       depth++;
+       
+       if (v->ptr0_dom_root) {
+               if (!prs_align_custom(ps, 4))
                        return False;
-               if(!prs_align(ps))
+               
+               if (!smb_io_unistr2("dom_root", &v->dom_root, 1, ps, depth))
                        return False;
        }
-
+       
        return True;
 }
+
+BOOL netdfs_io_dfs_Info_p(const char *desc, NETDFS_DFS_INFO_CTR* v, prs_struct *ps, int depth)
+{
+       if (!prs_uint32("switch_value", ps, depth, &v->switch_value))
+               return False;
+       
+       switch (v->switch_value) {
+               case 0:
+                       depth++;
+                       if (!prs_uint32("ptr0_info0", ps, depth, &v->ptr0))
+                               return False;
+                       
+                       depth--;
+                       break;
+               
+               case 1:
+                       depth++;
+                       if (!prs_uint32("ptr0_info1", ps, depth, &v->ptr0))
+                               return False;
+                       
+                       depth--;
+                       break;
+               
+               case 2:
+                       depth++;
+                       if (!prs_uint32("ptr0_info2", ps, depth, &v->ptr0))
+                               return False;
+                       
+                       depth--;
+                       break;
+               
+               case 3:
+                       depth++;
+                       if (!prs_uint32("ptr0_info3", ps, depth, &v->ptr0))
+                               return False;
+                       
+                       depth--;
+                       break;
+               
+               case 4:
+                       depth++;
+                       if (!prs_uint32("ptr0_info4", ps, depth, &v->ptr0))
+                               return False;
+                       
+                       depth--;
+                       break;
+               
+               case 100:
+                       depth++;
+                       if (!prs_uint32("ptr0_info100", ps, depth, &v->ptr0))
+                               return False;
+                       
+                       depth--;
+                       break;
+               
+               case 101:
+                       depth++;
+                       if (!prs_uint32("ptr0_info101", ps, depth, &v->ptr0))
+                               return False;
+                       
+                       depth--;
+                       break;
+               
+               case 102:
+                       depth++;
+                       if (!prs_uint32("ptr0_info102", ps, depth, &v->ptr0))
+                               return False;
+                       
+                       depth--;
+                       break;
+               
+               default:
+                       return False;
+               
+       }
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_Info_d(const char *desc, NETDFS_DFS_INFO_CTR* v, prs_struct *ps, int depth)
+{
+       switch (v->switch_value) {
+               case 0:
+                       depth++;
+                       if (v->ptr0) {
+                               if (!prs_align_custom(ps, 1))
+                                       return False;
+                               
+                               if (!netdfs_io_dfs_Info0_p("info0", &v->u.info0, ps, depth))
+                                       return False;
+                               if (!netdfs_io_dfs_Info0_d("info0", &v->u.info0, ps, depth))
+                                       return False;
+                       }
+                       depth--;
+                       break;
+               
+               case 1:
+                       depth++;
+                       if (v->ptr0) {
+                               if (!prs_align_custom(ps, 4))
+                                       return False;
+                               
+                               if (!netdfs_io_dfs_Info1_p("info1", &v->u.info1, ps, depth))
+                                       return False;
+                               if (!netdfs_io_dfs_Info1_d("info1", &v->u.info1, ps, depth))
+                                       return False;
+                       }
+                       depth--;
+                       break;
+               
+               case 2:
+                       depth++;
+                       if (v->ptr0) {
+                               if (!prs_align_custom(ps, 4))
+                                       return False;
+                               
+                               if (!netdfs_io_dfs_Info2_p("info2", &v->u.info2, ps, depth))
+                                       return False;
+                               if (!netdfs_io_dfs_Info2_d("info2", &v->u.info2, ps, depth))
+                                       return False;
+                       }
+                       depth--;
+                       break;
+               
+               case 3:
+                       depth++;
+                       if (v->ptr0) {
+                               if (!prs_align_custom(ps, 4))
+                                       return False;
+                               
+                               if (!netdfs_io_dfs_Info3_p("info3", &v->u.info3, ps, depth))
+                                       return False;
+                               if (!netdfs_io_dfs_Info3_d("info3", &v->u.info3, ps, depth))
+                                       return False;
+                       }
+                       depth--;
+                       break;
+               
+               case 4:
+                       depth++;
+                       if (v->ptr0) {
+                               if (!prs_align_custom(ps, 4))
+                                       return False;
+                               
+                               if (!netdfs_io_dfs_Info4_p("info4", &v->u.info4, ps, depth))
+                                       return False;
+                               if (!netdfs_io_dfs_Info4_d("info4", &v->u.info4, ps, depth))
+                                       return False;
+                       }
+                       depth--;
+                       break;
+               
+               case 100:
+                       depth++;
+                       if (v->ptr0) {
+                               if (!prs_align_custom(ps, 4))
+                                       return False;
+                               
+                               if (!netdfs_io_dfs_Info100_p("info100", &v->u.info100, ps, depth))
+                                       return False;
+                               if (!netdfs_io_dfs_Info100_d("info100", &v->u.info100, ps, depth))
+                                       return False;
+                       }
+                       depth--;
+                       break;
+               
+               case 101:
+                       depth++;
+                       if (v->ptr0) {
+                               if (!prs_align_custom(ps, 4))
+                                       return False;
+                               
+                               if (!netdfs_io_dfs_Info101_p("info101", &v->u.info101, ps, depth))
+                                       return False;
+                               if (!netdfs_io_dfs_Info101_d("info101", &v->u.info101, ps, depth))
+                                       return False;
+                       }
+                       depth--;
+                       break;
+               
+               case 102:
+                       depth++;
+                       if (v->ptr0) {
+                               if (!prs_align_custom(ps, 4))
+                                       return False;
+                               
+                               if (!netdfs_io_dfs_Info102_p("info102", &v->u.info102, ps, depth))
+                                       return False;
+                               if (!netdfs_io_dfs_Info102_d("info102", &v->u.info102, ps, depth))
+                                       return False;
+                       }
+                       depth--;
+                       break;
+               
+       }
+       
+       return True;
+}
+BOOL init_netdfs_dfs_EnumArray1(NETDFS_DFS_ENUMARRAY1 *v, uint32 count, NETDFS_DFS_INFO1 **s)
+{
+       DEBUG(5,("init_netdfs_dfs_EnumArray1\n"));
+       
+       v->count = count;
+       
+       if (s) {
+               v->ptr0_s = 1;
+               v->s = *s;
+       } else {
+               v->ptr0_s = 0;
+       }
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray1_p(const char *desc, NETDFS_DFS_ENUMARRAY1 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray1_p");
+       depth++;
+       if (!prs_uint32("count", ps, depth, &v->count))
+               return False;
+       
+       if (!prs_uint32("ptr0_s", ps, depth, &v->ptr0_s))
+               return False;
+       
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray1_d(const char *desc, NETDFS_DFS_ENUMARRAY1 *v, prs_struct *ps, int depth)
+{
+       uint32 i_s_1;
+       
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray1_d");
+       depth++;
+       
+       if (v->ptr0_s) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!prs_uint32("size_s", ps, depth, &v->size_s))
+                       return False;
+               
+               if (UNMARSHALLING(ps)) {
+                       v->s = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*v->s)*v->count);
+               }
+               for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+                       if (!netdfs_io_dfs_Info1_p("s", &v->s[i_s_1], ps, depth))
+                               return False;
+               }
+               for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+                       if (!netdfs_io_dfs_Info1_d("s", &v->s[i_s_1], ps, depth))
+                               return False;
+               }
+       }
+       
+       return True;
+}
+
+BOOL init_netdfs_dfs_EnumArray2(NETDFS_DFS_ENUMARRAY2 *v, uint32 count, NETDFS_DFS_INFO2 **s)
+{
+       DEBUG(5,("init_netdfs_dfs_EnumArray2\n"));
+       
+       v->count = count;
+       
+       if (s) {
+               v->ptr0_s = 1;
+               v->s = *s;
+       } else {
+               v->ptr0_s = 0;
+       }
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray2_p(const char *desc, NETDFS_DFS_ENUMARRAY2 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray2_p");
+       depth++;
+       if (!prs_uint32("count", ps, depth, &v->count))
+               return False;
+       
+       if (!prs_uint32("ptr0_s", ps, depth, &v->ptr0_s))
+               return False;
+       
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray2_d(const char *desc, NETDFS_DFS_ENUMARRAY2 *v, prs_struct *ps, int depth)
+{
+       uint32 i_s_1;
+       
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray2_d");
+       depth++;
+       
+       if (v->ptr0_s) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!prs_uint32("size_s", ps, depth, &v->size_s))
+                       return False;
+               
+               if (UNMARSHALLING(ps)) {
+                       v->s = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*v->s)*v->count);
+               }
+               for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+                       if (!netdfs_io_dfs_Info2_p("s", &v->s[i_s_1], ps, depth))
+                               return False;
+               }
+               for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+                       if (!netdfs_io_dfs_Info2_d("s", &v->s[i_s_1], ps, depth))
+                               return False;
+               }
+       }
+       
+       return True;
+}
+
+BOOL init_netdfs_dfs_EnumArray3(NETDFS_DFS_ENUMARRAY3 *v, uint32 count, NETDFS_DFS_INFO3 **s)
+{
+       DEBUG(5,("init_netdfs_dfs_EnumArray3\n"));
+       
+       v->count = count;
+       
+       if (s) {
+               v->ptr0_s = 1;
+               v->s = *s;
+       } else {
+               v->ptr0_s = 0;
+       }
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray3_p(const char *desc, NETDFS_DFS_ENUMARRAY3 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray3_p");
+       depth++;
+       if (!prs_uint32("count", ps, depth, &v->count))
+               return False;
+       
+       if (!prs_uint32("ptr0_s", ps, depth, &v->ptr0_s))
+               return False;
+       
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray3_d(const char *desc, NETDFS_DFS_ENUMARRAY3 *v, prs_struct *ps, int depth)
+{
+       uint32 i_s_1;
+       
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray3_d");
+       depth++;
+       
+       if (v->ptr0_s) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!prs_uint32("size_s", ps, depth, &v->size_s))
+                       return False;
+               
+               if (UNMARSHALLING(ps)) {
+                       v->s = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*v->s)*v->count);
+               }
+               for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+                       if (!netdfs_io_dfs_Info3_p("s", &v->s[i_s_1], ps, depth))
+                               return False;
+               }
+               for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+                       if (!netdfs_io_dfs_Info3_d("s", &v->s[i_s_1], ps, depth))
+                               return False;
+               }
+       }
+       
+       return True;
+}
+
+BOOL init_netdfs_dfs_EnumArray4(NETDFS_DFS_ENUMARRAY4 *v, uint32 count, NETDFS_DFS_INFO4 **s)
+{
+       DEBUG(5,("init_netdfs_dfs_EnumArray4\n"));
+       
+       v->count = count;
+       
+       if (s) {
+               v->ptr0_s = 1;
+               v->s = *s;
+       } else {
+               v->ptr0_s = 0;
+       }
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray4_p(const char *desc, NETDFS_DFS_ENUMARRAY4 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray4_p");
+       depth++;
+       if (!prs_uint32("count", ps, depth, &v->count))
+               return False;
+       
+       if (!prs_uint32("ptr0_s", ps, depth, &v->ptr0_s))
+               return False;
+       
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray4_d(const char *desc, NETDFS_DFS_ENUMARRAY4 *v, prs_struct *ps, int depth)
+{
+       uint32 i_s_1;
+       
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray4_d");
+       depth++;
+       
+       if (v->ptr0_s) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!prs_uint32("size_s", ps, depth, &v->size_s))
+                       return False;
+               
+               if (UNMARSHALLING(ps)) {
+                       v->s = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*v->s)*v->count);
+               }
+               for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+                       if (!netdfs_io_dfs_Info4_p("s", &v->s[i_s_1], ps, depth))
+                               return False;
+               }
+               for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+                       if (!netdfs_io_dfs_Info4_d("s", &v->s[i_s_1], ps, depth))
+                               return False;
+               }
+       }
+       
+       return True;
+}
+
+BOOL init_netdfs_dfs_EnumArray200(NETDFS_DFS_ENUMARRAY200 *v, uint32 count, NETDFS_DFS_INFO200 **s)
+{
+       DEBUG(5,("init_netdfs_dfs_EnumArray200\n"));
+       
+       v->count = count;
+       
+       if (s) {
+               v->ptr0_s = 1;
+               v->s = *s;
+       } else {
+               v->ptr0_s = 0;
+       }
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray200_p(const char *desc, NETDFS_DFS_ENUMARRAY200 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray200_p");
+       depth++;
+       if (!prs_uint32("count", ps, depth, &v->count))
+               return False;
+       
+       if (!prs_uint32("ptr0_s", ps, depth, &v->ptr0_s))
+               return False;
+       
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray200_d(const char *desc, NETDFS_DFS_ENUMARRAY200 *v, prs_struct *ps, int depth)
+{
+       uint32 i_s_1;
+       
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray200_d");
+       depth++;
+       
+       if (v->ptr0_s) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!prs_uint32("size_s", ps, depth, &v->size_s))
+                       return False;
+               
+               if (UNMARSHALLING(ps)) {
+                       v->s = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*v->s)*v->count);
+               }
+               for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+                       if (!netdfs_io_dfs_Info200_p("s", &v->s[i_s_1], ps, depth))
+                               return False;
+               }
+               for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+                       if (!netdfs_io_dfs_Info200_d("s", &v->s[i_s_1], ps, depth))
+                               return False;
+               }
+       }
+       
+       return True;
+}
+
+BOOL init_netdfs_dfs_EnumArray300(NETDFS_DFS_ENUMARRAY300 *v, uint32 count, NETDFS_DFS_INFO300 **s)
+{
+       DEBUG(5,("init_netdfs_dfs_EnumArray300\n"));
+       
+       v->count = count;
+       
+       if (s) {
+               v->ptr0_s = 1;
+               v->s = *s;
+       } else {
+               v->ptr0_s = 0;
+       }
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray300_p(const char *desc, NETDFS_DFS_ENUMARRAY300 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray300_p");
+       depth++;
+       if (!prs_uint32("count", ps, depth, &v->count))
+               return False;
+       
+       if (!prs_uint32("ptr0_s", ps, depth, &v->ptr0_s))
+               return False;
+       
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_EnumArray300_d(const char *desc, NETDFS_DFS_ENUMARRAY300 *v, prs_struct *ps, int depth)
+{
+       uint32 i_s_1;
+       
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray300_d");
+       depth++;
+       
+       if (v->ptr0_s) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!prs_uint32("size_s", ps, depth, &v->size_s))
+                       return False;
+               
+               if (UNMARSHALLING(ps)) {
+                       v->s = (void *)PRS_ALLOC_MEM_VOID(ps,sizeof(*v->s)*v->count);
+               }
+               for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+                       if (!netdfs_io_dfs_Info300_p("s", &v->s[i_s_1], ps, depth))
+                               return False;
+               }
+               for (i_s_1=0; i_s_1<v->count;i_s_1++) {
+                       if (!netdfs_io_dfs_Info300_d("s", &v->s[i_s_1], ps, depth))
+                               return False;
+               }
+       }
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_EnumInfo_p(const char *desc, NETDFS_DFS_ENUMINFO_CTR* v, prs_struct *ps, int depth)
+{
+       if (!prs_uint32("switch_value", ps, depth, &v->switch_value))
+               return False;
+       
+       switch (v->switch_value) {
+               case 1:
+                       depth++;
+                       if (!prs_uint32("ptr0_info1", ps, depth, &v->ptr0))
+                               return False;
+                       
+                       depth--;
+                       break;
+               
+               case 2:
+                       depth++;
+                       if (!prs_uint32("ptr0_info2", ps, depth, &v->ptr0))
+                               return False;
+                       
+                       depth--;
+                       break;
+               
+               case 3:
+                       depth++;
+                       if (!prs_uint32("ptr0_info3", ps, depth, &v->ptr0))
+                               return False;
+                       
+                       depth--;
+                       break;
+               
+               case 4:
+                       depth++;
+                       if (!prs_uint32("ptr0_info4", ps, depth, &v->ptr0))
+                               return False;
+                       
+                       depth--;
+                       break;
+               
+               case 200:
+                       depth++;
+                       if (!prs_uint32("ptr0_info200", ps, depth, &v->ptr0))
+                               return False;
+                       
+                       depth--;
+                       break;
+               
+               case 300:
+                       depth++;
+                       if (!prs_uint32("ptr0_info300", ps, depth, &v->ptr0))
+                               return False;
+                       
+                       depth--;
+                       break;
+               
+               default:
+                       return False;
+               
+       }
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_EnumInfo_d(const char *desc, NETDFS_DFS_ENUMINFO_CTR* v, prs_struct *ps, int depth)
+{
+       switch (v->switch_value) {
+               case 1:
+                       depth++;
+                       if (v->ptr0) {
+                               if (!prs_align_custom(ps, 4))
+                                       return False;
+                               
+                               if (!netdfs_io_dfs_EnumArray1_p("info1", &v->u.info1, ps, depth))
+                                       return False;
+                               if (!netdfs_io_dfs_EnumArray1_d("info1", &v->u.info1, ps, depth))
+                                       return False;
+                       }
+                       depth--;
+                       break;
+               
+               case 2:
+                       depth++;
+                       if (v->ptr0) {
+                               if (!prs_align_custom(ps, 4))
+                                       return False;
+                               
+                               if (!netdfs_io_dfs_EnumArray2_p("info2", &v->u.info2, ps, depth))
+                                       return False;
+                               if (!netdfs_io_dfs_EnumArray2_d("info2", &v->u.info2, ps, depth))
+                                       return False;
+                       }
+                       depth--;
+                       break;
+               
+               case 3:
+                       depth++;
+                       if (v->ptr0) {
+                               if (!prs_align_custom(ps, 4))
+                                       return False;
+                               
+                               if (!netdfs_io_dfs_EnumArray3_p("info3", &v->u.info3, ps, depth))
+                                       return False;
+                               if (!netdfs_io_dfs_EnumArray3_d("info3", &v->u.info3, ps, depth))
+                                       return False;
+                       }
+                       depth--;
+                       break;
+               
+               case 4:
+                       depth++;
+                       if (v->ptr0) {
+                               if (!prs_align_custom(ps, 4))
+                                       return False;
+                               
+                               if (!netdfs_io_dfs_EnumArray4_p("info4", &v->u.info4, ps, depth))
+                                       return False;
+                               if (!netdfs_io_dfs_EnumArray4_d("info4", &v->u.info4, ps, depth))
+                                       return False;
+                       }
+                       depth--;
+                       break;
+               
+               case 200:
+                       depth++;
+                       if (v->ptr0) {
+                               if (!prs_align_custom(ps, 4))
+                                       return False;
+                               
+                               if (!netdfs_io_dfs_EnumArray200_p("info200", &v->u.info200, ps, depth))
+                                       return False;
+                               if (!netdfs_io_dfs_EnumArray200_d("info200", &v->u.info200, ps, depth))
+                                       return False;
+                       }
+                       depth--;
+                       break;
+               
+               case 300:
+                       depth++;
+                       if (v->ptr0) {
+                               if (!prs_align_custom(ps, 4))
+                                       return False;
+                               
+                               if (!netdfs_io_dfs_EnumArray300_p("info300", &v->u.info300, ps, depth))
+                                       return False;
+                               if (!netdfs_io_dfs_EnumArray300_d("info300", &v->u.info300, ps, depth))
+                                       return False;
+                       }
+                       depth--;
+                       break;
+               
+       }
+       
+       return True;
+}
+BOOL init_netdfs_dfs_EnumStruct(NETDFS_DFS_ENUMSTRUCT *v, uint32 level, NETDFS_DFS_ENUMINFO_CTR e)
+{
+       DEBUG(5,("init_netdfs_dfs_EnumStruct\n"));
+       
+       v->level = level;
+       
+       v->e = e;
+       v->e.switch_value = v->level;
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_EnumStruct_p(const char *desc, NETDFS_DFS_ENUMSTRUCT *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumStruct_p");
+       depth++;
+       if (!prs_uint32("level", ps, depth, &v->level))
+               return False;
+       
+       if (!netdfs_io_dfs_EnumInfo_p("e", &v->e, ps, depth))
+               return False;
+       
+       return True;
+}
+
+BOOL netdfs_io_dfs_EnumStruct_d(const char *desc, NETDFS_DFS_ENUMSTRUCT *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumStruct_d");
+       depth++;
+       
+       if (!prs_align_custom(ps, 4))
+               return False;
+       
+       if (!netdfs_io_dfs_EnumInfo_d("e", &v->e, ps, depth))
+               return False;
+       
+       return True;
+}
+
+/* netdfs functions */
+BOOL init_netdfs_q_dfs_GetManagerVersion(NETDFS_Q_DFS_GETMANAGERVERSION *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_GetManagerVersion\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_GetManagerVersion(const char *desc, NETDFS_Q_DFS_GETMANAGERVERSION *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_GetManagerVersion");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_GetManagerVersion(NETDFS_R_DFS_GETMANAGERVERSION *v, uint32 *exist_flag)
+{
+       DEBUG(5,("init_netdfs_r_dfs_GetManagerVersion\n"));
+       
+       if (!exist_flag)
+               return False;
+       
+       v->exist_flag = *exist_flag;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_GetManagerVersion(const char *desc, NETDFS_R_DFS_GETMANAGERVERSION *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_GetManagerVersion");
+       depth++;
+       if (!prs_uint32("exist_flag", ps, depth, &v->exist_flag))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_Add(NETDFS_Q_DFS_ADD *v, const char *path, const char *server, const char *share, const char *comment, uint32 flags)
+{
+       DEBUG(5,("init_netdfs_q_dfs_Add\n"));
+       
+       if (!path)
+               return False;
+       
+       init_unistr2(&v->path, path, UNI_FLAGS_NONE);
+       
+       if (!server)
+               return False;
+       
+       init_unistr2(&v->server, server, UNI_FLAGS_NONE);
+       
+       if (share) {
+               v->ptr0_share = 1;
+               init_unistr2(&v->share, share, UNI_FLAGS_NONE);
+       } else {
+               v->ptr0_share = 0;
+       }
+       
+       if (comment) {
+               v->ptr0_comment = 1;
+               init_unistr2(&v->comment, comment, UNI_FLAGS_NONE);
+       } else {
+               v->ptr0_comment = 0;
+       }
+       
+       v->flags = flags;
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_Add(const char *desc, NETDFS_Q_DFS_ADD *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_Add");
+       depth++;
+       if (!prs_align_custom(ps, 4))
+               return False;
+       
+       if (!smb_io_unistr2("path", &v->path, 1, ps, depth))
+               return False;
+       
+       if (!prs_align_custom(ps, 4))
+               return False;
+       
+       if (!smb_io_unistr2("server", &v->server, 1, ps, depth))
+               return False;
+       
+       if (!prs_align_custom(ps, 4))
+               return False;
+       
+       if (!prs_uint32("ptr0_share", ps, depth, &v->ptr0_share))
+               return False;
+       
+       if (v->ptr0_share) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!smb_io_unistr2("share", &v->share, 1, ps, depth))
+                       return False;
+       }
+       
+       if (!prs_align_custom(ps, 4))
+               return False;
+       
+       if (!prs_uint32("ptr0_comment", ps, depth, &v->ptr0_comment))
+               return False;
+       
+       if (v->ptr0_comment) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!smb_io_unistr2("comment", &v->comment, 1, ps, depth))
+                       return False;
+       }
+       
+       if (!prs_align_custom(ps, 4))
+               return False;
+       
+       if (!prs_uint32("flags", ps, depth, &v->flags))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_Add(NETDFS_R_DFS_ADD *v, const char *path, const char *server, const char *share, const char *comment, uint32 flags, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_Add\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_Add(const char *desc, NETDFS_R_DFS_ADD *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_Add");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_Remove(NETDFS_Q_DFS_REMOVE *v, const char *path, const char *server, const char *share)
+{
+       DEBUG(5,("init_netdfs_q_dfs_Remove\n"));
+       
+       if (!path)
+               return False;
+       
+       init_unistr2(&v->path, path, UNI_FLAGS_NONE);
+       
+       if (server) {
+               v->ptr0_server = 1;
+               init_unistr2(&v->server, server, UNI_FLAGS_NONE);
+       } else {
+               v->ptr0_server = 0;
+       }
+       
+       if (share) {
+               v->ptr0_share = 1;
+               init_unistr2(&v->share, share, UNI_FLAGS_NONE);
+       } else {
+               v->ptr0_share = 0;
+       }
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_Remove(const char *desc, NETDFS_Q_DFS_REMOVE *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_Remove");
+       depth++;
+       if (!prs_align_custom(ps, 4))
+               return False;
+       
+       if (!smb_io_unistr2("path", &v->path, 1, ps, depth))
+               return False;
+       
+       if (!prs_align_custom(ps, 4))
+               return False;
+       
+       if (!prs_uint32("ptr0_server", ps, depth, &v->ptr0_server))
+               return False;
+       
+       if (v->ptr0_server) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!smb_io_unistr2("server", &v->server, 1, ps, depth))
+                       return False;
+       }
+       
+       if (!prs_align_custom(ps, 4))
+               return False;
+       
+       if (!prs_uint32("ptr0_share", ps, depth, &v->ptr0_share))
+               return False;
+       
+       if (v->ptr0_share) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!smb_io_unistr2("share", &v->share, 1, ps, depth))
+                       return False;
+       }
+       
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_Remove(NETDFS_R_DFS_REMOVE *v, const char *path, const char *server, const char *share, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_Remove\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_Remove(const char *desc, NETDFS_R_DFS_REMOVE *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_Remove");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_SetInfo(NETDFS_Q_DFS_SETINFO *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_SetInfo\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_SetInfo(const char *desc, NETDFS_Q_DFS_SETINFO *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_SetInfo");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_SetInfo(NETDFS_R_DFS_SETINFO *v, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_SetInfo\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_SetInfo(const char *desc, NETDFS_R_DFS_SETINFO *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_SetInfo");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_GetInfo(NETDFS_Q_DFS_GETINFO *v, const char *path, const char *server, const char *share, uint32 level)
+{
+       DEBUG(5,("init_netdfs_q_dfs_GetInfo\n"));
+       
+       if (!path)
+               return False;
+       
+       init_unistr2(&v->path, path, UNI_FLAGS_NONE);
+       
+       if (server) {
+               v->ptr0_server = 1;
+               init_unistr2(&v->server, server, UNI_FLAGS_NONE);
+       } else {
+               v->ptr0_server = 0;
+       }
+       
+       if (share) {
+               v->ptr0_share = 1;
+               init_unistr2(&v->share, share, UNI_FLAGS_NONE);
+       } else {
+               v->ptr0_share = 0;
+       }
+       
+       v->level = level;
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_GetInfo(const char *desc, NETDFS_Q_DFS_GETINFO *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_GetInfo");
+       depth++;
+       if (!prs_align_custom(ps, 4))
+               return False;
+       
+       if (!smb_io_unistr2("path", &v->path, 1, ps, depth))
+               return False;
+       
+       if (!prs_align_custom(ps, 4))
+               return False;
+       
+       if (!prs_uint32("ptr0_server", ps, depth, &v->ptr0_server))
+               return False;
+       
+       if (v->ptr0_server) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!smb_io_unistr2("server", &v->server, 1, ps, depth))
+                       return False;
+       }
+       
+       if (!prs_align_custom(ps, 4))
+               return False;
+       
+       if (!prs_uint32("ptr0_share", ps, depth, &v->ptr0_share))
+               return False;
+       
+       if (v->ptr0_share) {
+               if (!prs_align_custom(ps, 4))
+                       return False;
+               
+               if (!smb_io_unistr2("share", &v->share, 1, ps, depth))
+                       return False;
+       }
+       
+       if (!prs_align_custom(ps, 4))
+               return False;
+       
+       if (!prs_uint32("level", ps, depth, &v->level))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_GetInfo(NETDFS_R_DFS_GETINFO *v, const char *path, const char *server, const char *share, uint32 level, NETDFS_DFS_INFO_CTR *info, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_GetInfo\n"));
+       
+       if (!info)
+               return False;
+       
+       v->info = *info;
+       v->info.switch_value = level;
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_GetInfo(const char *desc, NETDFS_R_DFS_GETINFO *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_GetInfo");
+       depth++;
+       if (!netdfs_io_dfs_Info_p("info", &v->info, ps, depth))
+               return False;
+       if (!netdfs_io_dfs_Info_d("info", &v->info, ps, depth))
+               return False;
+       
+       if (!prs_align_custom(ps, 4))
+               return False;
+       
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_Enum(NETDFS_Q_DFS_ENUM *v, uint32 level, uint32 bufsize, NETDFS_DFS_ENUMSTRUCT *info, uint32 *unknown, uint32 *total)
+{
+       DEBUG(5,("init_netdfs_q_dfs_Enum\n"));
+       
+       v->level = level;
+       
+       v->bufsize = bufsize;
+       
+       if (info) {
+               v->ptr0_info = 1;
+               v->info = *info;
+       } else {
+               v->ptr0_info = 0;
+       }
+       
+       if (unknown) {
+               v->ptr0_unknown = 1;
+               v->unknown = *unknown;
+       } else {
+               v->ptr0_unknown = 0;
+       }
+       
+       if (total) {
+               v->ptr0_total = 1;
+               v->total = *total;
+       } else {
+               v->ptr0_total = 0;
+       }
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_Enum(const char *desc, NETDFS_Q_DFS_ENUM *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_Enum");
+       depth++;
+       if (!prs_uint32("level", ps, depth, &v->level))
+               return False;
+       
+       if (!prs_uint32("bufsize", ps, depth, &v->bufsize))
+               return False;
+       
+       if (!prs_uint32("ptr0_info", ps, depth, &v->ptr0_info))
+               return False;
+       
+       if (v->ptr0_info) {
+               if (!netdfs_io_dfs_EnumStruct_p("info", &v->info, ps, depth))
+                       return False;
+               if (!netdfs_io_dfs_EnumStruct_d("info", &v->info, ps, depth))
+                       return False;
+       }
+       
+       if (!prs_align_custom(ps, 4))
+               return False;
+       
+       if (!prs_uint32("ptr0_unknown", ps, depth, &v->ptr0_unknown))
+               return False;
+       
+       if (v->ptr0_unknown) {
+               if (!prs_uint32("unknown", ps, depth, &v->unknown))
+                       return False;
+       }
+       
+       if (!prs_align_custom(ps, 4))
+               return False;
+       
+       if (!prs_uint32("ptr0_total", ps, depth, &v->ptr0_total))
+               return False;
+       
+       if (v->ptr0_total) {
+               if (!prs_uint32("total", ps, depth, &v->total))
+                       return False;
+       }
+       
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_Enum(NETDFS_R_DFS_ENUM *v, uint32 level, uint32 bufsize, NETDFS_DFS_ENUMSTRUCT *info, uint32 *unknown, uint32 *total, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_Enum\n"));
+       
+       if (info) {
+               v->ptr0_info = 1;
+               v->info = *info;
+       } else {
+               v->ptr0_info = 0;
+       }
+       
+       if (total) {
+               v->ptr0_total = 1;
+               v->total = *total;
+       } else {
+               v->ptr0_total = 0;
+       }
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_Enum(const char *desc, NETDFS_R_DFS_ENUM *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_Enum");
+       depth++;
+       if (!prs_uint32("ptr0_info", ps, depth, &v->ptr0_info))
+               return False;
+       
+       if (v->ptr0_info) {
+               if (!netdfs_io_dfs_EnumStruct_p("info", &v->info, ps, depth))
+                       return False;
+               if (!netdfs_io_dfs_EnumStruct_d("info", &v->info, ps, depth))
+                       return False;
+       }
+       
+       if (!prs_align_custom(ps, 4))
+               return False;
+       
+       if (!prs_uint32("ptr0_total", ps, depth, &v->ptr0_total))
+               return False;
+       
+       if (v->ptr0_total) {
+               if (!prs_uint32("total", ps, depth, &v->total))
+                       return False;
+       }
+       
+       if (!prs_align_custom(ps, 4))
+               return False;
+       
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_Rename(NETDFS_Q_DFS_RENAME *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_Rename\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_Rename(const char *desc, NETDFS_Q_DFS_RENAME *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_Rename");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_Rename(NETDFS_R_DFS_RENAME *v, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_Rename\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_Rename(const char *desc, NETDFS_R_DFS_RENAME *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_Rename");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_Move(NETDFS_Q_DFS_MOVE *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_Move\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_Move(const char *desc, NETDFS_Q_DFS_MOVE *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_Move");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_Move(NETDFS_R_DFS_MOVE *v, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_Move\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_Move(const char *desc, NETDFS_R_DFS_MOVE *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_Move");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_ManagerGetConfigInfo(NETDFS_Q_DFS_MANAGERGETCONFIGINFO *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_ManagerGetConfigInfo\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_ManagerGetConfigInfo(const char *desc, NETDFS_Q_DFS_MANAGERGETCONFIGINFO *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_ManagerGetConfigInfo");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_ManagerGetConfigInfo(NETDFS_R_DFS_MANAGERGETCONFIGINFO *v, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_ManagerGetConfigInfo\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_ManagerGetConfigInfo(const char *desc, NETDFS_R_DFS_MANAGERGETCONFIGINFO *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_ManagerGetConfigInfo");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_ManagerSendSiteInfo(NETDFS_Q_DFS_MANAGERSENDSITEINFO *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_ManagerSendSiteInfo\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_ManagerSendSiteInfo(const char *desc, NETDFS_Q_DFS_MANAGERSENDSITEINFO *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_ManagerSendSiteInfo");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_ManagerSendSiteInfo(NETDFS_R_DFS_MANAGERSENDSITEINFO *v, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_ManagerSendSiteInfo\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_ManagerSendSiteInfo(const char *desc, NETDFS_R_DFS_MANAGERSENDSITEINFO *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_ManagerSendSiteInfo");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_AddFtRoot(NETDFS_Q_DFS_ADDFTROOT *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_AddFtRoot\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_AddFtRoot(const char *desc, NETDFS_Q_DFS_ADDFTROOT *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_AddFtRoot");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_AddFtRoot(NETDFS_R_DFS_ADDFTROOT *v, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_AddFtRoot\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_AddFtRoot(const char *desc, NETDFS_R_DFS_ADDFTROOT *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_AddFtRoot");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_RemoveFtRoot(NETDFS_Q_DFS_REMOVEFTROOT *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_RemoveFtRoot\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_RemoveFtRoot(const char *desc, NETDFS_Q_DFS_REMOVEFTROOT *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_RemoveFtRoot");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_RemoveFtRoot(NETDFS_R_DFS_REMOVEFTROOT *v, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_RemoveFtRoot\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_RemoveFtRoot(const char *desc, NETDFS_R_DFS_REMOVEFTROOT *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_RemoveFtRoot");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_AddStdRoot(NETDFS_Q_DFS_ADDSTDROOT *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_AddStdRoot\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_AddStdRoot(const char *desc, NETDFS_Q_DFS_ADDSTDROOT *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_AddStdRoot");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_AddStdRoot(NETDFS_R_DFS_ADDSTDROOT *v, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_AddStdRoot\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_AddStdRoot(const char *desc, NETDFS_R_DFS_ADDSTDROOT *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_AddStdRoot");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_RemoveStdRoot(NETDFS_Q_DFS_REMOVESTDROOT *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_RemoveStdRoot\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_RemoveStdRoot(const char *desc, NETDFS_Q_DFS_REMOVESTDROOT *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_RemoveStdRoot");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_RemoveStdRoot(NETDFS_R_DFS_REMOVESTDROOT *v, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_RemoveStdRoot\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_RemoveStdRoot(const char *desc, NETDFS_R_DFS_REMOVESTDROOT *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_RemoveStdRoot");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_ManagerInitialize(NETDFS_Q_DFS_MANAGERINITIALIZE *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_ManagerInitialize\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_ManagerInitialize(const char *desc, NETDFS_Q_DFS_MANAGERINITIALIZE *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_ManagerInitialize");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_ManagerInitialize(NETDFS_R_DFS_MANAGERINITIALIZE *v, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_ManagerInitialize\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_ManagerInitialize(const char *desc, NETDFS_R_DFS_MANAGERINITIALIZE *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_ManagerInitialize");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_AddStdRootForced(NETDFS_Q_DFS_ADDSTDROOTFORCED *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_AddStdRootForced\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_AddStdRootForced(const char *desc, NETDFS_Q_DFS_ADDSTDROOTFORCED *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_AddStdRootForced");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_AddStdRootForced(NETDFS_R_DFS_ADDSTDROOTFORCED *v, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_AddStdRootForced\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_AddStdRootForced(const char *desc, NETDFS_R_DFS_ADDSTDROOTFORCED *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_AddStdRootForced");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_GetDcAddress(NETDFS_Q_DFS_GETDCADDRESS *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_GetDcAddress\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_GetDcAddress(const char *desc, NETDFS_Q_DFS_GETDCADDRESS *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_GetDcAddress");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_GetDcAddress(NETDFS_R_DFS_GETDCADDRESS *v, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_GetDcAddress\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_GetDcAddress(const char *desc, NETDFS_R_DFS_GETDCADDRESS *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_GetDcAddress");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_SetDcAddress(NETDFS_Q_DFS_SETDCADDRESS *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_SetDcAddress\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_SetDcAddress(const char *desc, NETDFS_Q_DFS_SETDCADDRESS *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_SetDcAddress");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_SetDcAddress(NETDFS_R_DFS_SETDCADDRESS *v, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_SetDcAddress\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_SetDcAddress(const char *desc, NETDFS_R_DFS_SETDCADDRESS *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_SetDcAddress");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_FlushFtTable(NETDFS_Q_DFS_FLUSHFTTABLE *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_FlushFtTable\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_FlushFtTable(const char *desc, NETDFS_Q_DFS_FLUSHFTTABLE *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_FlushFtTable");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_FlushFtTable(NETDFS_R_DFS_FLUSHFTTABLE *v, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_FlushFtTable\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_FlushFtTable(const char *desc, NETDFS_R_DFS_FLUSHFTTABLE *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_FlushFtTable");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_Add2(NETDFS_Q_DFS_ADD2 *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_Add2\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_Add2(const char *desc, NETDFS_Q_DFS_ADD2 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_Add2");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_Add2(NETDFS_R_DFS_ADD2 *v, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_Add2\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_Add2(const char *desc, NETDFS_R_DFS_ADD2 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_Add2");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_Remove2(NETDFS_Q_DFS_REMOVE2 *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_Remove2\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_Remove2(const char *desc, NETDFS_Q_DFS_REMOVE2 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_Remove2");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_Remove2(NETDFS_R_DFS_REMOVE2 *v, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_Remove2\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_Remove2(const char *desc, NETDFS_R_DFS_REMOVE2 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_Remove2");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_EnumEx(NETDFS_Q_DFS_ENUMEX *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_EnumEx\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_EnumEx(const char *desc, NETDFS_Q_DFS_ENUMEX *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_EnumEx");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_EnumEx(NETDFS_R_DFS_ENUMEX *v, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_EnumEx\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_EnumEx(const char *desc, NETDFS_R_DFS_ENUMEX *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_EnumEx");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
+BOOL init_netdfs_q_dfs_SetInfo2(NETDFS_Q_DFS_SETINFO2 *v)
+{
+       DEBUG(5,("init_netdfs_q_dfs_SetInfo2\n"));
+       
+       return True;
+}
+
+BOOL netdfs_io_q_dfs_SetInfo2(const char *desc, NETDFS_Q_DFS_SETINFO2 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_q_dfs_SetInfo2");
+       depth++;
+       return True;
+}
+
+BOOL init_netdfs_r_dfs_SetInfo2(NETDFS_R_DFS_SETINFO2 *v, WERROR status)
+{
+       DEBUG(5,("init_netdfs_r_dfs_SetInfo2\n"));
+       
+       v->status = status;
+       
+       return True;
+}
+
+BOOL netdfs_io_r_dfs_SetInfo2(const char *desc, NETDFS_R_DFS_SETINFO2 *v, prs_struct *ps, int depth)
+{
+       if (v == NULL)
+               return False;
+       
+       prs_debug(ps, depth, desc, "netdfs_io_r_dfs_SetInfo2");
+       depth++;
+       if (!prs_werror("status", ps, depth, &v->status))
+               return False;
+       
+       return True;
+}
+
index 3d28b657f332c3150ccefe5d4cb2f5759fe1e802..1edc0175106bc41f3569b57f9ac8a9d583514796 100644 (file)
@@ -508,8 +508,9 @@ BOOL lsa_io_q_enum_trust_dom(const char *desc, LSA_Q_ENUM_TRUST_DOM *q_e,
  Inits an LSA_R_ENUM_TRUST_DOM structure.
 ********************************************************************/
 
-void init_r_enum_trust_dom(TALLOC_CTX *ctx, LSA_R_ENUM_TRUST_DOM *out, uint32 enum_context,
-                          uint32 req_num_domains, uint32 num_domains, TRUSTDOM **td)
+void init_r_enum_trust_dom(TALLOC_CTX *ctx, LSA_R_ENUM_TRUST_DOM *out,
+                          uint32 enum_context, uint32 num_domains,
+                          struct trustdom_info **td)
 {
        unsigned int i;
 
@@ -523,7 +524,8 @@ void init_r_enum_trust_dom(TALLOC_CTX *ctx, LSA_R_ENUM_TRUST_DOM *out, uint32 en
                /* allocate container memory */
                
                out->domlist = TALLOC_P( ctx, DOMAIN_LIST );
-               out->domlist->domains = TALLOC_ARRAY( ctx, DOMAIN_INFO, out->count );
+               out->domlist->domains = TALLOC_ARRAY( ctx, DOMAIN_INFO,
+                                                     out->count );
                
                if ( !out->domlist || !out->domlist->domains ) {
                        out->status = NT_STATUS_NO_MEMORY;
@@ -535,13 +537,21 @@ void init_r_enum_trust_dom(TALLOC_CTX *ctx, LSA_R_ENUM_TRUST_DOM *out, uint32 en
                /* initialize the list of domains and their sid */
                
                for (i = 0; i < num_domains; i++) {     
-                       if ( !(out->domlist->domains[i].sid = TALLOC_P(ctx, DOM_SID2)) ) {
+                       smb_ucs2_t *name;
+                       if ( !(out->domlist->domains[i].sid =
+                              TALLOC_P(ctx, DOM_SID2)) ) {
                                out->status = NT_STATUS_NO_MEMORY;
                                return;
                        }
                                
-                       init_dom_sid2(out->domlist->domains[i].sid, &(td[i])->sid);
-                       init_unistr4_w(ctx, &out->domlist->domains[i].name, (td[i])->name);     
+                       init_dom_sid2(out->domlist->domains[i].sid,
+                                     &(td[i])->sid);
+                       if (push_ucs2_talloc(ctx, &name, (td[i])->name) < 0){
+                               out->status = NT_STATUS_NO_MEMORY;
+                               return;
+                       }
+                       init_unistr4_w(ctx, &out->domlist->domains[i].name,
+                                      name);
                }
        }
 
@@ -2539,8 +2549,78 @@ BOOL lsa_io_q_open_trusted_domain(const char *desc, LSA_Q_OPEN_TRUSTED_DOMAIN *i
 }
 #endif
 
+
+/*******************************************************************
+ Inits an LSA_Q_OPEN_TRUSTED_DOMAIN_BY_NAME structure.
+********************************************************************/
+
+void init_lsa_q_open_trusted_domain_by_name(LSA_Q_OPEN_TRUSTED_DOMAIN_BY_NAME *q, 
+                                           POLICY_HND *hnd, 
+                                           const char *name, 
+                                           uint32 desired_access)
+{
+       memcpy(&q->pol, hnd, sizeof(q->pol));
+
+       init_lsa_string(&q->name, name);
+       q->access_mask = desired_access;
+}
+
+/*******************************************************************
+********************************************************************/
+
+
+/*******************************************************************
+ Reads or writes an LSA_Q_OPEN_TRUSTED_DOMAIN_BY_NAME structure.
+********************************************************************/
+
+BOOL lsa_io_q_open_trusted_domain_by_name(const char *desc, LSA_Q_OPEN_TRUSTED_DOMAIN_BY_NAME *q_o, prs_struct *ps, int depth)
+{
+       prs_debug(ps, depth, desc, "lsa_io_q_open_trusted_domain_by_name");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+       if(!smb_io_pol_hnd("pol", &q_o->pol, ps, depth))
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!smb_io_lsa_string("name", &q_o->name, ps, depth))
+               return False;
+
+       if(!prs_align(ps))
+               return False;
+
+       if(!prs_uint32("access", ps, depth, &q_o->access_mask))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ Reads or writes an LSA_R_OPEN_TRUSTED_DOMAIN_BY_NAME structure.
+********************************************************************/
+
+BOOL lsa_io_r_open_trusted_domain_by_name(const char *desc, LSA_R_OPEN_TRUSTED_DOMAIN_BY_NAME *out, prs_struct *ps, int depth)
+{
+       prs_debug(ps, depth, desc, "lsa_io_r_open_trusted_domain_by_name");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+
+       if (!smb_io_pol_hnd("handle", &out->handle, ps, depth))
+               return False;
+
+       if(!prs_ntstatus("status", ps, depth, &out->status))
+               return False;
+
+       return True;
+}
+
 /*******************************************************************
- Reads or writes an LSA_Q_OPEN_TRUSTED_DOMAIN structure.
 ********************************************************************/
 
 BOOL lsa_io_q_open_trusted_domain(const char *desc, LSA_Q_OPEN_TRUSTED_DOMAIN *q_o, prs_struct *ps, int depth)
@@ -3111,3 +3191,130 @@ BOOL lsa_io_r_query_trusted_domain_info(const char *desc,
        return True;
 }
 
+/*******************************************************************
+ Inits an LSA_Q_QUERY_DOM_INFO_POLICY structure.
+********************************************************************/
+
+void init_q_query_dom_info(LSA_Q_QUERY_DOM_INFO_POLICY *in, POLICY_HND *hnd, uint16 info_class)
+{
+       DEBUG(5, ("init_q_query_dom_info\n"));
+
+       memcpy(&in->pol, hnd, sizeof(in->pol));
+
+       in->info_class = info_class;
+}
+
+/*******************************************************************
+ Reads or writes an LSA_Q_QUERY_DOM_INFO_POLICY structure.
+********************************************************************/
+
+BOOL lsa_io_q_query_dom_info(const char *desc, LSA_Q_QUERY_DOM_INFO_POLICY *in, prs_struct *ps, int depth)
+{
+       prs_debug(ps, depth, desc, "lsa_io_q_query_dom_info");
+       depth++;
+
+       if(!prs_align(ps))
+               return False;
+       if(!smb_io_pol_hnd("pol", &in->pol, ps, depth))
+               return False;
+       
+       if(!prs_uint16("info_class", ps, depth, &in->info_class))
+               return False;
+
+       return True;
+}
+
+/*******************************************************************
+ Reads or writes an LSA_R_QUERY_DOM_INFO_POLICY structure.
+********************************************************************/
+
+static BOOL lsa_io_dominfo_query_3(const char *desc, LSA_DOM_INFO_POLICY_KERBEROS *krb_policy, 
+                                  prs_struct *ps, int depth)
+{
+       if (!prs_align_uint64(ps))
+               return False;
+
+       if (!prs_align(ps))
+               return False;
+
+       if (!prs_uint32("enforce_restrictions", ps, depth, &krb_policy->enforce_restrictions))
+               return False;
+
+       if (!prs_align_uint64(ps))
+               return False;
+
+       if (!smb_io_nttime("service_tkt_lifetime", ps, depth, &krb_policy->service_tkt_lifetime))
+               return False;
+
+       if (!prs_align_uint64(ps))
+               return False;
+       
+       if (!smb_io_nttime("user_tkt_lifetime", ps, depth, &krb_policy->user_tkt_lifetime))
+               return False;
+
+       if (!prs_align_uint64(ps))
+               return False;
+       
+       if (!smb_io_nttime("user_tkt_renewaltime", ps, depth, &krb_policy->user_tkt_renewaltime))
+               return False;
+
+       if (!prs_align_uint64(ps))
+               return False;
+       
+       if (!smb_io_nttime("clock_skew", ps, depth, &krb_policy->clock_skew))
+               return False;
+
+       if (!prs_align_uint64(ps))
+               return False;
+       
+       if (!smb_io_nttime("unknown6", ps, depth, &krb_policy->unknown6))
+               return False;
+
+       return True;
+}
+
+static BOOL lsa_io_dom_info_query(const char *desc, prs_struct *ps, int depth, LSA_DOM_INFO_UNION *info)
+{
+       prs_debug(ps, depth, desc, "lsa_io_dom_info_query");
+       depth++;
+
+       if(!prs_align_uint16(ps))
+               return False;
+
+       if(!prs_uint16("info_class", ps, depth, &info->info_class))
+               return False;
+
+       switch (info->info_class) {
+       case 3: 
+               if (!lsa_io_dominfo_query_3("krb_policy", &info->krb_policy, ps, depth))
+                       return False;
+               break;
+       default:
+               DEBUG(0,("unsupported info-level: %d\n", info->info_class));
+               return False;
+               break;
+       }
+
+       return True;
+}
+
+
+BOOL lsa_io_r_query_dom_info(const char *desc, LSA_R_QUERY_DOM_INFO_POLICY *out,
+                            prs_struct *ps, int depth)
+{
+       prs_debug(ps, depth, desc, "lsa_io_r_query_dom_info");
+       depth++;
+
+       if (!prs_pointer("dominfo", ps, depth, (void**)&out->info, 
+                        sizeof(LSA_DOM_INFO_UNION), 
+                        (PRS_POINTER_CAST)lsa_io_dom_info_query) )
+               return False;
+       
+       if(!prs_ntstatus("status", ps, depth, &out->status))
+               return False;
+
+       return True;
+}
+
+
index 3bd6977dbb1491626deaaef2073ff2f97d887812..e7b1cdc767bbf8997e36e437a5725b511406ece3 100644 (file)
@@ -1396,7 +1396,7 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr,
                         uint32 user_flgs, uchar user_session_key[16],
                         uchar lm_session_key[16],
                         const char *logon_srv, const char *logon_dom,
-                        const DOM_SID *dom_sid, const char *other_sids)
+                        const DOM_SID *dom_sid)
 {
        /* only cope with one "other" sid, right now. */
        /* need to count the number of space-delimited sids */
@@ -1454,7 +1454,7 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr,
                memcpy(usr->lm_sess_key, lm_session_key, sizeof(usr->lm_sess_key));
        }
 
-       num_other_sids = init_dom_sid2s(ctx, other_sids, &usr->other_sids);
+       num_other_sids = init_dom_sid2s(ctx, NULL, &usr->other_sids);
 
        usr->num_other_sids = num_other_sids;
        usr->buffer_other_sids = (num_other_sids != 0) ? 1 : 0; 
@@ -1488,6 +1488,47 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr,
 
        init_dom_sid2(&usr->dom_sid, dom_sid);
        /* "other" sids are set up above */
+}
+
+ void dump_acct_flags(uint32 acct_flags) {
+
+       int lvl = 10;
+       DEBUG(lvl,("dump_acct_flags\n"));
+       if (acct_flags & ACB_NORMAL) {
+               DEBUGADD(lvl,("\taccount has UF_NORMAL_ACCOUNT\n"));
+       }
+       if (acct_flags & ACB_PWNOEXP) {
+               DEBUGADD(lvl,("\taccount has UF_DONT_EXPIRE_PASSWD\n"));
+       }
+       if (acct_flags & ACB_ENC_TXT_PWD_ALLOWED) {
+               DEBUGADD(lvl,("\taccount has UF_ENCRYPTED_TEXT_PASSWORD_ALLOWED\n"));
+       }
+       if (acct_flags & ACB_NOT_DELEGATED) {
+               DEBUGADD(lvl,("\taccount has UF_NOT_DELEGATED\n"));
+       }
+       if (acct_flags & ACB_USE_DES_KEY_ONLY) {
+               DEBUGADD(lvl,("\taccount has UF_USE_DES_KEY_ONLY set, sig verify wont work\n"));
+       }
+}
+
+ void dump_user_flgs(uint32 user_flags) {
+
+       int lvl = 10;
+       DEBUG(lvl,("dump_user_flgs\n"));
+       if (user_flags & LOGON_EXTRA_SIDS) {
+               DEBUGADD(lvl,("\taccount has LOGON_EXTRA_SIDS\n"));
+       }
+       if (user_flags & LOGON_RESOURCE_GROUPS) {
+               DEBUGADD(lvl,("\taccount has LOGON_RESOURCE_GROUPS\n"));
+       }
+       if (user_flags & LOGON_NTLMV2_ENABLED) {
+               DEBUGADD(lvl,("\taccount has LOGON_NTLMV2_ENABLED\n"));
+       }
+       if (user_flags & LOGON_CACHED_ACCOUNT) {
+               DEBUGADD(lvl,("\taccount has LOGON_CACHED_ACCOUNT\n"));
+       }
+
+
 }
 
 /*******************************************************************
@@ -1562,7 +1603,7 @@ BOOL net_io_user_info3(const char *desc, NET_USER_INFO_3 *usr, prs_struct *ps,
                return False;
        if(!prs_uint32("user_flgs     ", ps, depth, &usr->user_flgs))     /* user flags */
                return False;
-
+       dump_user_flgs(usr->user_flgs);
        if(!prs_uint8s(False, "user_sess_key", ps, depth, usr->user_sess_key, 16)) /* user session key */
                return False;
 
@@ -1579,7 +1620,7 @@ BOOL net_io_user_info3(const char *desc, NET_USER_INFO_3 *usr, prs_struct *ps,
 
        if(!prs_uint32("acct_flags ", ps, depth, &usr->acct_flags)) /* Account flags  */
                return False;
-
+       dump_acct_flags(usr->acct_flags);
        for (i = 0; i < 7; i++)
        {
                if (!prs_uint32("unkown", ps, depth, &usr->unknown[i])) /* unknown */
index 7c84ee800b94031effd8b8172a0bd703c4db8d7e..c4f9f512ab72b6cce951f4ced13fbb176ca574fc 100644 (file)
@@ -1303,6 +1303,35 @@ BOOL prs_string(const char *name, prs_struct *ps, int depth, char *str, int max_
        return True;
 }
 
+BOOL prs_string_alloc(const char *name, prs_struct *ps, int depth, const char **str)
+{
+       size_t len;
+       char *tmp_str;
+
+       if (UNMARSHALLING(ps)) {
+               len = strlen(&ps->data_p[ps->data_offset]);
+       } else {
+               len = strlen(*str);
+       }
+
+       tmp_str = PRS_ALLOC_MEM(ps, char, len+1);
+
+       if (tmp_str == NULL) {
+               return False;
+       }
+
+       if (MARSHALLING(ps)) {
+               strncpy(tmp_str, *str, len);
+       }
+
+       if (!prs_string(name, ps, depth, tmp_str, len+1)) {
+               return False;
+       }
+
+       *str = tmp_str;
+       return True;
+}
+
 /*******************************************************************
  prs_uint16 wrapper. Call this and it sets up a pointer to where the
  uint16 should be stored, or gets the size if reading.
index ea4ec2c8639d33526a67cfa83e0ef0cdbae89343..544d139acb363bc06a3ee13a69651960d2497467 100644 (file)
@@ -191,16 +191,6 @@ interface/version dce/rpc pipe identification
        }, 0x00                             \
 }
 
-#define SYNT_UNIXINFO_V0                    \
-{                                           \
-       {                                   \
-               0x9c54e310, 0xa955, 0x4885, \
-               { 0xbd, 0x31 },             \
-                { 0x78, 0x78,               \
-                  0x71, 0x47, 0xdf, 0xa6 }  \
-       }, 0x00                             \
-}
-
 #define SYNT_NTSVCS_V1                      \
 {                                           \
        {                                   \
index 6c2b4f4ea71c0546e075a1554669149c05276601..7cbaa4e3c993216bcff833f2bbe8499c60417c68 100644 (file)
@@ -5031,7 +5031,7 @@ inits a SAMR_Q_QUERY_USERINFO structure.
 ********************************************************************/
 
 void init_samr_q_query_userinfo(SAMR_Q_QUERY_USERINFO * q_u,
-                               POLICY_HND *hnd, uint16 switch_value)
+                               const POLICY_HND *hnd, uint16 switch_value)
 {
        DEBUG(5, ("init_samr_q_query_userinfo\n"));
 
@@ -6541,7 +6541,7 @@ inits a SAMR_Q_SET_USERINFO structure.
 ********************************************************************/
 
 void init_samr_q_set_userinfo(SAMR_Q_SET_USERINFO * q_u,
-                             POLICY_HND *hnd, DATA_BLOB *sess_key,
+                             const POLICY_HND *hnd, DATA_BLOB *sess_key,
                              uint16 switch_value, void *info)
 {
        DEBUG(5, ("init_samr_q_set_userinfo\n"));
@@ -6615,7 +6615,7 @@ inits a SAMR_Q_SET_USERINFO2 structure.
 ********************************************************************/
 
 void init_samr_q_set_userinfo2(SAMR_Q_SET_USERINFO2 * q_u,
-                              POLICY_HND *hnd, DATA_BLOB *sess_key,
+                              const POLICY_HND *hnd, DATA_BLOB *sess_key,
                               uint16 switch_value, SAM_USERINFO_CTR * ctr)
 {
        DEBUG(5, ("init_samr_q_set_userinfo2\n"));
index 42be7c5a35776d6cc8d31786f07eb00f25c5f36f..44a9c06a3caff9c92c5a50898f1e95ead3106b6a 100644 (file)
-/* 
- *  Unix SMB/CIFS implementation.
- *  RPC Pipe client / server routines for Dfs
- *  Copyright (C) Andrew Tridgell              1992-1997,
- *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
- *  Copyright (C) Shirish Kalele                    2000,
- *  Copyright (C) Jeremy Allison                    2001,
- *  Copyright (C) Jim McDonough <jmcd@us.ibm.com>   2003.
- *  
- *  This program is free software; you can redistribute it and/or modify
- *  it under the terms of the GNU General Public License as published by
- *  the Free Software Foundation; either version 2 of the License, or
- *  (at your option) any later version.
- *  
- *  This program is distributed in the hope that it will be useful,
- *  but WITHOUT ANY WARRANTY; without even the implied warranty of
- *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
- *  GNU General Public License for more details.
- *  
- *  You should have received a copy of the GNU General Public License
- *  along with this program; if not, write to the Free Software
- *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+/*
+ * Unix SMB/CIFS implementation.
+ * server auto-generated by pidl. DO NOT MODIFY!
  */
 
-/* This is the interface to the dfs pipe. */
-
 #include "includes.h"
 #include "nterr.h"
 
 #undef DBGC_CLASS
-#define DBGC_CLASS DBGC_MSDFS
+#define DBGC_CLASS DBGC_RPC
 
-/**********************************************************************
- api_dfs_exist
- **********************************************************************/
+/******************************************************************
+ api_dfs_GetManagerVersion
+ *****************************************************************/
 
-static BOOL api_dfs_exist(pipes_struct *p)
+static BOOL api_dfs_GetManagerVersion(pipes_struct *p)
 {
-       DFS_Q_DFS_EXIST q_u;
-       DFS_R_DFS_EXIST r_u;
+       NETDFS_Q_DFS_GETMANAGERVERSION q_u;
+       NETDFS_R_DFS_GETMANAGERVERSION r_u;
        prs_struct *data = &p->in_data.data;
        prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_GetManagerVersion("", &q_u, data, 0))
+               return False;
+       
+       _dfs_GetManagerVersion(p, &q_u, &r_u);
+       
+       if (!netdfs_io_r_dfs_GetManagerVersion("", &r_u, rdata, 0))
+               return False;
+       
+       return True;
+}
+/******************************************************************
+ api_dfs_Add
+ *****************************************************************/
 
-       if(!dfs_io_q_dfs_exist("", &q_u, data, 0))
+static BOOL api_dfs_Add(pipes_struct *p)
+{
+       NETDFS_Q_DFS_ADD q_u;
+       NETDFS_R_DFS_ADD r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_Add("", &q_u, data, 0))
                return False;
        
-       r_u.status = _dfs_exist(p, &q_u, &r_u);
+       r_u.status = _dfs_Add(p, &q_u, &r_u);
        
-       if (!dfs_io_r_dfs_exist("", &r_u, rdata, 0))
+       if (!netdfs_io_r_dfs_Add("", &r_u, rdata, 0))
                return False;
+       
+       return True;
+}
+/******************************************************************
+ api_dfs_Remove
+ *****************************************************************/
 
+static BOOL api_dfs_Remove(pipes_struct *p)
+{
+       NETDFS_Q_DFS_REMOVE q_u;
+       NETDFS_R_DFS_REMOVE r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_Remove("", &q_u, data, 0))
+               return False;
+       
+       r_u.status = _dfs_Remove(p, &q_u, &r_u);
+       
+       if (!netdfs_io_r_dfs_Remove("", &r_u, rdata, 0))
+               return False;
+       
        return True;
 }
+/******************************************************************
+ api_dfs_SetInfo
+ *****************************************************************/
 
-/*****************************************************************
- api_dfs_add
+static BOOL api_dfs_SetInfo(pipes_struct *p)
+{
+       NETDFS_Q_DFS_SETINFO q_u;
+       NETDFS_R_DFS_SETINFO r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_SetInfo("", &q_u, data, 0))
+               return False;
+       
+       r_u.status = _dfs_SetInfo(p, &q_u, &r_u);
+       
+       if (!netdfs_io_r_dfs_SetInfo("", &r_u, rdata, 0))
+               return False;
+       
+       return True;
+}
+/******************************************************************
+ api_dfs_GetInfo
  *****************************************************************/
 
-static BOOL api_dfs_add(pipes_struct *p)
+static BOOL api_dfs_GetInfo(pipes_struct *p)
 {
-       DFS_Q_DFS_ADD q_u;
-       DFS_R_DFS_ADD r_u;
+       NETDFS_Q_DFS_GETINFO q_u;
+       NETDFS_R_DFS_GETINFO r_u;
        prs_struct *data = &p->in_data.data;
        prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_GetInfo("", &q_u, data, 0))
+               return False;
+       
+       r_u.status = _dfs_GetInfo(p, &q_u, &r_u);
+       
+       if (!netdfs_io_r_dfs_GetInfo("", &r_u, rdata, 0))
+               return False;
+       
+       return True;
+}
+/******************************************************************
+ api_dfs_Enum
+ *****************************************************************/
 
+static BOOL api_dfs_Enum(pipes_struct *p)
+{
+       NETDFS_Q_DFS_ENUM q_u;
+       NETDFS_R_DFS_ENUM r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       
        ZERO_STRUCT(q_u);
        ZERO_STRUCT(r_u);
        
-       if(!dfs_io_q_dfs_add("", &q_u, data, 0))
+       if (!netdfs_io_q_dfs_Enum("", &q_u, data, 0))
                return False;
        
-       r_u.status = _dfs_add(p, &q_u, &r_u);
+       r_u.status = _dfs_Enum(p, &q_u, &r_u);
        
-       if (!dfs_io_r_dfs_add("", &r_u, rdata, 0))
+       if (!netdfs_io_r_dfs_Enum("", &r_u, rdata, 0))
                return False;
        
        return True;
 }
+/******************************************************************
+ api_dfs_Rename
+ *****************************************************************/
 
-/*****************************************************************
- api_dfs_remove
+static BOOL api_dfs_Rename(pipes_struct *p)
+{
+       NETDFS_Q_DFS_RENAME q_u;
+       NETDFS_R_DFS_RENAME r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_Rename("", &q_u, data, 0))
+               return False;
+       
+       r_u.status = _dfs_Rename(p, &q_u, &r_u);
+       
+       if (!netdfs_io_r_dfs_Rename("", &r_u, rdata, 0))
+               return False;
+       
+       return True;
+}
+/******************************************************************
+ api_dfs_Move
  *****************************************************************/
 
-static BOOL api_dfs_remove(pipes_struct *p)
+static BOOL api_dfs_Move(pipes_struct *p)
 {
-       DFS_Q_DFS_REMOVE q_u;
-       DFS_R_DFS_REMOVE r_u;
+       NETDFS_Q_DFS_MOVE q_u;
+       NETDFS_R_DFS_MOVE r_u;
        prs_struct *data = &p->in_data.data;
        prs_struct *rdata = &p->out_data.rdata;
        
        ZERO_STRUCT(q_u);
        ZERO_STRUCT(r_u);
        
-       if(!dfs_io_q_dfs_remove("", &q_u, data, 0))
+       if (!netdfs_io_q_dfs_Move("", &q_u, data, 0))
                return False;
        
-       r_u.status = _dfs_remove(p, &q_u, &r_u);
+       r_u.status = _dfs_Move(p, &q_u, &r_u);
        
-       if (!dfs_io_r_dfs_remove("", &r_u, rdata, 0))
+       if (!netdfs_io_r_dfs_Move("", &r_u, rdata, 0))
                return False;
        
        return True;
 }
+/******************************************************************
+ api_dfs_ManagerGetConfigInfo
+ *****************************************************************/
 
-/*******************************************************************
- api_dfs_get_info
- *******************************************************************/
+static BOOL api_dfs_ManagerGetConfigInfo(pipes_struct *p)
+{
+       NETDFS_Q_DFS_MANAGERGETCONFIGINFO q_u;
+       NETDFS_R_DFS_MANAGERGETCONFIGINFO r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_ManagerGetConfigInfo("", &q_u, data, 0))
+               return False;
+       
+       r_u.status = _dfs_ManagerGetConfigInfo(p, &q_u, &r_u);
+       
+       if (!netdfs_io_r_dfs_ManagerGetConfigInfo("", &r_u, rdata, 0))
+               return False;
+       
+       return True;
+}
+/******************************************************************
+ api_dfs_ManagerSendSiteInfo
+ *****************************************************************/
 
-static BOOL api_dfs_get_info(pipes_struct *p)
+static BOOL api_dfs_ManagerSendSiteInfo(pipes_struct *p)
 {
-       DFS_Q_DFS_GET_INFO q_u;
-       DFS_R_DFS_GET_INFO r_u;
+       NETDFS_Q_DFS_MANAGERSENDSITEINFO q_u;
+       NETDFS_R_DFS_MANAGERSENDSITEINFO r_u;
        prs_struct *data = &p->in_data.data;
        prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_ManagerSendSiteInfo("", &q_u, data, 0))
+               return False;
+       
+       r_u.status = _dfs_ManagerSendSiteInfo(p, &q_u, &r_u);
+       
+       if (!netdfs_io_r_dfs_ManagerSendSiteInfo("", &r_u, rdata, 0))
+               return False;
+       
+       return True;
+}
+/******************************************************************
+ api_dfs_AddFtRoot
+ *****************************************************************/
 
+static BOOL api_dfs_AddFtRoot(pipes_struct *p)
+{
+       NETDFS_Q_DFS_ADDFTROOT q_u;
+       NETDFS_R_DFS_ADDFTROOT r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       
        ZERO_STRUCT(q_u);
        ZERO_STRUCT(r_u);
        
-       if(!dfs_io_q_dfs_get_info("", &q_u, data, 0))
+       if (!netdfs_io_q_dfs_AddFtRoot("", &q_u, data, 0))
                return False;
        
-       r_u.status = _dfs_get_info(p, &q_u, &r_u);
+       r_u.status = _dfs_AddFtRoot(p, &q_u, &r_u);
        
-       if(!dfs_io_r_dfs_get_info("", &r_u, rdata, 0))
+       if (!netdfs_io_r_dfs_AddFtRoot("", &r_u, rdata, 0))
                return False;
+       
+       return True;
+}
+/******************************************************************
+ api_dfs_RemoveFtRoot
+ *****************************************************************/
 
+static BOOL api_dfs_RemoveFtRoot(pipes_struct *p)
+{
+       NETDFS_Q_DFS_REMOVEFTROOT q_u;
+       NETDFS_R_DFS_REMOVEFTROOT r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_RemoveFtRoot("", &q_u, data, 0))
+               return False;
+       
+       r_u.status = _dfs_RemoveFtRoot(p, &q_u, &r_u);
+       
+       if (!netdfs_io_r_dfs_RemoveFtRoot("", &r_u, rdata, 0))
+               return False;
+       
        return True;
 }
+/******************************************************************
+ api_dfs_AddStdRoot
+ *****************************************************************/
 
-/*******************************************************************
- api_dfs_enum
- *******************************************************************/
+static BOOL api_dfs_AddStdRoot(pipes_struct *p)
+{
+       NETDFS_Q_DFS_ADDSTDROOT q_u;
+       NETDFS_R_DFS_ADDSTDROOT r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_AddStdRoot("", &q_u, data, 0))
+               return False;
+       
+       r_u.status = _dfs_AddStdRoot(p, &q_u, &r_u);
+       
+       if (!netdfs_io_r_dfs_AddStdRoot("", &r_u, rdata, 0))
+               return False;
+       
+       return True;
+}
+/******************************************************************
+ api_dfs_RemoveStdRoot
+ *****************************************************************/
 
-static BOOL api_dfs_enum(pipes_struct *p)
+static BOOL api_dfs_RemoveStdRoot(pipes_struct *p)
 {
-       DFS_Q_DFS_ENUM q_u;
-       DFS_R_DFS_ENUM r_u;
+       NETDFS_Q_DFS_REMOVESTDROOT q_u;
+       NETDFS_R_DFS_REMOVESTDROOT r_u;
        prs_struct *data = &p->in_data.data;
        prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_RemoveStdRoot("", &q_u, data, 0))
+               return False;
+       
+       r_u.status = _dfs_RemoveStdRoot(p, &q_u, &r_u);
+       
+       if (!netdfs_io_r_dfs_RemoveStdRoot("", &r_u, rdata, 0))
+               return False;
+       
+       return True;
+}
+/******************************************************************
+ api_dfs_ManagerInitialize
+ *****************************************************************/
 
+static BOOL api_dfs_ManagerInitialize(pipes_struct *p)
+{
+       NETDFS_Q_DFS_MANAGERINITIALIZE q_u;
+       NETDFS_R_DFS_MANAGERINITIALIZE r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       
        ZERO_STRUCT(q_u);
        ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_ManagerInitialize("", &q_u, data, 0))
+               return False;
+       
+       r_u.status = _dfs_ManagerInitialize(p, &q_u, &r_u);
+       
+       if (!netdfs_io_r_dfs_ManagerInitialize("", &r_u, rdata, 0))
+               return False;
+       
+       return True;
+}
+/******************************************************************
+ api_dfs_AddStdRootForced
+ *****************************************************************/
 
-       if(!dfs_io_q_dfs_enum("", &q_u, data, 0))
+static BOOL api_dfs_AddStdRootForced(pipes_struct *p)
+{
+       NETDFS_Q_DFS_ADDSTDROOTFORCED q_u;
+       NETDFS_R_DFS_ADDSTDROOTFORCED r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_AddStdRootForced("", &q_u, data, 0))
                return False;
        
-       r_u.status = _dfs_enum(p, &q_u, &r_u);
+       r_u.status = _dfs_AddStdRootForced(p, &q_u, &r_u);
        
-       if(!dfs_io_r_dfs_enum("", &r_u, rdata, 0))
+       if (!netdfs_io_r_dfs_AddStdRootForced("", &r_u, rdata, 0))
                return False;
+       
+       return True;
+}
+/******************************************************************
+ api_dfs_GetDcAddress
+ *****************************************************************/
 
+static BOOL api_dfs_GetDcAddress(pipes_struct *p)
+{
+       NETDFS_Q_DFS_GETDCADDRESS q_u;
+       NETDFS_R_DFS_GETDCADDRESS r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_GetDcAddress("", &q_u, data, 0))
+               return False;
+       
+       r_u.status = _dfs_GetDcAddress(p, &q_u, &r_u);
+       
+       if (!netdfs_io_r_dfs_GetDcAddress("", &r_u, rdata, 0))
+               return False;
+       
+       return True;
+}
+/******************************************************************
+ api_dfs_SetDcAddress
+ *****************************************************************/
+
+static BOOL api_dfs_SetDcAddress(pipes_struct *p)
+{
+       NETDFS_Q_DFS_SETDCADDRESS q_u;
+       NETDFS_R_DFS_SETDCADDRESS r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_SetDcAddress("", &q_u, data, 0))
+               return False;
+       
+       r_u.status = _dfs_SetDcAddress(p, &q_u, &r_u);
+       
+       if (!netdfs_io_r_dfs_SetDcAddress("", &r_u, rdata, 0))
+               return False;
+       
+       return True;
+}
+/******************************************************************
+ api_dfs_FlushFtTable
+ *****************************************************************/
+
+static BOOL api_dfs_FlushFtTable(pipes_struct *p)
+{
+       NETDFS_Q_DFS_FLUSHFTTABLE q_u;
+       NETDFS_R_DFS_FLUSHFTTABLE r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_FlushFtTable("", &q_u, data, 0))
+               return False;
+       
+       r_u.status = _dfs_FlushFtTable(p, &q_u, &r_u);
+       
+       if (!netdfs_io_r_dfs_FlushFtTable("", &r_u, rdata, 0))
+               return False;
+       
+       return True;
+}
+/******************************************************************
+ api_dfs_Add2
+ *****************************************************************/
+
+static BOOL api_dfs_Add2(pipes_struct *p)
+{
+       NETDFS_Q_DFS_ADD2 q_u;
+       NETDFS_R_DFS_ADD2 r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_Add2("", &q_u, data, 0))
+               return False;
+       
+       r_u.status = _dfs_Add2(p, &q_u, &r_u);
+       
+       if (!netdfs_io_r_dfs_Add2("", &r_u, rdata, 0))
+               return False;
+       
+       return True;
+}
+/******************************************************************
+ api_dfs_Remove2
+ *****************************************************************/
+
+static BOOL api_dfs_Remove2(pipes_struct *p)
+{
+       NETDFS_Q_DFS_REMOVE2 q_u;
+       NETDFS_R_DFS_REMOVE2 r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_Remove2("", &q_u, data, 0))
+               return False;
+       
+       r_u.status = _dfs_Remove2(p, &q_u, &r_u);
+       
+       if (!netdfs_io_r_dfs_Remove2("", &r_u, rdata, 0))
+               return False;
+       
+       return True;
+}
+/******************************************************************
+ api_dfs_EnumEx
+ *****************************************************************/
+
+static BOOL api_dfs_EnumEx(pipes_struct *p)
+{
+       NETDFS_Q_DFS_ENUMEX q_u;
+       NETDFS_R_DFS_ENUMEX r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_EnumEx("", &q_u, data, 0))
+               return False;
+       
+       r_u.status = _dfs_EnumEx(p, &q_u, &r_u);
+       
+       if (!netdfs_io_r_dfs_EnumEx("", &r_u, rdata, 0))
+               return False;
+       
+       return True;
+}
+/******************************************************************
+ api_dfs_SetInfo2
+ *****************************************************************/
+
+static BOOL api_dfs_SetInfo2(pipes_struct *p)
+{
+       NETDFS_Q_DFS_SETINFO2 q_u;
+       NETDFS_R_DFS_SETINFO2 r_u;
+       prs_struct *data = &p->in_data.data;
+       prs_struct *rdata = &p->out_data.rdata;
+       
+       ZERO_STRUCT(q_u);
+       ZERO_STRUCT(r_u);
+       
+       if (!netdfs_io_q_dfs_SetInfo2("", &q_u, data, 0))
+               return False;
+       
+       r_u.status = _dfs_SetInfo2(p, &q_u, &r_u);
+       
+       if (!netdfs_io_r_dfs_SetInfo2("", &r_u, rdata, 0))
+               return False;
+       
        return True;
 }
 
-/*******************************************************************
-\pipe\netdfs commands
-********************************************************************/
-static struct api_struct api_netdfs_cmds[] =
+/* Tables */
+static struct api_struct api_netdfs_cmds[] = 
 {
-      {"DFS_EXIST",        DFS_EXIST,               api_dfs_exist    },
-      {"DFS_ADD",          DFS_ADD,                 api_dfs_add      },
-      {"DFS_REMOVE",       DFS_REMOVE,              api_dfs_remove   },
-      {"DFS_GET_INFO",     DFS_GET_INFO,            api_dfs_get_info },
-      {"DFS_ENUM",         DFS_ENUM,                api_dfs_enum     }
+       {"DFS_GETMANAGERVERSION", DFS_GETMANAGERVERSION, api_dfs_GetManagerVersion},
+       {"DFS_ADD", DFS_ADD, api_dfs_Add},
+       {"DFS_REMOVE", DFS_REMOVE, api_dfs_Remove},
+       {"DFS_SETINFO", DFS_SETINFO, api_dfs_SetInfo},
+       {"DFS_GETINFO", DFS_GETINFO, api_dfs_GetInfo},
+       {"DFS_ENUM", DFS_ENUM, api_dfs_Enum},
+       {"DFS_RENAME", DFS_RENAME, api_dfs_Rename},
+       {"DFS_MOVE", DFS_MOVE, api_dfs_Move},
+       {"DFS_MANAGERGETCONFIGINFO", DFS_MANAGERGETCONFIGINFO, api_dfs_ManagerGetConfigInfo},
+       {"DFS_MANAGERSENDSITEINFO", DFS_MANAGERSENDSITEINFO, api_dfs_ManagerSendSiteInfo},
+       {"DFS_ADDFTROOT", DFS_ADDFTROOT, api_dfs_AddFtRoot},
+       {"DFS_REMOVEFTROOT", DFS_REMOVEFTROOT, api_dfs_RemoveFtRoot},
+       {"DFS_ADDSTDROOT", DFS_ADDSTDROOT, api_dfs_AddStdRoot},
+       {"DFS_REMOVESTDROOT", DFS_REMOVESTDROOT, api_dfs_RemoveStdRoot},
+       {"DFS_MANAGERINITIALIZE", DFS_MANAGERINITIALIZE, api_dfs_ManagerInitialize},
+       {"DFS_ADDSTDROOTFORCED", DFS_ADDSTDROOTFORCED, api_dfs_AddStdRootForced},
+       {"DFS_GETDCADDRESS", DFS_GETDCADDRESS, api_dfs_GetDcAddress},
+       {"DFS_SETDCADDRESS", DFS_SETDCADDRESS, api_dfs_SetDcAddress},
+       {"DFS_FLUSHFTTABLE", DFS_FLUSHFTTABLE, api_dfs_FlushFtTable},
+       {"DFS_ADD2", DFS_ADD2, api_dfs_Add2},
+       {"DFS_REMOVE2", DFS_REMOVE2, api_dfs_Remove2},
+       {"DFS_ENUMEX", DFS_ENUMEX, api_dfs_EnumEx},
+       {"DFS_SETINFO2", DFS_SETINFO2, api_dfs_SetInfo2},
 };
 
-void netdfs_get_pipe_fns( struct api_struct **fns, int *n_fns )
+void netdfs_get_pipe_fns(struct api_struct **fns, int *n_fns)
 {
        *fns = api_netdfs_cmds;
        *n_fns = sizeof(api_netdfs_cmds) / sizeof(struct api_struct);
 }
 
-NTSTATUS rpc_dfs_init(void)
+NTSTATUS rpc_netdfs_init(void)
 {
-  return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "netdfs", "netdfs", api_netdfs_cmds,
-                                   sizeof(api_netdfs_cmds) / sizeof(struct api_struct));
+       return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "netdfs", "netdfs", api_netdfs_cmds, sizeof(api_netdfs_cmds) / sizeof(struct api_struct));
 }
index 63e4d4e9b7c175cf1a3f143dd15663ec46dc314c..f04d8c37c3d4c6d6994f270ff287d2611d4a7e9b 100644 (file)
@@ -1,10 +1,9 @@
 /* 
  *  Unix SMB/CIFS implementation.
  *  RPC Pipe client / server routines for Dfs
- *  Copyright (C) Andrew Tridgell              1992-1997,
- *  Copyright (C) Luke Kenneth Casson Leighton 1996-1997,
- *  Copyright (C) Shirish Kalele               2000.
- *  Copyright (C) Jeremy Allison                               2001.
+ *  Copyright (C) Shirish Kalele       2000.
+ *  Copyright (C) Jeremy Allison       2001.
+ *  Copyright (C) Jelmer Vernooij      2005.
  *  
  *  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
@@ -24,7 +23,6 @@
 /* This is the implementation of the dfs pipe. */
 
 #include "includes.h"
-#include "nterr.h"
 
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_MSDFS
@@ -32,7 +30,7 @@
 /* This function does not return a WERROR or NTSTATUS code but rather 1 if
    dfs exists, or 0 otherwise. */
 
-uint32 _dfs_exist(pipes_struct *p, DFS_Q_DFS_EXIST *q_u, DFS_R_DFS_EXIST *r_u)
+uint32 _dfs_GetManagerVersion(pipes_struct *p, NETDFS_Q_DFS_GETMANAGERVERSION *q_u, NETDFS_R_DFS_GETMANAGERVERSION *r_u)
 {
        if(lp_host_msdfs()) 
                return 1;
@@ -40,7 +38,7 @@ uint32 _dfs_exist(pipes_struct *p, DFS_Q_DFS_EXIST *q_u, DFS_R_DFS_EXIST *r_u)
                return 0;
 }
 
-WERROR _dfs_add(pipes_struct *p, DFS_Q_DFS_ADD* q_u, DFS_R_DFS_ADD *r_u)
+WERROR _dfs_Add(pipes_struct *p, NETDFS_Q_DFS_ADD* q_u, NETDFS_R_DFS_ADD *r_u)
 {
        struct current_user user;
        struct junction_map jn;
@@ -57,9 +55,9 @@ WERROR _dfs_add(pipes_struct *p, DFS_Q_DFS_ADD* q_u, DFS_R_DFS_ADD *r_u)
                return WERR_ACCESS_DENIED;
        }
 
-       unistr2_to_ascii(dfspath, &q_u->DfsEntryPath, sizeof(dfspath)-1);
-       unistr2_to_ascii(servername, &q_u->ServerName, sizeof(servername)-1);
-       unistr2_to_ascii(sharename, &q_u->ShareName, sizeof(sharename)-1);
+       unistr2_to_ascii(dfspath, &q_u->path, sizeof(dfspath)-1);
+       unistr2_to_ascii(servername, &q_u->server, sizeof(servername)-1);
+       unistr2_to_ascii(sharename, &q_u->share, sizeof(sharename)-1);
 
        DEBUG(5,("init_reply_dfs_add: Request to add %s -> %s\\%s.\n",
                dfspath, servername, sharename));
@@ -103,8 +101,8 @@ WERROR _dfs_add(pipes_struct *p, DFS_Q_DFS_ADD* q_u, DFS_R_DFS_ADD *r_u)
        return WERR_OK;
 }
 
-WERROR _dfs_remove(pipes_struct *p, DFS_Q_DFS_REMOVE *q_u, 
-                   DFS_R_DFS_REMOVE *r_u)
+WERROR _dfs_Remove(pipes_struct *p, NETDFS_Q_DFS_REMOVE *q_u, 
+                   NETDFS_R_DFS_REMOVE *r_u)
 {
        struct current_user user;
        struct junction_map jn;
@@ -120,16 +118,16 @@ WERROR _dfs_remove(pipes_struct *p, DFS_Q_DFS_REMOVE *q_u,
                return WERR_ACCESS_DENIED;
        }
 
-       unistr2_to_ascii(dfspath, &q_u->DfsEntryPath, sizeof(dfspath)-1);
-       if(q_u->ptr_ServerName) {
-               unistr2_to_ascii(servername, &q_u->ServerName, sizeof(servername)-1);
+       unistr2_to_ascii(dfspath, &q_u->path, sizeof(dfspath)-1);
+       if(q_u->ptr0_server) {
+               unistr2_to_ascii(servername, &q_u->server, sizeof(servername)-1);
        }
 
-       if(q_u->ptr_ShareName) {
-               unistr2_to_ascii(sharename, &q_u->ShareName, sizeof(sharename)-1);
+       if(q_u->ptr0_share) {
+               unistr2_to_ascii(sharename, &q_u->share, sizeof(sharename)-1);
        }
 
-       if(q_u->ptr_ServerName && q_u->ptr_ShareName) {
+       if(q_u->ptr0_server && q_u->ptr0_share) {
                pstrcpy(altpath, servername);
                pstrcat(altpath, "\\");
                pstrcat(altpath, sharename);
@@ -144,7 +142,7 @@ WERROR _dfs_remove(pipes_struct *p, DFS_Q_DFS_REMOVE *q_u,
        }
 
        /* if no server-share pair given, remove the msdfs link completely */
-       if(!q_u->ptr_ServerName && !q_u->ptr_ShareName) {
+       if(!q_u->ptr0_server && !q_u->ptr0_share) {
                if(!remove_msdfs_link(&jn)) {
                        vfs_ChDir(p->conn,p->conn->connectpath);
                        return WERR_DFS_NO_SUCH_VOL;
@@ -189,167 +187,164 @@ WERROR _dfs_remove(pipes_struct *p, DFS_Q_DFS_REMOVE *q_u,
        return WERR_OK;
 }
 
-static BOOL init_reply_dfs_info_1(struct junction_map* j, DFS_INFO_1* dfs1, int num_j)
+static BOOL init_reply_dfs_info_1(struct junction_map* j, NETDFS_DFS_INFO1* dfs1)
 {
-       int i=0;
-       for(i=0;i<num_j;i++) {
-               pstring str;
-               dfs1[i].ptr_entrypath = 1;
-               slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname(), 
-                       j[i].service_name, j[i].volume_name);
-               DEBUG(5,("init_reply_dfs_info_1: %d) initing entrypath: %s\n",i,str));
-               init_unistr2(&dfs1[i].entrypath,str,UNI_STR_TERMINATE);
-       }
+       pstring str;
+       dfs1->ptr0_path = 1;
+       slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname(), 
+               j->service_name, j->volume_name);
+       DEBUG(5,("init_reply_dfs_info_1: initing entrypath: %s\n",str));
+       init_unistr2(&dfs1->path,str,UNI_STR_TERMINATE);
        return True;
 }
 
-static BOOL init_reply_dfs_info_2(struct junction_map* j, DFS_INFO_2* dfs2, int num_j)
+static BOOL init_reply_dfs_info_2(struct junction_map* j, NETDFS_DFS_INFO2* dfs2)
 {
-       int i=0;
-       for(i=0;i<num_j;i++) {
-               pstring str;
-               dfs2[i].ptr_entrypath = 1;
-               slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname(),
-                       j[i].service_name, j[i].volume_name);
-               init_unistr2(&dfs2[i].entrypath, str, UNI_STR_TERMINATE);
-               dfs2[i].ptr_comment = 0;
-               dfs2[i].state = 1; /* set up state of dfs junction as OK */
-               dfs2[i].num_storages = j[i].referral_count;
-       }
+       pstring str;
+       dfs2->ptr0_path = 1;
+       slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname(),
+               j->service_name, j->volume_name);
+       init_unistr2(&dfs2->path, str, UNI_STR_TERMINATE);
+       dfs2->ptr0_comment = 0;
+       dfs2->state = 1; /* set up state of dfs junction as OK */
+       dfs2->num_stores = j->referral_count;
        return True;
 }
 
-static BOOL init_reply_dfs_info_3(TALLOC_CTX *ctx, struct junction_map* j, DFS_INFO_3* dfs3, int num_j)
+static BOOL init_reply_dfs_info_3(TALLOC_CTX *ctx, struct junction_map* j, NETDFS_DFS_INFO3* dfs3)
 {
-       int i=0,ii=0;
-       for(i=0;i<num_j;i++) {
-               pstring str;
-               dfs3[i].ptr_entrypath = 1;
-               if (j[i].volume_name[0] == '\0')
-                       slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s",
-                               global_myname(), j[i].service_name);
-               else
-                       slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname(),
-                               j[i].service_name, j[i].volume_name);
-
-               init_unistr2(&dfs3[i].entrypath, str, UNI_STR_TERMINATE);
-               dfs3[i].ptr_comment = 1;
-               init_unistr2(&dfs3[i].comment, "", UNI_STR_TERMINATE);
-               dfs3[i].state = 1;
-               dfs3[i].num_storages = dfs3[i].num_storage_infos = j[i].referral_count;
-               dfs3[i].ptr_storages = 1;
-     
-               /* also enumerate the storages */
-               dfs3[i].storages = TALLOC_ARRAY(ctx, DFS_STORAGE_INFO, j[i].referral_count);
-               if (!dfs3[i].storages)
-                       return False;
-
-               memset(dfs3[i].storages, '\0', j[i].referral_count * sizeof(DFS_STORAGE_INFO));
-
-               for(ii=0;ii<j[i].referral_count;ii++) {
-                       char* p; 
-                       pstring path;
-                       DFS_STORAGE_INFO* stor = &(dfs3[i].storages[ii]);
-                       struct referral* ref = &(j[i].referral_list[ii]);
-         
-                       pstrcpy(path, ref->alternate_path);
-                       trim_char(path,'\\','\0');
-                       p = strrchr_m(path,'\\');
-                       if(p==NULL) {
-                               DEBUG(4,("init_reply_dfs_info_3: invalid path: no \\ found in %s\n",path));
-                               continue;
-                       }
-                       *p = '\0';
-                       DEBUG(5,("storage %d: %s.%s\n",ii,path,p+1));
-                       stor->state = 2; /* set all storages as ONLINE */
-                       init_unistr2(&stor->servername, path, UNI_STR_TERMINATE);
-                       init_unistr2(&stor->sharename,  p+1, UNI_STR_TERMINATE);
-                       stor->ptr_servername = stor->ptr_sharename = 1;
+       int ii;
+       pstring str;
+       dfs3->ptr0_path = 1;
+       if (j->volume_name[0] == '\0')
+               slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s",
+                       global_myname(), j->service_name);
+       else
+               slprintf(str, sizeof(pstring)-1, "\\\\%s\\%s\\%s", global_myname(),
+                       j->service_name, j->volume_name);
+
+       init_unistr2(&dfs3->path, str, UNI_STR_TERMINATE);
+       dfs3->ptr0_comment = 1;
+       init_unistr2(&dfs3->comment, "", UNI_STR_TERMINATE);
+       dfs3->state = 1;
+       dfs3->num_stores = dfs3->size_stores = j->referral_count;
+       dfs3->ptr0_stores = 1;
+    
+       /* also enumerate the stores */
+       dfs3->stores = TALLOC_ARRAY(ctx, NETDFS_DFS_STORAGEINFO, j->referral_count);
+       if (!dfs3->stores)
+               return False;
+
+       memset(dfs3->stores, '\0', j->referral_count * sizeof(NETDFS_DFS_STORAGEINFO));
+
+       for(ii=0;ii<j->referral_count;ii++) {
+               char* p; 
+               pstring path;
+               NETDFS_DFS_STORAGEINFO* stor = &(dfs3->stores[ii]);
+               struct referral* ref = &(j->referral_list[ii]);
+  
+               pstrcpy(path, ref->alternate_path);
+               trim_char(path,'\\','\0');
+               p = strrchr_m(path,'\\');
+               if(p==NULL) {
+                       DEBUG(4,("init_reply_dfs_info_3: invalid path: no \\ found in %s\n",path));
+                       continue;
                }
+               *p = '\0';
+               DEBUG(5,("storage %d: %s.%s\n",ii,path,p+1));
+               stor->state = 2; /* set all stores as ONLINE */
+               init_unistr2(&stor->server, path, UNI_STR_TERMINATE);
+               init_unistr2(&stor->share,  p+1, UNI_STR_TERMINATE);
+               stor->ptr0_server = stor->ptr0_share = 1;
        }
        return True;
 }
 
-static WERROR init_reply_dfs_ctr(TALLOC_CTX *ctx, uint32 level, 
-                                   DFS_INFO_CTR* ctr, struct junction_map* jn,
-                                   int num_jn)
+WERROR _dfs_Enum(pipes_struct *p, NETDFS_Q_DFS_ENUM *q_u, NETDFS_R_DFS_ENUM *r_u)
 {
-       /* do the levels */
-       switch(level) {
+       uint32 level = q_u->level;
+       struct junction_map jn[MAX_MSDFS_JUNCTIONS];
+       int num_jn = 0;
+       int i;
+
+       num_jn = enum_msdfs_links(p->mem_ctx, jn, ARRAY_SIZE(jn));
+       vfs_ChDir(p->conn,p->conn->connectpath);
+    
+       DEBUG(5,("make_reply_dfs_enum: %d junctions found in Dfs, doing level %d\n", num_jn, level));
+
+       r_u->ptr0_info = q_u->ptr0_info;
+       r_u->ptr0_total = q_u->ptr0_total;
+       r_u->total = num_jn;
+
+       r_u->info = q_u->info;
+
+       /* Create the return array */
+       switch (level) {
        case 1:
-               {
-               DFS_INFO_1* dfs1;
-               dfs1 = TALLOC_ARRAY(ctx, DFS_INFO_1, num_jn);
-               if (!dfs1)
+               if ((r_u->info.e.u.info1.s = TALLOC_ARRAY(p->mem_ctx, NETDFS_DFS_INFO1, num_jn)) == NULL) {
                        return WERR_NOMEM;
-               init_reply_dfs_info_1(jn, dfs1, num_jn);
-               ctr->dfs.info1 = dfs1;
-               break;
                }
+               r_u->info.e.u.info1.count = num_jn;
+               r_u->info.e.u.info1.ptr0_s = 1;
+               r_u->info.e.u.info1.size_s = num_jn;
+               break;
        case 2:
-               {
-               DFS_INFO_2* dfs2;
-               dfs2 = TALLOC_ARRAY(ctx, DFS_INFO_2, num_jn);
-               if (!dfs2)
+               if ((r_u->info.e.u.info2.s = TALLOC_ARRAY(p->mem_ctx, NETDFS_DFS_INFO2, num_jn)) == NULL) {
                        return WERR_NOMEM;
-               init_reply_dfs_info_2(jn, dfs2, num_jn);
-               ctr->dfs.info2 = dfs2;
-               break;
                }
+               r_u->info.e.u.info2.count = num_jn;
+               r_u->info.e.u.info2.ptr0_s = 1;
+               r_u->info.e.u.info2.size_s = num_jn;
+               break;
        case 3:
-               {
-               DFS_INFO_3* dfs3;
-               dfs3 = TALLOC_ARRAY(ctx, DFS_INFO_3, num_jn);
-               if (!dfs3)
+               if ((r_u->info.e.u.info3.s = TALLOC_ARRAY(p->mem_ctx, NETDFS_DFS_INFO3, num_jn)) == NULL) {
                        return WERR_NOMEM;
-               init_reply_dfs_info_3(ctx, jn, dfs3, num_jn);
-               ctr->dfs.info3 = dfs3;
+               }
+               r_u->info.e.u.info3.count = num_jn;
+               r_u->info.e.u.info3.ptr0_s = 1;
+               r_u->info.e.u.info3.size_s = num_jn;
                break;
+       case 4:
+               if ((r_u->info.e.u.info4.s = TALLOC_ARRAY(p->mem_ctx, NETDFS_DFS_INFO4, num_jn)) == NULL) {
+                       return WERR_NOMEM;
                }
+               r_u->info.e.u.info4.count = num_jn;
+               r_u->info.e.u.info4.ptr0_s = 1;
+               r_u->info.e.u.info4.size_s = num_jn;
+               break;
        default:
                return WERR_INVALID_PARAM;
        }
-       return WERR_OK;
-}
-      
-WERROR _dfs_enum(pipes_struct *p, DFS_Q_DFS_ENUM *q_u, DFS_R_DFS_ENUM *r_u)
-{
-       uint32 level = q_u->level;
-       struct junction_map jn[MAX_MSDFS_JUNCTIONS];
-       int num_jn = 0;
-
-       num_jn = enum_msdfs_links(p->mem_ctx, jn, ARRAY_SIZE(jn));
-       vfs_ChDir(p->conn,p->conn->connectpath);
-    
-       DEBUG(5,("make_reply_dfs_enum: %d junctions found in Dfs, doing level %d\n", num_jn, level));
 
-       r_u->ptr_buffer = level;
-       r_u->level = r_u->level2 = level;
-       r_u->ptr_num_entries = r_u->ptr_num_entries2 = 1;
-       r_u->num_entries = r_u->num_entries2 = num_jn;
-       r_u->reshnd.ptr_hnd = 1;
-       r_u->reshnd.handle = num_jn;
-  
-       r_u->ctr = TALLOC_P(p->mem_ctx, DFS_INFO_CTR);
-       if (!r_u->ctr)
-               return WERR_NOMEM;
-       ZERO_STRUCTP(r_u->ctr);
-       r_u->ctr->switch_value = level;
-       r_u->ctr->num_entries = num_jn;
-       r_u->ctr->ptr_dfs_ctr = 1;
+       for (i = 0; i < num_jn; i++) {
+               switch (level) {
+               case 1: 
+                       init_reply_dfs_info_1(&jn[i], &r_u->info.e.u.info1.s[i]);
+                       break;
+               case 2:
+                       init_reply_dfs_info_2(&jn[i], &r_u->info.e.u.info2.s[i]);
+                       break;
+               case 3:
+                       init_reply_dfs_info_3(p->mem_ctx, &jn[i], &r_u->info.e.u.info3.s[i]);
+                       break;
+               default:
+                       return WERR_INVALID_PARAM;
+               }
+       }
   
-       r_u->status = init_reply_dfs_ctr(p->mem_ctx, level, r_u->ctr, jn, num_jn);
+       r_u->status = WERR_OK;
 
        return r_u->status;
 }
       
-WERROR _dfs_get_info(pipes_struct *p, DFS_Q_DFS_GET_INFO *q_u, 
-                     DFS_R_DFS_GET_INFO *r_u)
+WERROR _dfs_GetInfo(pipes_struct *p, NETDFS_Q_DFS_GETINFO *q_u, 
+                     NETDFS_R_DFS_GETINFO *r_u)
 {
-       UNISTR2* uni_path = &q_u->uni_path;
+       UNISTR2* uni_path = &q_u->path;
        uint32 level = q_u->level;
        int consumedcnt = sizeof(pstring);
        pstring path;
+       BOOL ret;
        struct junction_map jn;
 
        unistr2_to_ascii(path, uni_path, sizeof(path)-1);
@@ -363,9 +358,130 @@ WERROR _dfs_get_info(pipes_struct *p, DFS_Q_DFS_GET_INFO *q_u,
        }
 
        vfs_ChDir(p->conn,p->conn->connectpath);
-       r_u->level = level;
-       r_u->ptr_ctr = 1;
-       r_u->status = init_reply_dfs_ctr(p->mem_ctx, level, &r_u->ctr, &jn, 1);
+       r_u->info.switch_value = level;
+       r_u->info.ptr0 = 1;
+       r_u->status = WERR_OK;
+
+       switch (level) {
+               case 1: ret = init_reply_dfs_info_1(&jn, &r_u->info.u.info1); break;
+               case 2: ret = init_reply_dfs_info_2(&jn, &r_u->info.u.info2); break;
+               case 3: ret = init_reply_dfs_info_3(p->mem_ctx, &jn, &r_u->info.u.info3); break;
+               default:
+                       ret = False;
+                       break;
+       }
+
+       if (!ret) 
+               r_u->status = WERR_INVALID_PARAM;
   
        return r_u->status;
 }
+
+WERROR _dfs_SetInfo(pipes_struct *p, NETDFS_Q_DFS_SETINFO *q_u, NETDFS_R_DFS_SETINFO *r_u)
+{
+       /* FIXME: Implement your code here */
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_Rename(pipes_struct *p, NETDFS_Q_DFS_RENAME *q_u, NETDFS_R_DFS_RENAME *r_u)
+{
+       /* FIXME: Implement your code here */
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_Move(pipes_struct *p, NETDFS_Q_DFS_MOVE *q_u, NETDFS_R_DFS_MOVE *r_u)
+{
+       /* FIXME: Implement your code here */
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_ManagerGetConfigInfo(pipes_struct *p, NETDFS_Q_DFS_MANAGERGETCONFIGINFO *q_u, NETDFS_R_DFS_MANAGERGETCONFIGINFO *r_u)
+{
+       /* FIXME: Implement your code here */
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_ManagerSendSiteInfo(pipes_struct *p, NETDFS_Q_DFS_MANAGERSENDSITEINFO *q_u, NETDFS_R_DFS_MANAGERSENDSITEINFO *r_u)
+{
+       /* FIXME: Implement your code here */
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_AddFtRoot(pipes_struct *p, NETDFS_Q_DFS_ADDFTROOT *q_u, NETDFS_R_DFS_ADDFTROOT *r_u)
+{
+       /* FIXME: Implement your code here */
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_RemoveFtRoot(pipes_struct *p, NETDFS_Q_DFS_REMOVEFTROOT *q_u, NETDFS_R_DFS_REMOVEFTROOT *r_u)
+{
+       /* FIXME: Implement your code here */
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_AddStdRoot(pipes_struct *p, NETDFS_Q_DFS_ADDSTDROOT *q_u, NETDFS_R_DFS_ADDSTDROOT *r_u)
+{
+       /* FIXME: Implement your code here */
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_RemoveStdRoot(pipes_struct *p, NETDFS_Q_DFS_REMOVESTDROOT *q_u, NETDFS_R_DFS_REMOVESTDROOT *r_u)
+{
+       /* FIXME: Implement your code here */
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_ManagerInitialize(pipes_struct *p, NETDFS_Q_DFS_MANAGERINITIALIZE *q_u, NETDFS_R_DFS_MANAGERINITIALIZE *r_u)
+{
+       /* FIXME: Implement your code here */
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_AddStdRootForced(pipes_struct *p, NETDFS_Q_DFS_ADDSTDROOTFORCED *q_u, NETDFS_R_DFS_ADDSTDROOTFORCED *r_u)
+{
+       /* FIXME: Implement your code here */
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_GetDcAddress(pipes_struct *p, NETDFS_Q_DFS_GETDCADDRESS *q_u, NETDFS_R_DFS_GETDCADDRESS *r_u)
+{
+       /* FIXME: Implement your code here */
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_SetDcAddress(pipes_struct *p, NETDFS_Q_DFS_SETDCADDRESS *q_u, NETDFS_R_DFS_SETDCADDRESS *r_u)
+{
+       /* FIXME: Implement your code here */
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_FlushFtTable(pipes_struct *p, NETDFS_Q_DFS_FLUSHFTTABLE *q_u, NETDFS_R_DFS_FLUSHFTTABLE *r_u)
+{
+       /* FIXME: Implement your code here */
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_Add2(pipes_struct *p, NETDFS_Q_DFS_ADD2 *q_u, NETDFS_R_DFS_ADD2 *r_u)
+{
+       /* FIXME: Implement your code here */
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_Remove2(pipes_struct *p, NETDFS_Q_DFS_REMOVE2 *q_u, NETDFS_R_DFS_REMOVE2 *r_u)
+{
+       /* FIXME: Implement your code here */
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_EnumEx(pipes_struct *p, NETDFS_Q_DFS_ENUMEX *q_u, NETDFS_R_DFS_ENUMEX *r_u)
+{
+       /* FIXME: Implement your code here */
+       return WERR_NOT_SUPPORTED;
+}
+
+WERROR _dfs_SetInfo2(pipes_struct *p, NETDFS_Q_DFS_SETINFO2 *q_u, NETDFS_R_DFS_SETINFO2 *r_u)
+{
+       /* FIXME: Implement your code here */
+       return WERR_NOT_SUPPORTED;
+}
+
index f48f3e863a8fc36179dde1f67df9b8108059c045..c93107cec4185e169e33d357c96be7365f7c8e50 100644 (file)
@@ -9,6 +9,7 @@
  *  Copyright (C) Jim McDonough <jmcd@us.ibm.com>   2002,
  *  Copyright (C) Simo Sorce                        2003.
  *  Copyright (C) Gerald (Jerry) Carter             2005.
+ *  Copyright (C) Volker Lendecke                   2005.
  *
  *  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
@@ -102,9 +103,7 @@ static int init_dom_ref(DOM_R_REF *ref, const char *dom_name, DOM_SID *dom_sid)
 
        if (dom_name != NULL) {
                for (num = 0; num < ref->num_ref_doms_1; num++) {
-                       fstring domname;
-                       rpcstr_pull(domname, ref->ref_dom[num].uni_dom_name.buffer, sizeof(domname), -1, 0);
-                       if (strequal(domname, dom_name))
+                       if (sid_equal(dom_sid, &ref->ref_dom[num].ref_dom.sid))
                                return num;
                }
        } else {
@@ -159,8 +158,8 @@ static int init_lsa_rid2s(TALLOC_CTX *mem_ctx,
 
                /* Split name into domain and user component */
 
-               if (rpcstr_pull_unistr2_talloc(mem_ctx, &full_name,
-                                              &name[i]) < 0) {
+               full_name = rpcstr_pull_unistr2_talloc(mem_ctx, &name[i]);
+               if (full_name == NULL) {
                        DEBUG(0, ("pull_ucs2_talloc failed\n"));
                        return 0;
                }
@@ -226,87 +225,6 @@ static void init_reply_lookup_names(LSA_R_LOOKUP_NAMES *r_l,
        r_l->mapped_count = mapped_count;
 }
 
-/***************************************************************************
- Init lsa_trans_names.
- ***************************************************************************/
-
-static void init_lsa_trans_names(TALLOC_CTX *ctx, DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *trn,
-                                int num_entries, DOM_SID2 *sid,
-                                uint32 *mapped_count)
-{
-       int i;
-       int total = 0;
-       *mapped_count = 0;
-
-       /* Allocate memory for list of names */
-
-       if (num_entries > 0) {
-               if (!(trn->name = TALLOC_ARRAY(ctx, LSA_TRANS_NAME, num_entries))) {
-                       DEBUG(0, ("init_lsa_trans_names(): out of memory\n"));
-                       return;
-               }
-
-               if (!(trn->uni_name = TALLOC_ARRAY(ctx, UNISTR2, num_entries))) {
-                       DEBUG(0, ("init_lsa_trans_names(): out of memory\n"));
-                       return;
-               }
-       }
-
-       become_root(); /* Need root to get to passdb to for local sids */
-
-       for (i = 0; i < num_entries; i++) {
-               BOOL status = False;
-               DOM_SID find_sid = sid[i].sid;
-               uint32 rid = 0xffffffff;
-               int dom_idx = -1;
-               const char *name, *domain;
-               enum SID_NAME_USE type = SID_NAME_UNKNOWN;
-
-               DEBUG(5, ("init_lsa_trans_names: looking up sid %s\n",
-                         sid_string_static(&find_sid)));
-
-               /* Lookup sid from winbindd */
-
-               status = lookup_sid(ctx, &find_sid, &domain, &name, &type);
-
-               DEBUG(5, ("init_lsa_trans_names: %s\n", status ? "found" : 
-                         "not found"));
-
-               if (!status) {
-                       type = SID_NAME_UNKNOWN;
-                       domain = talloc_strdup(ctx, "");
-                       name = talloc_strdup(ctx,
-                                            sid_string_static(&find_sid));
-                       dom_idx = -1;
-
-                       DEBUG(10,("init_lsa_trans_names: added unknown user "
-                                 "'%s' to referenced list.\n", name ));
-               } else {
-                       (*mapped_count)++;
-                       /* Store domain sid in ref array */
-                       if (find_sid.num_auths == 5) {
-                               sid_split_rid(&find_sid, &rid);
-                       }
-                       dom_idx = init_dom_ref(ref, domain, &find_sid);
-
-                       DEBUG(10,("init_lsa_trans_names: added %s '%s\\%s' "
-                                 "(%d) to referenced list.\n", 
-                                 sid_type_lookup(type), domain, name, type));
-
-               }
-
-               init_lsa_trans_name(&trn->name[total], &trn->uni_name[total],
-                                   type, name, dom_idx);
-               total++;
-       }
-
-       unbecome_root();
-
-       trn->num_entries = total;
-       trn->ptr_trans_names = 1;
-       trn->num_entries2 = total;
-}
-
 /***************************************************************************
  Init_reply_lookup_sids.
  ***************************************************************************/
@@ -315,7 +233,7 @@ static void init_reply_lookup_sids(LSA_R_LOOKUP_SIDS *r_l,
                 DOM_R_REF *ref, LSA_TRANS_NAME_ENUM *names,
                 uint32 mapped_count)
 {
-       r_l->ptr_dom_ref  = 1;
+       r_l->ptr_dom_ref  = ref ? 1 : 0;
        r_l->dom_ref      = ref;
        r_l->names        = names;
        r_l->mapped_count = mapped_count;
@@ -496,10 +414,12 @@ NTSTATUS _lsa_open_policy(pipes_struct *p, LSA_Q_OPEN_POL *q_u, LSA_R_OPEN_POL *
  ufff, done :)  mimir
  ***************************************************************************/
 
-NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_ENUM_TRUST_DOM *r_u)
+NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u,
+                            LSA_R_ENUM_TRUST_DOM *r_u)
 {
        struct lsa_info *info;
-       uint32 enum_context = q_u->enum_context;
+       uint32 next_idx;
+       struct trustdom_info **domains;
 
        /*
         * preferred length is set to 5 as a "our" preferred length
@@ -507,10 +427,11 @@ NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_E
         * update (20.08.2002): it's not preferred length, but preferred size!
         * it needs further investigation how to optimally choose this value
         */
-       uint32 max_num_domains = q_u->preferred_len < 5 ? q_u->preferred_len : 10;
-       TRUSTDOM **trust_doms;
+       uint32 max_num_domains =
+               q_u->preferred_len < 5 ? q_u->preferred_len : 10;
        uint32 num_domains;
        NTSTATUS nt_status;
+       uint32 num_thistime;
 
        if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&info))
                return NT_STATUS_INVALID_HANDLE;
@@ -519,19 +440,34 @@ NTSTATUS _lsa_enum_trust_dom(pipes_struct *p, LSA_Q_ENUM_TRUST_DOM *q_u, LSA_R_E
        if (!(info->access & POLICY_VIEW_LOCAL_INFORMATION))
                return NT_STATUS_ACCESS_DENIED;
 
-       nt_status = secrets_get_trusted_domains(p->mem_ctx, (int *)&enum_context, max_num_domains, (int *)&num_domains, &trust_doms);
+       nt_status = secrets_trusted_domains(p->mem_ctx, &num_domains,
+                                           &domains);
 
-       if (!NT_STATUS_IS_OK(nt_status) &&
-           !NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES) &&
-           !NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MORE_ENTRIES)) {
+       if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
-       } else {
-               r_u->status = nt_status;
        }
 
+       if (q_u->enum_context < num_domains) {
+               num_thistime = MIN(num_domains, max_num_domains);
+
+               r_u->status = STATUS_MORE_ENTRIES;
+
+               if (q_u->enum_context + num_thistime > num_domains) {
+                       num_thistime = num_domains - q_u->enum_context;
+                       r_u->status = NT_STATUS_OK;
+               }
+
+               next_idx = q_u->enum_context + num_thistime;
+       } else {
+               num_thistime = 0;
+               next_idx = 0xffffffff;
+               r_u->status = NT_STATUS_NO_MORE_ENTRIES;
+       }
+               
        /* set up the lsa_enum_trust_dom response */
 
-       init_r_enum_trust_dom(p->mem_ctx, r_u, enum_context, max_num_domains, num_domains, trust_doms);
+       init_r_enum_trust_dom(p->mem_ctx, r_u, next_idx,
+                             num_thistime, domains+q_u->enum_context);
 
        return r_u->status;
 }
@@ -650,24 +586,29 @@ NTSTATUS _lsa_query_info(pipes_struct *p, LSA_Q_QUERY_INFO *q_u, LSA_R_QUERY_INF
  _lsa_lookup_sids
  ***************************************************************************/
 
-NTSTATUS _lsa_lookup_sids(pipes_struct *p, LSA_Q_LOOKUP_SIDS *q_u, LSA_R_LOOKUP_SIDS *r_u)
+NTSTATUS _lsa_lookup_sids(pipes_struct *p,
+                         LSA_Q_LOOKUP_SIDS *q_u,
+                         LSA_R_LOOKUP_SIDS *r_u)
 {
        struct lsa_info *handle;
-       DOM_SID2 *sid = q_u->sids.sid;
-       int num_entries = q_u->sids.num_entries;
-       DOM_R_REF *ref = NULL;
-       LSA_TRANS_NAME_ENUM *names = NULL;
+
+       int i, num_sids;
+       const DOM_SID **sids;
        uint32 mapped_count = 0;
 
-       if (num_entries >  MAX_LOOKUP_SIDS) {
-               num_entries = 0;
-               DEBUG(5,("_lsa_lookup_sids: limit of %d exceeded, truncating SID lookup list to %d\n", MAX_LOOKUP_SIDS, num_entries));
-               r_u->status = NT_STATUS_NONE_MAPPED;
-       }
+       struct lsa_dom_info *dom_infos;
+       struct lsa_name_info *name_infos;
+
+       DOM_R_REF *ref = NULL;
+       LSA_TRANS_NAME_ENUM *names = NULL;
 
-       ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF);
        names = TALLOC_ZERO_P(p->mem_ctx, LSA_TRANS_NAME_ENUM);
 
+       if ((q_u->level < 1) || (q_u->level > 6)) {
+               r_u->status = NT_STATUS_INVALID_PARAMETER;
+               goto done;
+       }
+
        if (!find_policy_by_hnd(p, &q_u->pol, (void **)(void *)&handle)) {
                r_u->status = NT_STATUS_INVALID_HANDLE;
                goto done;
@@ -678,19 +619,91 @@ NTSTATUS _lsa_lookup_sids(pipes_struct *p, LSA_Q_LOOKUP_SIDS *q_u, LSA_R_LOOKUP_
                r_u->status = NT_STATUS_ACCESS_DENIED;
                goto done;
        }
-       if (!ref || !names)
-               return NT_STATUS_NO_MEMORY;
 
-done:
+       num_sids = q_u->sids.num_entries;
+       if (num_sids >  MAX_LOOKUP_SIDS) {
+               DEBUG(5,("_lsa_lookup_sids: limit of %d exceeded, truncating "
+                        "SID lookup list to %d\n",
+                        MAX_LOOKUP_SIDS, num_sids));
+               r_u->status = NT_STATUS_NONE_MAPPED;
+               goto done;
+       }
 
-       /* set up the LSA Lookup SIDs response */
-       init_lsa_trans_names(p->mem_ctx, ref, names, num_entries, sid, &mapped_count);
-       if (NT_STATUS_IS_OK(r_u->status)) {
-               if (mapped_count == 0)
-                       r_u->status = NT_STATUS_NONE_MAPPED;
-               else if (mapped_count != num_entries)
-                       r_u->status = STATUS_SOME_UNMAPPED;
+       ref = TALLOC_ZERO_P(p->mem_ctx, DOM_R_REF);
+
+       sids = TALLOC_ARRAY(p->mem_ctx, const DOM_SID *, num_sids);
+       if ((ref == NULL) || (names == NULL) || (sids == NULL)) {
+               r_u->status = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+
+       for (i=0; i<num_sids; i++) {
+               sids[i] = &q_u->sids.sid[i].sid;
+       }
+
+       r_u->status = lookup_sids(p->mem_ctx, num_sids, sids, q_u->level,
+                                 &dom_infos, &name_infos);
+
+       if (!NT_STATUS_IS_OK(r_u->status)) {
+               goto done;
+       }
+
+       if (num_sids > 0) {
+               names->name = TALLOC_ARRAY(names, LSA_TRANS_NAME, num_sids);
+               names->uni_name = TALLOC_ARRAY(names, UNISTR2, num_sids);
+               if ((names->name == NULL) || (names->uni_name == NULL)) {
+                       r_u->status = NT_STATUS_NO_MEMORY;
+                       goto done;
+               }
        }
+
+       for (i=0; i<MAX_REF_DOMAINS; i++) {
+
+               if (!dom_infos[i].valid) {
+                       break;
+               }
+
+               if (init_dom_ref(ref, dom_infos[i].name,
+                                &dom_infos[i].sid) != i) {
+                       DEBUG(0, ("Domain %s mentioned twice??\n",
+                                 dom_infos[i].name));
+                       r_u->status = NT_STATUS_INTERNAL_ERROR;
+                       goto done;
+               }
+       }
+
+       for (i=0; i<num_sids; i++) {
+               struct lsa_name_info *name = &name_infos[i];
+
+               if (name->type == SID_NAME_UNKNOWN) {
+                       name->dom_idx = -1;
+                       name->name = talloc_asprintf(p->mem_ctx, "%8.8x",
+                                                    name->rid);
+                       if (name->name == NULL) {
+                               r_u->status = NT_STATUS_NO_MEMORY;
+                               goto done;
+                       }
+               } else {
+                       mapped_count += 1;
+               }
+               init_lsa_trans_name(&names->name[i], &names->uni_name[i],
+                                   name->type, name->name, name->dom_idx);
+       }
+
+       names->num_entries = num_sids;
+       names->ptr_trans_names = 1;
+       names->num_entries2 = num_sids;
+
+       r_u->status = NT_STATUS_NONE_MAPPED;
+       if (mapped_count > 0) {
+               r_u->status = (mapped_count < num_sids) ?
+                       STATUS_SOME_UNMAPPED : NT_STATUS_OK;
+       }
+
+       DEBUG(10, ("num_sids %d, mapped_count %d, status %s\n",
+                  num_sids, mapped_count, nt_errstr(r_u->status)));
+
+ done:
        init_reply_lookup_sids(r_u, ref, names, mapped_count);
 
        return r_u->status;
@@ -1173,10 +1186,7 @@ NTSTATUS _lsa_setsystemaccount(pipes_struct *p, LSA_Q_SETSYSTEMACCOUNT *q_u, LSA
        if (!pdb_getgrsid(&map, info->sid))
                return NT_STATUS_NO_SUCH_GROUP;
 
-       if(!pdb_update_group_mapping_entry(&map))
-               return NT_STATUS_NO_SUCH_GROUP;
-
-       return r_u->status;
+       return pdb_update_group_mapping_entry(&map);
 }
 
 /***************************************************************************
index 643921f5963e265fe5f9d0fccc7e48c8469af518..fd78f954cc4e393f5166d9e5ebdf107eb3e76970 100644 (file)
@@ -542,12 +542,9 @@ 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);
+               r_u->status = pdb_update_sam_account (sampass);
                unbecome_root();
        }
-       if (ret) {
-               status = NT_STATUS_OK;
-       }
 
        /* set up the LSA Server Password Set response */
        init_net_r_srv_pwset(r_u, &cred_out, status);
@@ -587,29 +584,29 @@ NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOF
 /*******************************************************************
  gets a domain user's groups from their already-calculated NT_USER_TOKEN
  ********************************************************************/
-static NTSTATUS nt_token_to_group_list(TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid, 
-                                      const NT_USER_TOKEN *nt_token,
+static NTSTATUS nt_token_to_group_list(TALLOC_CTX *mem_ctx,
+                                      const DOM_SID *domain_sid,
+                                      size_t num_sids,
+                                      const DOM_SID *sids,
                                       int *numgroups, DOM_GID **pgids) 
 {
-       DOM_GID *gids;
        int i;
 
-       gids = TALLOC_ARRAY(mem_ctx, DOM_GID, nt_token->num_sids);
-
-       if (!gids) {
-               return NT_STATUS_NO_MEMORY;
-       }
-
        *numgroups=0;
+       *pgids = NULL;
 
-       for (i=PRIMARY_GROUP_SID_INDEX; i < nt_token->num_sids; i++) {
-               if (sid_compare_domain(domain_sid, &nt_token->user_sids[i])==0) {
-                       sid_peek_rid(&nt_token->user_sids[i], &(gids[*numgroups].g_rid));
-                       gids[*numgroups].attr= (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_ENABLED);
-                       (*numgroups)++;
+       for (i=0; i<num_sids; i++) {
+               DOM_GID gid;
+               if (!sid_peek_check_rid(domain_sid, &sids[i], &gid.g_rid)) {
+                       continue;
+               }
+               gid.attr = (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT|
+                           SE_GROUP_ENABLED);
+               ADD_TO_ARRAY(mem_ctx, DOM_GID, gid, pgids, numgroups);
+               if (*pgids == NULL) {
+                       return NT_STATUS_NO_MEMORY;
                }
        }
-       *pgids = gids; 
        return NT_STATUS_OK;
 }
 
@@ -655,7 +652,7 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
                /* 'server schannel = yes' should enforce use of
                   schannel, the client did offer it in auth2, but
                   obviously did not use it. */
-               DEBUG(0,("_net_sam_logoff: client %s not using schannel for netlogon\n",
+               DEBUG(0,("_net_sam_logon: client %s not using schannel for netlogon\n",
                        p->dc->remote_machine ));
                return NT_STATUS_ACCESS_DENIED;
        }
@@ -734,10 +731,10 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
                break;
        }
        case INTERACTIVE_LOGON_TYPE:
-               /* 'Interactive' autheticaion, supplies the password in its
-                  MD4 form, encrypted with the session key.  We will
-                  convert this to chellange/responce for the auth
-                  subsystem to chew on */
+               /* 'Interactive' authentication, supplies the password in its
+                  MD4 form, encrypted with the session key.  We will convert
+                  this to challenge/response for the auth subsystem to chew
+                  on */
        {
                const uint8 *chal;
                
@@ -787,14 +784,15 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
                     && !is_trusted_domain(nt_domain) )
                        r_u->auth_resp = 0; /* We are not authoritative */
 
-               free_server_info(&server_info);
+               talloc_free(server_info);
                return status;
        }
 
        if (server_info->guest) {
                /* We don't like guest domain logons... */
-               DEBUG(5,("_net_sam_logon: Attempted domain logon as GUEST denied.\n"));
-               free_server_info(&server_info);
+               DEBUG(5,("_net_sam_logon: Attempted domain logon as GUEST "
+                        "denied.\n"));
+               talloc_free(server_info);
                return NT_STATUS_LOGON_FAILURE;
        }
 
@@ -819,7 +817,8 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
 
                sampw = server_info->sam_account;
 
-               /* set up pointer indicating user/password failed to be found */
+               /* set up pointer indicating user/password failed to be
+                * found */
                usr_info->ptr_user_info = 0;
 
                user_sid = pdb_get_user_sid(sampw);
@@ -829,8 +828,12 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
                sid_split_rid(&domain_sid, &user_rid);
 
                if (!sid_peek_check_rid(&domain_sid, group_sid, &group_rid)) {
-                       DEBUG(1, ("_net_sam_logon: user %s\\%s has user sid %s\n but group sid %s.\nThe conflicting domain portions are not supported for NETLOGON calls\n",        
-                                 pdb_get_domain(sampw), pdb_get_username(sampw),
+                       DEBUG(1, ("_net_sam_logon: user %s\\%s has user sid "
+                                 "%s\n but group sid %s.\n"
+                                 "The conflicting domain portions are not "
+                                 "supported for NETLOGON calls\n",         
+                                 pdb_get_domain(sampw),
+                                 pdb_get_username(sampw),
                                  sid_to_string(user_sid_string, user_sid),
                                  sid_to_string(group_sid_string, group_sid)));
                        return NT_STATUS_UNSUCCESSFUL;
@@ -842,26 +845,30 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
                } else {
                        pstrcpy(my_name, global_myname());
                }
-               
-               if (!NT_STATUS_IS_OK(status 
-                                    = nt_token_to_group_list(p->mem_ctx, 
-                                                             &domain_sid, 
-                                                             server_info->ptok, 
-                                                             &num_gids, 
-                                                             &gids))) {
+
+               status = nt_token_to_group_list(p->mem_ctx, &domain_sid,
+                                               server_info->num_sids,
+                                               server_info->sids,
+                                               &num_gids, &gids);
+
+               if (!NT_STATUS_IS_OK(status)) {
                        return status;
                }
 
                ZERO_STRUCT(netlogon_sess_key);
                memcpy(netlogon_sess_key, p->dc->sess_key, 8);
                if (server_info->user_session_key.length) {
-                       memcpy(user_session_key, server_info->user_session_key.data, 
-                              MIN(sizeof(user_session_key), server_info->user_session_key.length));
+                       memcpy(user_session_key,
+                              server_info->user_session_key.data, 
+                              MIN(sizeof(user_session_key),
+                                  server_info->user_session_key.length));
                        SamOEMhash(user_session_key, netlogon_sess_key, 16);
                }
                if (server_info->lm_session_key.length) {
-                       memcpy(lm_session_key, server_info->lm_session_key.data, 
-                              MIN(sizeof(lm_session_key), server_info->lm_session_key.length));
+                       memcpy(lm_session_key,
+                              server_info->lm_session_key.data, 
+                              MIN(sizeof(lm_session_key),
+                                  server_info->lm_session_key.length));
                        SamOEMhash(lm_session_key, netlogon_sess_key, 16);
                }
                ZERO_STRUCT(netlogon_sess_key);
@@ -891,14 +898,11 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON *
                                    server_info->lm_session_key.length ? lm_session_key : NULL,
                                    my_name     , /* char *logon_srv */
                                    pdb_get_domain(sampw),
-                                   &domain_sid,     /* DOM_SID *dom_sid */  
-                                   /* Should be users domain sid, not servers - for trusted domains */
-                                 
-                                   NULL); /* char *other_sids */
+                                   &domain_sid);     /* DOM_SID *dom_sid */  
                ZERO_STRUCT(user_session_key);
                ZERO_STRUCT(lm_session_key);
        }
-       free_server_info(&server_info);
+       talloc_free(server_info);
        return status;
 }
 
index 381adbe635890a31ae9afab76151dbdc6ade7607..68b3a2d434c26a8a23e752efeb8afb43d92fbf7c 100644 (file)
@@ -616,7 +616,7 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
        memset(p->wks, '\0', sizeof(p->wks));
 
        /* Set up for non-authenticated user. */
-       delete_nt_token(&p->pipe_user.nt_user_token);
+       talloc_free(p->pipe_user.nt_user_token);
        p->pipe_user.ut.ngroups = 0;
        SAFE_FREE( p->pipe_user.ut.groups);
 
@@ -664,7 +664,8 @@ static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob)
        }
 
        if (a->server_info->ptok) {
-               p->pipe_user.nt_user_token = dup_nt_token(a->server_info->ptok);
+               p->pipe_user.nt_user_token =
+                       dup_nt_token(NULL, a->server_info->ptok);
        } else {
                DEBUG(1,("Error: Authmodule failed to provide nt_user_token\n"));
                p->pipe_user.nt_user_token = NULL;
index 37d3ef64c0b3f747247ec58310061bc4bdb085ab..86a04e7ccbe9602be030f9fb824b52a78c6e3640 100644 (file)
@@ -349,7 +349,8 @@ static void *make_internal_rpc_pipe_p(char *pipe_name,
        /* Store the session key and NT_TOKEN */
        if (vuser) {
                p->session_key = data_blob(vuser->session_key.data, vuser->session_key.length);
-               p->pipe_user.nt_user_token = dup_nt_token(vuser->nt_user_token);
+               p->pipe_user.nt_user_token = dup_nt_token(
+                       NULL, vuser->nt_user_token);
        }
 
        /*
@@ -1222,7 +1223,7 @@ static BOOL close_internal_rpc_pipe_hnd(void *np_conn)
        /* Free the handles database. */
        close_policy_by_pipe(p);
 
-       delete_nt_token(&p->pipe_user.nt_user_token);
+       talloc_free(p->pipe_user.nt_user_token);
        data_blob_free(&p->session_key);
        SAFE_FREE(p->pipe_user.ut.groups);
 
index 2f9d494a26fb75d18436f9d28f1f04ea14ad0e06..81344cdc1eca9db84a667889ef46973b76ddeec7 100644 (file)
@@ -140,7 +140,7 @@ static NTSTATUS make_samr_object_sd( TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd
        if ( sid ) {
                init_sec_access( &mask, sid_access );
                init_sec_ace(&ace[i++], sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0);
-}
+       }
 
        /* create the security descriptor */
 
@@ -1416,7 +1416,7 @@ NTSTATUS _samr_lookup_names(pipes_struct *p, SAMR_Q_LOOKUP_NAMES *q_u, SAMR_R_LO
                                type[i] = SID_NAME_ALIAS;
                        }
                } else {
-                       lookup_global_sam_name(name, &rid[i], &type[i]);
+                       lookup_global_sam_name(name, 0, &rid[i], &type[i]);
                }
 
                if (type[i] != SID_NAME_UNKNOWN) {
@@ -1927,28 +1927,6 @@ NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_
                        return r_u->status;
                break;
 
-#if 0
-/* whoops - got this wrong.  i think.  or don't understand what's happening. */
-        case 17:
-        {
-            NTTIME expire;
-            info = (void *)&id11;
-
-            expire.low = 0xffffffff;
-            expire.high = 0x7fffffff;
-
-            ctr->info.id = TALLOC_ZERO_P(p->mem_ctx, SAM_USER_INFO_17));
-           ZERO_STRUCTP(ctr->info.id17);
-            init_sam_user_info17(ctr->info.id17, &expire,
-                         "BROOKFIELDS$",    /* name */
-                         0x03ef,    /* user rid */
-                         0x201, /* group rid */
-                         0x0080);   /* acb info */
-
-            break;
-        }
-#endif
-
        case 18:
                ctr->info.id18 = TALLOC_ZERO_P(p->mem_ctx, SAM_USER_INFO_18);
                if (ctr->info.id18 == NULL)
@@ -1993,10 +1971,11 @@ NTSTATUS _samr_query_userinfo(pipes_struct *p, SAMR_Q_QUERY_USERINFO *q_u, SAMR_
 NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, SAMR_R_QUERY_USERGROUPS *r_u)
 {
        SAM_ACCOUNT *sam_pass=NULL;
-       struct passwd *passwd;
        DOM_SID  sid;
        DOM_SID *sids;
+       DOM_GID dom_gid;
        DOM_GID *gids = NULL;
+       uint32 primary_group_rid;
        size_t num_groups = 0;
        gid_t *unix_gids;
        size_t i, num_gids;
@@ -2031,58 +2010,72 @@ NTSTATUS _samr_query_usergroups(pipes_struct *p, SAMR_Q_QUERY_USERGROUPS *q_u, S
        if (!sid_check_is_in_our_domain(&sid))
                return NT_STATUS_OBJECT_TYPE_MISMATCH;
 
-       pdb_init_sam(&sam_pass);
+       pdb_init_sam_talloc(p->mem_ctx, &sam_pass);
        
        become_root();
        ret = pdb_getsampwsid(sam_pass, &sid);
        unbecome_root();
 
-       if (ret == False) {
-               pdb_free_sam(&sam_pass);
-               return NT_STATUS_NO_SUCH_USER;
-       }
-
-       passwd = getpwnam_alloc(pdb_get_username(sam_pass));
-       if (passwd == NULL) {
-               pdb_free_sam(&sam_pass);
+       if (!ret) {
+               DEBUG(10, ("pdb_getsampwsid failed for %s\n",
+                          sid_string_static(&sid)));
                return NT_STATUS_NO_SUCH_USER;
        }
 
        sids = NULL;
 
        become_root();
-       result = pdb_enum_group_memberships(pdb_get_username(sam_pass),
-                                           passwd->pw_gid,
+       result = pdb_enum_group_memberships(p->mem_ctx, sam_pass,
                                            &sids, &unix_gids, &num_groups);
        unbecome_root();
 
-       pdb_free_sam(&sam_pass);
-       passwd_free(&passwd);
-
-       if (!NT_STATUS_IS_OK(result))
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
+                          sid_string_static(&sid)));
                return result;
-
-       SAFE_FREE(unix_gids);
+       }
 
        gids = NULL;
        num_gids = 0;
 
+       dom_gid.attr = (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT|
+                       SE_GROUP_ENABLED);
+
+       if (!sid_peek_check_rid(get_global_sam_sid(),
+                               pdb_get_group_sid(sam_pass),
+                               &primary_group_rid)) {
+               DEBUG(5, ("Group sid %s for user %s not in our domain\n",
+                         sid_string_static(pdb_get_group_sid(sam_pass)),
+                         pdb_get_username(sam_pass)));
+               pdb_free_sam(&sam_pass);
+               return NT_STATUS_INTERNAL_DB_CORRUPTION;
+       }
+
+       dom_gid.g_rid = primary_group_rid;
+
+       ADD_TO_ARRAY(p->mem_ctx, DOM_GID, dom_gid, &gids, &num_gids);
+
        for (i=0; i<num_groups; i++) {
-               uint32 rid;
 
                if (!sid_peek_check_rid(get_global_sam_sid(),
-                                       &(sids[i]), &rid))
+                                       &(sids[i]), &dom_gid.g_rid)) {
+                       DEBUG(10, ("Found sid %s not in our domain\n",
+                                  sid_string_static(&sids[i])));
                        continue;
+               }
 
-               gids = TALLOC_REALLOC_ARRAY(p->mem_ctx, gids, DOM_GID, num_gids+1);
-               gids[num_gids].attr= (SE_GROUP_MANDATORY|SE_GROUP_ENABLED_BY_DEFAULT|SE_GROUP_ENABLED);
-               gids[num_gids].g_rid = rid;
-               num_gids += 1;
+               if (dom_gid.g_rid == primary_group_rid) {
+                       /* We added the primary group directly from the
+                        * sam_account. The other SIDs are unique from
+                        * enum_group_memberships */
+                       continue;
+               }
+
+               ADD_TO_ARRAY(p->mem_ctx, DOM_GID, dom_gid, &gids, &num_gids);
        }
-       SAFE_FREE(sids);
        
        /* construct the response.  lkclXXXX: gids are not copied! */
-       init_samr_r_query_usergroups(r_u, num_groups, gids, r_u->status);
+       init_samr_r_query_usergroups(r_u, num_gids, gids, r_u->status);
        
        DEBUG(5,("_samr_query_usergroups: %d\n", __LINE__));
        
@@ -2322,7 +2315,8 @@ static NTSTATUS can_create(TALLOC_CTX *mem_ctx, const char *new_name)
  This funcion will need to be updated for bdc/domain trusts.
  ********************************************************************/
 
-NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREATE_USER *r_u)
+NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u,
+                          SAMR_R_CREATE_USER *r_u)
 {
        SAM_ACCOUNT *sam_pass=NULL;
        fstring account;
@@ -2339,7 +2333,6 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
        uint32 acc_granted;
        SEC_DESC *psd;
        size_t    sd_size;
-       uint32 new_rid = 0;
        /* check this, when giving away 'add computer to domain' privs */
        uint32    des_access = GENERIC_RIGHTS_USER_ALL_ACCESS;
        BOOL can_add_account = False;
@@ -2347,20 +2340,26 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
        DISP_INFO *disp_info = NULL;
 
        /* Get the domain SID stored in the domain policy */
-       if (!get_lsa_policy_samr_sid(p, &dom_pol, &sid, &acc_granted, &disp_info))
+       if (!get_lsa_policy_samr_sid(p, &dom_pol, &sid, &acc_granted,
+                                    &disp_info))
                return NT_STATUS_INVALID_HANDLE;
 
-       if (!NT_STATUS_IS_OK(nt_status = access_check_samr_function(acc_granted, SA_RIGHT_DOMAIN_CREATE_USER, "_samr_create_user"))) {
+       nt_status = access_check_samr_function(acc_granted,
+                                              SA_RIGHT_DOMAIN_CREATE_USER,
+                                              "_samr_create_user");
+       if (!NT_STATUS_IS_OK(nt_status)) {
                return nt_status;
        }
 
-       if (!(acb_info == ACB_NORMAL || acb_info == ACB_DOMTRUST || acb_info == ACB_WSTRUST || acb_info == ACB_SVRTRUST)) { 
+       if (!(acb_info == ACB_NORMAL || acb_info == ACB_DOMTRUST ||
+             acb_info == ACB_WSTRUST || acb_info == ACB_SVRTRUST)) { 
                /* Match Win2k, and return NT_STATUS_INVALID_PARAMETER if 
                   this parameter is not an account type */
                return NT_STATUS_INVALID_PARAMETER;
        }
 
-       rpcstr_pull(account, user_account.buffer, sizeof(account), user_account.uni_str_len*2, 0);
+       rpcstr_pull(account, user_account.buffer, sizeof(account),
+                   user_account.uni_str_len*2, 0);
        strlower_m(account);
 
        nt_status = can_create(p->mem_ctx, account);
@@ -2369,14 +2368,14 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
        }
 
        /*********************************************************************
-        * HEADS UP!  If we have to create a new user account, we have to get 
-        * a new RID from somewhere.  This used to be done by the passdb 
-        * backend. It has been moved into idmap now.  Since idmap is now 
-        * wrapped up behind winbind, this means you have to run winbindd if you
-        * want new accounts to get a new RID when "enable rid algorithm = no".
-        * Tough.  We now have a uniform way of allocating RIDs regardless
-        * of what ever passdb backend people may use.
-        *                                             --jerry (2003-07-10)
+        * HEADS UP!  If we have to create a new user account, we have to get
+        * a new RID from somewhere.  This used to be done by the passdb
+        * backend. It has been moved into idmap now.  Since idmap is now
+        * wrapped up behind winbind, this means you have to run winbindd if
+        * you want new accounts to get a new RID when "enable rid algorithm =
+        * no".  Tough.  We now have a uniform way of allocating RIDs
+        * regardless of what ever passdb backend people may use.  --jerry
+        * (2003-07-10)
         *********************************************************************/
 
        pw = Get_Pwnam(account);
@@ -2387,24 +2386,30 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
        {
                pstrcpy(add_script, lp_addmachine_script());
                se_priv_copy( &se_rights, &se_machine_account );
-               can_add_account = user_has_privileges( p->pipe_user.nt_user_token, &se_rights );
+               can_add_account = user_has_privileges(
+                       p->pipe_user.nt_user_token, &se_rights );
        } 
        /* usrmgr.exe (and net rpc trustdom grant) creates a normal user 
           account for domain trusts and changes the ACB flags later */
-       else if ( acb_info & ACB_NORMAL && (account[strlen(account)-1] != '$') )
+       else if ( acb_info & ACB_NORMAL &&
+                 (account[strlen(account)-1] != '$') )
        {
                pstrcpy(add_script, lp_adduser_script());
                se_priv_copy( &se_rights, &se_add_users );
-               can_add_account = user_has_privileges( p->pipe_user.nt_user_token, &se_rights );
+               can_add_account = user_has_privileges(
+                       p->pipe_user.nt_user_token, &se_rights );
        } 
-       else    /* implicit assumption of a BDC or domain trust account here (we already check the flags earlier) */
+       else    /* implicit assumption of a BDC or domain trust account here
+                * (we already check the flags earlier) */
        {
                pstrcpy(add_script, lp_addmachine_script());
                if ( lp_enable_privileges() ) {
                        /* only Domain Admins can add a BDC or domain trust */
                        se_priv_copy( &se_rights, &se_priv_none );
-                       can_add_account = nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS );
-       }
+                       can_add_account = nt_token_check_domain_rid(
+                               p->pipe_user.nt_user_token,
+                               DOMAIN_GROUP_RID_ADMINS );
+               }
        }
                
        DEBUG(5, ("_samr_create_user: %s can add this account : %s\n",
@@ -2419,16 +2424,20 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
                if (*add_script) {
                        int add_ret;
 
-                       all_string_sub(add_script, "%u", account, sizeof(add_script));
+                       all_string_sub(add_script, "%u", account,
+                                      sizeof(add_script));
                        add_ret = smbrun(add_script,NULL);
-                       DEBUG(add_ret ? 0 : 3,("_samr_create_user: Running the command `%s' gave %d\n", add_script, add_ret));
+                       DEBUG(add_ret ? 0 : 3,("_samr_create_user: Running "
+                                              "the command `%s' gave %d\n",
+                                              add_script, add_ret));
                }
        }
 
-       /* implicit call to getpwnam() next.  we have a valid SID coming out of this call */
+       /* implicit call to getpwnam() next.  we have a valid SID coming out
+        * of this call */
 
        flush_pwnam_cache();
-       nt_status = pdb_init_sam_new(&sam_pass, account, new_rid);
+       nt_status = pdb_init_sam_new(&sam_pass, account);
 
        /* this code is order such that we have no unnecessary retuns 
           out of the admin block of code */    
@@ -2438,7 +2447,8 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
        
                if ( !(ret = pdb_add_sam_account(sam_pass)) ) {
                        pdb_free_sam(&sam_pass);
-                       DEBUG(0, ("could not add user/computer %s to passdb.  Check permissions?\n", 
+                       DEBUG(0, ("could not add user/computer %s to passdb. "
+                                 "Check permissions?\n", 
                                account));
                        nt_status = NT_STATUS_ACCESS_DENIED;
                }
@@ -2458,7 +2468,8 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA
        
        sid_copy(&sid, pdb_get_user_sid(sam_pass));
        
-       make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping, &sid, SAMR_USR_RIGHTS_WRITE_PW);
+       make_samr_object_sd(p->mem_ctx, &psd, &sd_size, &usr_generic_mapping,
+                           &sid, SAMR_USR_RIGHTS_WRITE_PW);
        se_map_generic(&des_access, &usr_generic_mapping);
        
        nt_status = access_check_samr_object(psd, p->pipe_user.nt_user_token, 
@@ -2944,7 +2955,7 @@ static BOOL set_user_info_16(const SAM_USER_INFO_16 *id16, SAM_ACCOUNT *pwd)
                return False;
        }
 
-       if(!pdb_update_sam_account(pwd)) {
+       if(!NT_STATUS_IS_OK(pdb_update_sam_account(pwd))) {
                pdb_free_sam(&pwd);
                return False;
        }
@@ -2980,7 +2991,7 @@ static BOOL set_user_info_18(SAM_USER_INFO_18 *id18, SAM_ACCOUNT *pwd)
                return False; 
        }
  
-       if(!pdb_update_sam_account(pwd)) {
+       if(!NT_STATUS_IS_OK(pdb_update_sam_account(pwd))) {
                pdb_free_sam(&pwd);
                return False;
        }
@@ -2997,8 +3008,7 @@ static BOOL set_unix_primary_group(SAM_ACCOUNT *sampass)
        struct group *grp;
        gid_t gid;
 
-       if (!NT_STATUS_IS_OK(sid_to_gid(pdb_get_group_sid(sampass),
-                                       &gid))) {
+       if (!sid_to_gid(pdb_get_group_sid(sampass), &gid)) {
                DEBUG(2,("Could not get gid for primary group of "
                         "user %s\n", pdb_get_username(sampass)));
                return False;
@@ -3039,7 +3049,7 @@ static BOOL set_user_info_20(SAM_USER_INFO_20 *id20, SAM_ACCOUNT *pwd)
        copy_id20_to_sam_passwd(pwd, id20);
 
        /* write the change out */
-       if(!pdb_update_sam_account(pwd)) {
+       if(!NT_STATUS_IS_OK(pdb_update_sam_account(pwd))) {
                pdb_free_sam(&pwd);
                return False;
        }
@@ -3073,7 +3083,7 @@ static BOOL set_user_info_21(SAM_USER_INFO_21 *id21, SAM_ACCOUNT *pwd)
                set_unix_primary_group(pwd);
 
        /* write the change out */
-       if(!pdb_update_sam_account(pwd)) {
+       if(!NT_STATUS_IS_OK(pdb_update_sam_account(pwd))) {
                pdb_free_sam(&pwd);
                return False;
        }
@@ -3140,7 +3150,7 @@ static BOOL set_user_info_23(SAM_USER_INFO_23 *id23, SAM_ACCOUNT *pwd)
        if (IS_SAM_CHANGED(pwd, PDB_GROUPSID))
                set_unix_primary_group(pwd);
 
-       if(!pdb_update_sam_account(pwd)) {
+       if(!NT_STATUS_IS_OK(pdb_update_sam_account(pwd))) {
                pdb_free_sam(&pwd);
                return False;
        }
@@ -3202,7 +3212,7 @@ static BOOL set_user_info_pw(uint8 *pass, SAM_ACCOUNT *pwd)
        DEBUG(5,("set_user_info_pw: pdb_update_pwd()\n"));
  
        /* update the SAMBA password */
-       if(!pdb_update_sam_account(pwd)) {
+       if(!NT_STATUS_IS_OK(pdb_update_sam_account(pwd))) {
                pdb_free_sam(&pwd);
                return False;
        }
@@ -3485,7 +3495,6 @@ NTSTATUS _samr_query_useraliases(pipes_struct *p, SAMR_Q_QUERY_USERALIASES *q_u,
        NTSTATUS ntstatus2;
 
        DOM_SID *members;
-       BOOL res;
 
        r_u->status = NT_STATUS_OK;
 
@@ -3521,13 +3530,14 @@ NTSTATUS _samr_query_useraliases(pipes_struct *p, SAMR_Q_QUERY_USERALIASES *q_u,
        num_alias_rids = 0;
 
        become_root();
-       res = pdb_enum_alias_memberships(p->mem_ctx, &info->sid, members,
-                                        q_u->num_sids1,
-                                        &alias_rids, &num_alias_rids);
+       ntstatus1 = pdb_enum_alias_memberships(p->mem_ctx, &info->sid, members,
+                                              q_u->num_sids1,
+                                              &alias_rids, &num_alias_rids);
        unbecome_root();
 
-       if (!res)
-               return NT_STATUS_UNSUCCESSFUL;
+       if (!NT_STATUS_IS_OK(ntstatus1)) {
+               return ntstatus1;
+       }
 
        init_samr_r_query_useraliases(r_u, num_alias_rids, alias_rids,
                                      NT_STATUS_OK);
@@ -3540,6 +3550,7 @@ NTSTATUS _samr_query_useraliases(pipes_struct *p, SAMR_Q_QUERY_USERALIASES *q_u,
 
 NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_R_QUERY_ALIASMEM *r_u)
 {
+       NTSTATUS status;
        size_t i;
        size_t num_sids = 0;
        DOM_SID2 *sid;
@@ -3560,8 +3571,11 @@ NTSTATUS _samr_query_aliasmem(pipes_struct *p, SAMR_Q_QUERY_ALIASMEM *q_u, SAMR_
 
        DEBUG(10, ("sid is %s\n", sid_string_static(&alias_sid)));
 
-       if (!pdb_enum_aliasmem(&alias_sid, &sids, &num_sids))
-               return NT_STATUS_NO_SUCH_ALIAS;
+       status = pdb_enum_aliasmem(&alias_sid, &sids, &num_sids);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
 
        sid = TALLOC_ZERO_ARRAY(p->mem_ctx, DOM_SID2, num_sids);        
        if (num_sids!=0 && sid == NULL) {
@@ -3710,7 +3724,7 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD
        uint32 acc_granted;
        SE_PRIV se_rights;
        BOOL can_add_accounts;
-       BOOL ret;
+       NTSTATUS ret;
        DISP_INFO *disp_info = NULL;
 
        /* Find the policy handle. Open a policy on it. */
@@ -3738,11 +3752,11 @@ NTSTATUS _samr_add_aliasmem(pipes_struct *p, SAMR_Q_ADD_ALIASMEM *q_u, SAMR_R_AD
                
        /******** END SeAddUsers BLOCK *********/
        
-       if (ret) {
+       if (NT_STATUS_IS_OK(ret)) {
                force_flush_samr_cache(disp_info);
        }
 
-       return ret ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
+       return ret;
 }
 
 /*********************************************************************
@@ -3755,7 +3769,7 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE
        uint32 acc_granted;
        SE_PRIV se_rights;
        BOOL can_add_accounts;
-       BOOL ret;
+       NTSTATUS ret;
        DISP_INFO *disp_info = NULL;
 
        /* Find the policy handle. Open a policy on it. */
@@ -3784,11 +3798,11 @@ NTSTATUS _samr_del_aliasmem(pipes_struct *p, SAMR_Q_DEL_ALIASMEM *q_u, SAMR_R_DE
                
        /******** END SeAddUsers BLOCK *********/
        
-       if (ret) {
+       if (NT_STATUS_IS_OK(ret)) {
                force_flush_samr_cache(disp_info);
        }
 
-       return ret ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
+       return ret;
 }
 
 /*********************************************************************
@@ -3847,19 +3861,18 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD
        }
 
        /* check a real user exist before we run the script to add a user to a group */
-       if (!NT_STATUS_IS_OK(sid_to_uid(pdb_get_user_sid(sam_user), &uid))) {
+       if (!sid_to_uid(pdb_get_user_sid(sam_user), &uid)) {
                pdb_free_sam(&sam_user);
                return NT_STATUS_NO_SUCH_USER;
        }
 
        pdb_free_sam(&sam_user);
 
-       if ((pwd=getpwuid_alloc(uid)) == NULL) {
+       if ((pwd=getpwuid_alloc(p->mem_ctx, uid)) == NULL) {
                return NT_STATUS_NO_SUCH_USER;
        }
 
        if ((grp=getgrgid(map.gid)) == NULL) {
-               passwd_free(&pwd);
                return NT_STATUS_NO_SUCH_GROUP;
        }
 
@@ -3867,8 +3880,7 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD
        fstrcpy(grp_name, grp->gr_name);
 
        /* if the user is already in the group */
-       if(user_in_unix_group_list(pwd->pw_name, grp_name)) {
-               passwd_free(&pwd);
+       if(user_in_unix_group(pwd->pw_name, grp_name)) {
                return NT_STATUS_MEMBER_IN_GROUP;
        }
 
@@ -3894,13 +3906,10 @@ NTSTATUS _samr_add_groupmem(pipes_struct *p, SAMR_Q_ADD_GROUPMEM *q_u, SAMR_R_AD
        /******** END SeAddUsers BLOCK *********/
        
        /* check if the user has been added then ... */
-       if(!user_in_unix_group_list(pwd->pw_name, grp_name)) {
-               passwd_free(&pwd);
+       if(!user_in_unix_group(pwd->pw_name, grp_name)) {
                return NT_STATUS_MEMBER_NOT_IN_GROUP;           /* don't know what to reply else */
        }
 
-       passwd_free(&pwd);
-
        force_flush_samr_cache(disp_info);
 
        return NT_STATUS_OK;
@@ -3961,7 +3970,7 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
        }
 
        /* if the user is not in the group */
-       if (!user_in_unix_group_list(pdb_get_username(sam_pass), grp_name)) {
+       if (!user_in_unix_group(pdb_get_username(sam_pass), grp_name)) {
                pdb_free_sam(&sam_pass);
                return NT_STATUS_MEMBER_NOT_IN_GROUP;
        }
@@ -3983,7 +3992,7 @@ NTSTATUS _samr_del_groupmem(pipes_struct *p, SAMR_Q_DEL_GROUPMEM *q_u, SAMR_R_DE
        /******** END SeAddUsers BLOCK *********/
        
        /* check if the user has been removed then ... */
-       if (user_in_unix_group_list(pdb_get_username(sam_pass), grp_name)) {
+       if (user_in_unix_group(pdb_get_username(sam_pass), grp_name)) {
                pdb_free_sam(&sam_pass);
                return NT_STATUS_ACCESS_DENIED;         /* don't know what to reply else */
        }
@@ -4290,19 +4299,28 @@ NTSTATUS _samr_create_dom_group(pipes_struct *p, SAMR_Q_CREATE_DOM_GROUP *q_u, S
                /* so far, so good */
                
                result = NT_STATUS_OK;
-               
-               r_u->rid = pdb_gid_to_group_rid( grp->gr_gid );
 
-               /* add the group to the mapping table */
+               if (pdb_rid_algorithm()) {
+                       r_u->rid = pdb_gid_to_group_rid( grp->gr_gid );
+               } else {
+                       if (!pdb_new_rid(&r_u->rid)) {
+                               result = NT_STATUS_ACCESS_DENIED;
+                       }
+               }
+
+               if (NT_STATUS_IS_OK(result)) {
+
+                       /* add the group to the mapping table */
                
-               sid_copy( &info_sid, get_global_sam_sid() );
-               sid_append_rid( &info_sid, r_u->rid );
-               sid_to_string( sid_string, &info_sid );
+                       sid_copy( &info_sid, get_global_sam_sid() );
+                       sid_append_rid( &info_sid, r_u->rid );
+                       sid_to_string( sid_string, &info_sid );
                
-               /* reset the error code if we fail to add the mapping entry */
+                       /* reset the error code if we fail to add the mapping entry */
                
-               if ( !add_initial_entry(grp->gr_gid, sid_string, SID_NAME_DOM_GRP, name, NULL) )
-                       result = NT_STATUS_ACCESS_DENIED;
+                       if ( !add_initial_entry(grp->gr_gid, sid_string, SID_NAME_DOM_GRP, name, NULL) )
+                               result = NT_STATUS_ACCESS_DENIED;
+               }
        }
 
        if ( can_add_accounts )
@@ -4383,18 +4401,26 @@ NTSTATUS _samr_create_dom_alias(pipes_struct *p, SAMR_Q_CREATE_DOM_ALIAS *q_u, S
                
        /******** END SeAddUsers BLOCK *********/
 
-       if (!NT_STATUS_IS_OK(result))
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(10, ("pdb_create_alias failed: %s\n",
+                          nt_errstr(result)));
                return result;
+       }
 
        sid_copy(&info_sid, get_global_sam_sid());
        sid_append_rid(&info_sid, r_u->rid);
 
-       if (!NT_STATUS_IS_OK(sid_to_gid(&info_sid, &gid)))
+       if (!sid_to_gid(&info_sid, &gid)) {
+               DEBUG(10, ("Could not find alias just created\n"));
                return NT_STATUS_ACCESS_DENIED;
+       }
 
        /* check if the group has been successfully created */
-       if ( getgrgid(gid) == NULL )
+       if ( getgrgid(gid) == NULL ) {
+               DEBUG(10, ("getgrgid(%d) of just created alias failed\n",
+                          gid));
                return NT_STATUS_ACCESS_DENIED;
+       }
 
        if ((info = get_samr_info_by_sid(&info_sid)) == NULL)
                return NT_STATUS_NO_MEMORY;
@@ -4485,7 +4511,8 @@ NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_
        GROUP_MAP map;
        GROUP_INFO_CTR *ctr;
        uint32 acc_granted;
-       BOOL ret;
+       NTSTATUS ret;
+       BOOL result;
        BOOL can_mod_accounts;
        DISP_INFO *disp_info = NULL;
 
@@ -4497,9 +4524,9 @@ NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_
        }
 
        become_root();
-       ret = get_domain_group_from_sid(group_sid, &map);
+       result = get_domain_group_from_sid(group_sid, &map);
        unbecome_root();
-       if (!ret)
+       if (!result)
                return NT_STATUS_NO_SUCH_GROUP;
        
        ctr=q_u->ctr;
@@ -4529,11 +4556,11 @@ NTSTATUS _samr_set_groupinfo(pipes_struct *p, SAMR_Q_SET_GROUPINFO *q_u, SAMR_R_
 
        /******** End SeAddUsers BLOCK *********/
 
-       if (ret) {
+       if (NT_STATUS_IS_OK(ret)) {
                force_flush_samr_cache(disp_info);
        }
 
-       return ret ? NT_STATUS_OK : NT_STATUS_ACCESS_DENIED;
+       return ret;
 }
 
 /*********************************************************************
index a22d6db266c4a73a783b725b4605c8d7584a9472..e6d45f76ec0285046294ca438fc318c662fe2306 100644 (file)
@@ -1620,10 +1620,13 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
                        /* if the user is not root, doesn't have SE_PRINT_OPERATOR privilege,
                           and not a printer admin, then fail */
                        
-                       if ( user.ut.uid != 0
-                               && !user_has_privileges( user.nt_user_token, &se_printop )
-                               && !user_in_list(uidtoname(user.ut.uid), lp_printer_admin(snum), user.ut.groups, user.ut.ngroups) )
-                       {
+                       if ((user.ut.uid != 0) &&
+                           !user_has_privileges(user.nt_user_token,
+                                                &se_printop ) &&
+                           !token_contains_name_in_list(
+                                   uidtoname(user.ut.uid), NULL,
+                                   user.nt_user_token,
+                                   lp_printer_admin(snum))) {
                                close_printer_handle(p, handle);
                                return WERR_ACCESS_DENIED;
                        }
@@ -1676,7 +1679,10 @@ WERROR _spoolss_open_printer_ex( pipes_struct *p, SPOOL_Q_OPEN_PRINTER_EX *q_u,
                        return WERR_ACCESS_DENIED;
                }
 
-               if (!user_ok(uidtoname(user.ut.uid), snum, user.ut.groups, user.ut.ngroups) || !print_access_check(&user, snum, printer_default->access_required)) {
+               if (!user_ok_token(uidtoname(user.ut.uid), user.nt_user_token,
+                                  snum) ||
+                   !print_access_check(&user, snum,
+                                       printer_default->access_required)) {
                        DEBUG(3, ("access DENIED for printer open\n"));
                        close_printer_handle(p, handle);
                        return WERR_ACCESS_DENIED;
@@ -5997,7 +6003,7 @@ BOOL add_printer_hook(NT_USER_TOKEN *token, NT_PRINTER_INFO_LEVEL *printer)
 
        numlines = 0;
        /* Get lines and convert them back to dos-codepage */
-       qlines = fd_lines_load(fd, &numlines);
+       qlines = fd_lines_load(fd, &numlines, 0);
        DEBUGADD(10,("Lines returned = [%d]\n", numlines));
        close(fd);
 
@@ -7195,7 +7201,7 @@ WERROR enumports_hook( int *count, char ***lines )
                }
 
                numlines = 0;
-               qlines = fd_lines_load(fd, &numlines);
+               qlines = fd_lines_load(fd, &numlines, 0);
                DEBUGADD(10,("Lines returned = [%d]\n", numlines));
                close(fd);
        }
index 8150a8bf698b0e6135501e975dd9bf230863c24b..f279c98c31205393d853822a0960f2c27ffa082a 100644 (file)
@@ -29,26 +29,6 @@ extern struct generic_mapping file_generic_mapping;
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_RPC_SRV
 
-#define INVALID_SHARENAME_CHARS "<>*?|/\\+=;:\","
-
-/********************************************************************
- Check a string for any occurrences of a specified list of invalid 
- characters.
-********************************************************************/
-
-static BOOL validate_net_name( const char *name, const char *invalid_chars, int max_len )
-{
-       int i;
-
-       for ( i=0; i<max_len && name[i]; i++ ) {
-               /* fail if strchr_m() finds one of the invalid characters */
-               if ( name[i] && strchr_m( invalid_chars, name[i] ) )
-                       return False;
-       }
-
-       return True;
-}
-
 /*******************************************************************
  Utility function to get the 'type' of a share from an snum.
  ********************************************************************/
@@ -131,190 +111,11 @@ static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int sn
        init_srv_share_info2_str(&sh2->info_2_str, net_name, remark, path, passwd);
 }
 
-/*******************************************************************
- What to do when smb.conf is updated.
- ********************************************************************/
-
-static void smb_conf_updated(int msg_type, struct process_id src,
-                            void *buf, size_t len)
-{
-       DEBUG(10,("smb_conf_updated: Got message saying smb.conf was updated. Reloading.\n"));
-       reload_services(False);
-}
-
-/*******************************************************************
- Create the share security tdb.
- ********************************************************************/
-
-static TDB_CONTEXT *share_tdb; /* used for share security descriptors */
-#define SHARE_DATABASE_VERSION_V1 1
-#define SHARE_DATABASE_VERSION_V2 2 /* version id in little endian. */
-
-BOOL share_info_db_init(void)
-{
-       static pid_t local_pid;
-       const char *vstring = "INFO/version";
-       int32 vers_id;
-       if (share_tdb && local_pid == sys_getpid())
-               return True;
-       share_tdb = tdb_open_log(lock_path("share_info.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600);
-       if (!share_tdb) {
-               DEBUG(0,("Failed to open share info database %s (%s)\n",
-                       lock_path("share_info.tdb"), strerror(errno) ));
-               return False;
-       }
-       local_pid = sys_getpid();
-       /* handle a Samba upgrade */
-       tdb_lock_bystring(share_tdb, vstring, 0);
-
-       /* Cope with byte-reversed older versions of the db. */
-       vers_id = tdb_fetch_int32(share_tdb, vstring);
-       if ((vers_id == SHARE_DATABASE_VERSION_V1) || (IREV(vers_id) == SHARE_DATABASE_VERSION_V1)) {
-               /* Written on a bigendian machine with old fetch_int code. Save as le. */
-               tdb_store_int32(share_tdb, vstring, SHARE_DATABASE_VERSION_V2);
-               vers_id = SHARE_DATABASE_VERSION_V2;
-       }
-
-       if (vers_id != SHARE_DATABASE_VERSION_V2) {
-               tdb_traverse(share_tdb, tdb_traverse_delete_fn, NULL);
-               tdb_store_int32(share_tdb, vstring, SHARE_DATABASE_VERSION_V2);
-       }
-       tdb_unlock_bystring(share_tdb, vstring);
-
-       message_register(MSG_SMB_CONF_UPDATED, smb_conf_updated);
-       return True;
-}
-
-/*******************************************************************
- Fake up a Everyone, full access as a default.
- ********************************************************************/
-
-static SEC_DESC *get_share_security_default( TALLOC_CTX *ctx, int snum, size_t *psize)
-{
-       SEC_ACCESS sa;
-       SEC_ACE ace;
-       SEC_ACL *psa = NULL;
-       SEC_DESC *psd = NULL;
-       uint32 def_access = GENERIC_ALL_ACCESS;
-
-       se_map_generic(&def_access, &file_generic_mapping);
-
-       init_sec_access(&sa, GENERIC_ALL_ACCESS | def_access );
-       init_sec_ace(&ace, &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, sa, 0);
-
-       if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, 1, &ace)) != NULL) {
-               psd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, psa, psize);
-       }
-
-       if (!psd) {
-               DEBUG(0,("get_share_security: Failed to make SEC_DESC.\n"));
-               return NULL;
-       }
-
-       return psd;
-}
-
-/*******************************************************************
- Pull a security descriptor from the share tdb.
- ********************************************************************/
-
-static SEC_DESC *get_share_security( TALLOC_CTX *ctx, int snum, size_t *psize)
-{
-       prs_struct ps;
-       fstring key;
-       SEC_DESC *psd = NULL;
-
-       *psize = 0;
-
-       /* Fetch security descriptor from tdb */
-       slprintf(key, sizeof(key)-1, "SECDESC/%s", lp_servicename(snum));
-       if (tdb_prs_fetch(share_tdb, key, &ps, ctx)!=0 ||
-               !sec_io_desc("get_share_security", &psd, &ps, 1)) {
-               DEBUG(4,("get_share_security: using default secdesc for %s\n", lp_servicename(snum) ));
-               return get_share_security_default(ctx, snum, psize);
-       }
-
-       if (psd)
-               *psize = sec_desc_size(psd);
-
-       prs_mem_free(&ps);
-       return psd;
-}
-
-/*******************************************************************
- Store a security descriptor in the share db.
- ********************************************************************/
-
-static BOOL set_share_security(TALLOC_CTX *ctx, const char *share_name, SEC_DESC *psd)
-{
-       prs_struct ps;
-       TALLOC_CTX *mem_ctx = NULL;
-       fstring key;
-       BOOL ret = False;
-
-       mem_ctx = talloc_init("set_share_security");
-       if (mem_ctx == NULL)
-               return False;
-
-       prs_init(&ps, (uint32)sec_desc_size(psd), mem_ctx, MARSHALL);
-       if (!sec_io_desc("share_security", &psd, &ps, 1))
-               goto out;
-       slprintf(key, sizeof(key)-1, "SECDESC/%s", share_name);
-       if (tdb_prs_store(share_tdb, key, &ps)==0) {
-               ret = True;
-               DEBUG(5,("set_share_security: stored secdesc for %s\n", share_name ));
-       } else {
-               DEBUG(1,("set_share_security: Failed to store secdesc for %s\n", share_name ));
-       } 
-
-       /* Free malloc'ed memory */
-out:
-       prs_mem_free(&ps);
-       if (mem_ctx)
-               talloc_destroy(mem_ctx);
-       return ret;
-}
-
-/*******************************************************************
- Delete a security descriptor.
-********************************************************************/
-
-static BOOL delete_share_security(int snum)
-{
-       TDB_DATA kbuf;
-       fstring key;
-
-       slprintf(key, sizeof(key)-1, "SECDESC/%s", lp_servicename(snum));
-       kbuf.dptr = key;
-       kbuf.dsize = strlen(key)+1;
-
-       if (tdb_delete(share_tdb, kbuf) != 0) {
-               DEBUG(0,("delete_share_security: Failed to delete entry for share %s\n",
-                               lp_servicename(snum) ));
-               return False;
-       }
-
-       return True;
-}
-
 /*******************************************************************
  Map any generic bits to file specific bits.
 ********************************************************************/
 
-void map_generic_share_sd_bits(SEC_DESC *psd)
+static void map_generic_share_sd_bits(SEC_DESC *psd)
 {
        int i;
        SEC_ACL *ps_dacl = NULL;
@@ -517,7 +318,7 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
               uint32 info_level, uint32 *resume_hnd, uint32 *total_entries, BOOL all_shares)
 {
        int num_entries = 0;
-       int num_services = lp_numservices();
+       int num_services = 0;
        int snum;
        TALLOC_CTX *ctx = p->mem_ctx;
 
@@ -528,6 +329,11 @@ static BOOL init_srv_share_info_ctr(pipes_struct *p, SRV_SHARE_INFO_CTR *ctr,
        ctr->info_level = ctr->switch_value = info_level;
        *resume_hnd = 0;
 
+       /* Ensure all the usershares are loaded. */
+       become_root();
+       num_services = load_usershare_shares();
+       unbecome_root();
+
        /* Count the number of entries. */
        for (snum = 0; snum < num_services; snum++) {
                if (lp_browseable(snum) && lp_snum_ok(snum) && (all_shares || !is_hidden_share(snum)) )
index 956dbfa402702fd0b1f2074d0ef7eca0943cb86f..b4d43bda5ee5339a0acac079ca43c16487c28dc8 100644 (file)
@@ -3,6 +3,7 @@
    RPC pipe client
 
    Copyright (C) Tim Potter 2000
+   Copyright (C) Jelmer Vernooij       2005.
 
    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
@@ -27,7 +28,7 @@
 static NTSTATUS cmd_dfs_exist(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                               int argc, const char **argv)
 {
-       BOOL dfs_exists;
+       uint32 dfs_exists;
        NTSTATUS result;
 
        if (argc != 1) {
@@ -35,7 +36,7 @@ static NTSTATUS cmd_dfs_exist(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                return NT_STATUS_OK;
        }
 
-       result = rpccli_dfs_exist(cli, mem_ctx, &dfs_exists);
+       result = rpccli_dfs_GetManagerVersion(cli, mem_ctx, &dfs_exists);
 
        if (NT_STATUS_IS_OK(result))
                printf("dfs is %spresent\n", dfs_exists ? "" : "not ");
@@ -47,21 +48,21 @@ static NTSTATUS cmd_dfs_add(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                             int argc, const char **argv)
 {
        NTSTATUS result;
-       const char *entrypath, *servername, *sharename, *comment;
+       const char *path, *servername, *sharename, *comment;
        uint32 flags = 0;
 
        if (argc != 5) {
-               printf("Usage: %s entrypath servername sharename comment\n", 
+               printf("Usage: %s path servername sharename comment\n", 
                       argv[0]);
                return NT_STATUS_OK;
        }
 
-       entrypath = argv[1];
+       path = argv[1];
        servername = argv[2];
        sharename = argv[3];
        comment = argv[4];
 
-       result = rpccli_dfs_add(cli, mem_ctx, entrypath, servername, 
+       result = rpccli_dfs_Add(cli, mem_ctx, path, servername, 
                             sharename, comment, flags);
 
        return result;
@@ -71,18 +72,18 @@ static NTSTATUS cmd_dfs_remove(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                                int argc, const char **argv)
 {
        NTSTATUS result;
-       const char *entrypath, *servername, *sharename;
+       const char *path, *servername, *sharename;
 
        if (argc != 4) {
-               printf("Usage: %s entrypath servername sharename\n", argv[0]);
+               printf("Usage: %s path servername sharename\n", argv[0]);
                return NT_STATUS_OK;
        }
 
-       entrypath = argv[1];
+       path = argv[1];
        servername = argv[2];
        sharename = argv[3];
 
-       result = rpccli_dfs_remove(cli, mem_ctx, entrypath, servername, 
+       result = rpccli_dfs_Remove(cli, mem_ctx, path, servername, 
                                sharename);
 
        return result;
@@ -90,78 +91,92 @@ static NTSTATUS cmd_dfs_remove(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
 
 /* Display a DFS_INFO_1 structure */
 
-static void display_dfs_info_1(DFS_INFO_1 *info1)
+static void display_dfs_info_1(NETDFS_DFS_INFO1 *info1)
 {
        fstring temp;
 
-       unistr2_to_ascii(temp, &info1->entrypath, sizeof(temp) - 1);
-       printf("entrypath: %s\n", temp);
+       unistr2_to_ascii(temp, &info1->path, sizeof(temp) - 1);
+       printf("path: %s\n", temp);
 }
 
 /* Display a DFS_INFO_2 structure */
 
-static void display_dfs_info_2(DFS_INFO_2 *info2)
+static void display_dfs_info_2(NETDFS_DFS_INFO2 *info2)
 {
        fstring temp;
 
-       unistr2_to_ascii(temp, &info2->entrypath, sizeof(temp) - 1);
-       printf("entrypath: %s\n", temp);
+       unistr2_to_ascii(temp, &info2->path, sizeof(temp) - 1);
+       printf("path: %s\n", temp);
 
        unistr2_to_ascii(temp, &info2->comment, sizeof(temp) - 1);
        printf("\tcomment: %s\n", temp);
 
        printf("\tstate: %d\n", info2->state);
-       printf("\tnum_storages: %d\n", info2->num_storages);
+       printf("\tnum_stores: %d\n", info2->num_stores);
 }
 
 /* Display a DFS_INFO_3 structure */
 
-static void display_dfs_info_3(DFS_INFO_3 *info3)
+static void display_dfs_info_3(NETDFS_DFS_INFO3 *info3)
 {
        fstring temp;
        int i;
 
-       unistr2_to_ascii(temp, &info3->entrypath, sizeof(temp) - 1);
-       printf("entrypath: %s\n", temp);
+       unistr2_to_ascii(temp, &info3->path, sizeof(temp) - 1);
+       printf("path: %s\n", temp);
 
        unistr2_to_ascii(temp, &info3->comment, sizeof(temp) - 1);
        printf("\tcomment: %s\n", temp);
 
        printf("\tstate: %d\n", info3->state);
-       printf("\tnum_storages: %d\n", info3->num_storages);
+       printf("\tnum_stores: %d\n", info3->num_stores);
 
-       for (i = 0; i < info3->num_storages; i++) {
-               DFS_STORAGE_INFO *dsi = &info3->storages[i];
+       for (i = 0; i < info3->num_stores; i++) {
+               NETDFS_DFS_STORAGEINFO *dsi = &info3->stores[i];
 
-               unistr2_to_ascii(temp, &dsi->servername, sizeof(temp) - 1);
-               printf("\t\tstorage[%d] servername: %s\n", i, temp);
+               unistr2_to_ascii(temp, &dsi->server, sizeof(temp) - 1);
+               printf("\t\tstorage[%d] server: %s\n", i, temp);
 
-               unistr2_to_ascii(temp, &dsi->sharename, sizeof(temp) - 1);
-               printf("\t\tstorage[%d] sharename: %s\n", i, temp);
+               unistr2_to_ascii(temp, &dsi->share, sizeof(temp) - 1);
+               printf("\t\tstorage[%d] share: %s\n", i, temp);
        }
 }
 
-/* Display a DFS_INFO_CTR structure */
 
-static void display_dfs_info_ctr(DFS_INFO_CTR *ctr)
+/* Display a DFS_INFO_CTR structure */
+static void display_dfs_info(NETDFS_DFS_INFO_CTR *ctr)
 {
-       int i;
-
-       for (i = 0; i < ctr->num_entries; i++) {
-               switch (ctr->switch_value) {
+       switch (ctr->switch_value) {
                case 0x01:
-                       display_dfs_info_1(&ctr->dfs.info1[i]);
+                       display_dfs_info_1(&ctr->u.info1);
                        break;
                case 0x02:
-                       display_dfs_info_2(&ctr->dfs.info2[i]);
+                       display_dfs_info_2(&ctr->u.info2);
                        break;
                case 0x03:
-                       display_dfs_info_3(&ctr->dfs.info3[i]);
+                       display_dfs_info_3(&ctr->u.info3);
                        break;
                default:
                        printf("unsupported info level %d\n", 
                               ctr->switch_value);
                        break;
+       }
+}
+
+static void display_dfs_enumstruct(NETDFS_DFS_ENUMSTRUCT *ctr)
+{
+       int i;
+       
+       /* count is always the first element, so we can just use info1 here */
+       for (i = 0; i < ctr->e.u.info1.count; i++) {
+               switch (ctr->level) {
+               case 1: display_dfs_info_1(&ctr->e.u.info1.s[i]); break;
+               case 2: display_dfs_info_2(&ctr->e.u.info2.s[i]); break;
+               case 3: display_dfs_info_3(&ctr->e.u.info3.s[i]); break;
+               default:
+                               printf("unsupported info level %d\n", 
+                              ctr->level);
+                               return;
                }
        }
 }
@@ -171,9 +186,11 @@ static void display_dfs_info_ctr(DFS_INFO_CTR *ctr)
 static NTSTATUS cmd_dfs_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
                              int argc, const char **argv)
 {
-       DFS_INFO_CTR ctr;
+       NETDFS_DFS_ENUMSTRUCT str;
+       NETDFS_DFS_ENUMINFO_CTR ctr;
        NTSTATUS result;
        uint32 info_level = 1;
+       uint32 unknown = 0, total = 0;
 
        if (argc > 2) {
                printf("Usage: %s [info_level]\n", argv[0]);
@@ -183,10 +200,14 @@ static NTSTATUS cmd_dfs_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx,
        if (argc == 2)
                info_level = atoi(argv[1]);
 
-       result = rpccli_dfs_enum(cli, mem_ctx, info_level, &ctr);
+       ZERO_STRUCT(ctr);
+       init_netdfs_dfs_EnumStruct(&str, info_level, ctr);
+       str.e.ptr0 = 1;
+
+       result = rpccli_dfs_Enum(cli, mem_ctx, info_level, 0xFFFFFFFF, &str, &unknown, &total);
 
        if (NT_STATUS_IS_OK(result))
-               display_dfs_info_ctr(&ctr);
+               display_dfs_enumstruct(&str);
 
        return result;
 }
@@ -195,28 +216,28 @@ static NTSTATUS cmd_dfs_getinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx
                                 int argc, const char **argv)
 {
        NTSTATUS result;
-       const char *entrypath, *servername, *sharename;
+       const char *path, *servername, *sharename;
        uint32 info_level = 1;
-       DFS_INFO_CTR ctr;
+       NETDFS_DFS_INFO_CTR ctr;
 
        if (argc < 4 || argc > 5) {
-               printf("Usage: %s entrypath servername sharename "
+               printf("Usage: %s path servername sharename "
                        "[info_level]\n", argv[0]);
                return NT_STATUS_OK;
        }
 
-       entrypath = argv[1];
+       path = argv[1];
        servername = argv[2];
        sharename = argv[3];
 
        if (argc == 5)
                info_level = atoi(argv[4]);
 
-       result = rpccli_dfs_get_info(cli, mem_ctx, entrypath, servername, 
+       result = rpccli_dfs_GetInfo(cli, mem_ctx, path, servername, 
                                  sharename, info_level, &ctr);
 
        if (NT_STATUS_IS_OK(result))
-               display_dfs_info_ctr(&ctr);
+               display_dfs_info(&ctr);
 
        return result;
 }
index 5adaf46981819ccb67dc631ab5ea6eb7d7b91e18..1b7ebac45f9d337b4111c1a9c46fea45c864685d 100644 (file)
@@ -47,7 +47,7 @@ static NTSTATUS name_to_sid(struct rpc_pipe_client *cli,
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
-       result = rpccli_lsa_lookup_names(cli, mem_ctx, &pol, 1, &name, &sids, &sid_types);
+       result = rpccli_lsa_lookup_names(cli, mem_ctx, &pol, 1, &name, NULL, &sids, &sid_types);
        if (!NT_STATUS_IS_OK(result))
                goto done;
 
@@ -165,7 +165,7 @@ static NTSTATUS cmd_lsa_lookup_names(struct rpc_pipe_client *cli,
                goto done;
 
        result = rpccli_lsa_lookup_names(cli, mem_ctx, &pol, argc - 1, 
-                                     (const char**)(argv + 1), &sids, &types);
+                                     (const char**)(argv + 1), NULL, &sids, &types);
 
        if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) != 
            NT_STATUS_V(STATUS_SOME_UNMAPPED))
index 991b55a13c80a524f1c04f2c21188fc6ffd9c29e..93a3e39036323f9aff1cf234cd79b63d9249d79a 100644 (file)
@@ -1065,6 +1065,82 @@ static NTSTATUS cmd_samr_query_aliasmem(struct rpc_pipe_client *cli,
        return result;
 }
 
+/* Query delete an alias membership */
+
+static NTSTATUS cmd_samr_delete_alias(struct rpc_pipe_client *cli, 
+                                     TALLOC_CTX *mem_ctx,
+                                     int argc, const char **argv) 
+{
+       POLICY_HND connect_pol, domain_pol, alias_pol;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       uint32 alias_rid;
+       uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+
+       if (argc != 3) {
+               printf("Usage: %s builtin|domain [rid|name]\n", argv[0]);
+               return NT_STATUS_OK;
+       }
+
+       alias_rid = strtoul(argv[2], NULL, 10);
+       
+       /* Open SAMR handle */
+
+       result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+                                  &connect_pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       /* Open handle on domain */
+       
+       if (StrCaseCmp(argv[1], "domain")==0)
+               result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
+                                             MAXIMUM_ALLOWED_ACCESS,
+                                             &domain_sid, &domain_pol);
+       else if (StrCaseCmp(argv[1], "builtin")==0)
+               result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
+                                             MAXIMUM_ALLOWED_ACCESS,
+                                             &global_sid_Builtin, &domain_pol);
+       else
+               return NT_STATUS_INVALID_PARAMETER;
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       /* Open handle on alias */
+
+       result = rpccli_samr_open_alias(cli, mem_ctx, &domain_pol,
+                                    access_mask,
+                                    alias_rid, &alias_pol);
+       if (!NT_STATUS_IS_OK(result) && (alias_rid == 0)) {
+               /* Probably this was a user name, try lookupnames */
+               uint32 num_rids;
+               uint32 *rids, *types;
+               
+               result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol,
+                                                 1000, 1, &argv[2],
+                                                 &num_rids, &rids,
+                                                 &types);
+
+               if (NT_STATUS_IS_OK(result)) {
+                       result = rpccli_samr_open_alias(cli, mem_ctx,
+                                                      &domain_pol,
+                                                      access_mask,
+                                                      rids[0], &alias_pol);
+               }
+       }
+
+       result = rpccli_samr_delete_dom_alias(cli, mem_ctx, &alias_pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       rpccli_samr_close(cli, mem_ctx, &domain_pol);
+       rpccli_samr_close(cli, mem_ctx, &connect_pol);
+ done:
+       return result;
+}
+
 /* Query display info */
 
 static NTSTATUS cmd_samr_query_dispinfo(struct rpc_pipe_client *cli, 
@@ -1405,6 +1481,65 @@ static NTSTATUS cmd_samr_create_dom_group(struct rpc_pipe_client *cli,
        return result;
 }
 
+/* Create domain alias */
+
+static NTSTATUS cmd_samr_create_dom_alias(struct rpc_pipe_client *cli, 
+                                          TALLOC_CTX *mem_ctx,
+                                          int argc, const char **argv) 
+{
+       POLICY_HND connect_pol, domain_pol, alias_pol;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       const char *alias_name;
+       uint32 access_mask = MAXIMUM_ALLOWED_ACCESS;
+
+       if ((argc < 2) || (argc > 3)) {
+               printf("Usage: %s aliasname [access mask]\n", argv[0]);
+               return NT_STATUS_OK;
+       }
+
+       alias_name = argv[1];
+       
+       if (argc > 2)
+                sscanf(argv[2], "%x", &access_mask);
+
+       /* Get sam policy handle */
+
+       result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, 
+                                  &connect_pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       /* Get domain policy handle */
+
+       result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol,
+                                        access_mask,
+                                        &domain_sid, &domain_pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       /* Create domain user */
+
+       result = rpccli_samr_create_dom_alias(cli, mem_ctx, &domain_pol,
+                                             alias_name, &alias_pol);
+
+       if (!NT_STATUS_IS_OK(result))
+               goto done;
+
+       result = rpccli_samr_close(cli, mem_ctx, &alias_pol);
+       if (!NT_STATUS_IS_OK(result)) goto done;
+
+       result = rpccli_samr_close(cli, mem_ctx, &domain_pol);
+       if (!NT_STATUS_IS_OK(result)) goto done;
+
+       result = rpccli_samr_close(cli, mem_ctx, &connect_pol);
+       if (!NT_STATUS_IS_OK(result)) goto done;
+
+ done:
+       return result;
+}
+
 /* Lookup sam names */
 
 static NTSTATUS cmd_samr_lookup_names(struct rpc_pipe_client *cli, 
@@ -1793,6 +1928,7 @@ struct cmd_set samr_commands[] = {
        { "queryuseraliases",   RPC_RTYPE_NTSTATUS, cmd_samr_query_useraliases,         NULL, PI_SAMR, NULL,    "Query user aliases",      "" },
        { "querygroupmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_groupmem,    NULL, PI_SAMR, NULL,    "Query group membership",  "" },
        { "queryaliasmem",      RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasmem,    NULL, PI_SAMR, NULL,    "Query alias membership",  "" },
+       { "deletealias",        RPC_RTYPE_NTSTATUS, cmd_samr_delete_alias,      NULL, PI_SAMR, NULL,    "Delete an alias",  "" },
        { "querydispinfo",      RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo,    NULL, PI_SAMR, NULL,    "Query display info",      "" },
        { "querydominfo",       RPC_RTYPE_NTSTATUS, cmd_samr_query_dominfo,     NULL, PI_SAMR, NULL,    "Query domain info",       "" },
        { "enumdomusers",      RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_users,       NULL, PI_SAMR, NULL,  "Enumerate domain users", "" },
@@ -1801,6 +1937,7 @@ struct cmd_set samr_commands[] = {
 
        { "createdomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_user,       NULL, PI_SAMR, NULL,        "Create domain user",      "" },
        { "createdomgroup",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_group,      NULL, PI_SAMR, NULL,        "Create domain group",     "" },
+       { "createdomalias",     RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_alias,      NULL, PI_SAMR, NULL,        "Create domain alias",     "" },
        { "samlookupnames",     RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names,          NULL, PI_SAMR, NULL,        "Look up names",           "" },
        { "samlookuprids",      RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids,           NULL, PI_SAMR, NULL,        "Look up names",           "" },
        { "deletedomuser",      RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user,       NULL, PI_SAMR, NULL,        "Delete domain user",      "" },
index 9fc1a573a92422dce3566d74eee3d86ae6b1e2ca..aac8b70013ac3bf424c8dbf7b5fd243b44fa059c 100644 (file)
@@ -188,6 +188,18 @@ NTSTATUS idmap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
        if (proxyonly)
                return NT_STATUS_UNSUCCESSFUL;
 
+       if (sid_check_is_in_our_domain(sid)) {
+               DEBUG(3, ("Refusing to add SID %s to idmap, it's our own "
+                         "domain\n", sid_string_static(sid)));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+               
+       if (sid_check_is_in_builtin(sid)) {
+               DEBUG(3, ("Refusing to add SID %s to idmap, it's our builtin "
+                         "domain\n", sid_string_static(sid)));
+               return NT_STATUS_ACCESS_DENIED;
+       }
+
        DEBUG(10, ("idmap_set_mapping: Set %s to %s %lu\n",
                   sid_string_static(sid),
                   ((id_type & ID_TYPEMASK) == ID_USERID) ? "UID" : "GID",
@@ -225,6 +237,18 @@ NTSTATUS idmap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *sid)
        if (proxyonly)
                return NT_STATUS_UNSUCCESSFUL;
 
+       if (sid_check_is_in_our_domain(sid)) {
+               DEBUG(9, ("sid %s is in our domain -- go look in passdb\n",
+                         sid_string_static(sid)));
+               return NT_STATUS_NONE_MAPPED;
+       }
+
+       if (sid_check_is_in_builtin(sid)) {
+               DEBUG(9, ("sid %s is in builtin domain -- go look in passdb\n",
+                         sid_string_static(sid)));
+               return NT_STATUS_NONE_MAPPED;
+       }
+
        loc_type = *id_type;
 
        if (remote_map) {
@@ -337,23 +361,6 @@ NTSTATUS idmap_allocate_id(unid_t *id, int id_type)
        return cache_map->allocate_id( id, id_type );
 }
 
-/**************************************************************************
- Alloocate a new RID
-**************************************************************************/
-
-NTSTATUS idmap_allocate_rid(uint32 *rid, int type)
-{
-       /* we have to allocate from the authoritative backend */
-       
-       if (proxyonly)
-               return NT_STATUS_UNSUCCESSFUL;
-
-       if ( remote_map )
-               return remote_map->allocate_rid( rid, type );
-
-       return cache_map->allocate_rid( rid, type );
-}
-
 /**************************************************************************
  Shutdown maps.
 **************************************************************************/
index 47e349483ddf6e63ea4f94db0b6e4a6a585416dd..f9a959e7ec0c2e6c8d805a82b1d81f437f61da19 100644 (file)
@@ -371,12 +371,6 @@ static NTSTATUS ad_idmap_close(void)
        return NT_STATUS_OK;
 }
 
-/* New for beta3 */
-static NTSTATUS ad_idmap_allocate_rid(uint32 *rid, int rid_type)
-{
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
 static NTSTATUS ad_idmap_allocate_id(unid_t *id, int id_type)
 {
        return NT_STATUS_NOT_IMPLEMENTED;
@@ -389,7 +383,6 @@ static void ad_idmap_status(void)
 
 static struct idmap_methods ad_methods = {
        ad_idmap_init,
-       ad_idmap_allocate_rid,
        ad_idmap_allocate_id,
        ad_idmap_get_sid_from_id,
        ad_idmap_get_id_from_sid,
index b4a8c8a75285cf217fc92e485f4b4e2322d8a7ce..17482a5146d0890b73b0c73bd681af1277064199 100644 (file)
@@ -113,260 +113,6 @@ static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
        return NT_STATUS_OK;
 }
 
-/**********************************************************************
- Even if the sambaDomain attribute in LDAP tells us that this RID is 
- safe to use, always check before use.  
-*********************************************************************/
-
-static BOOL sid_in_use(struct ldap_idmap_state *state, 
-                      const DOM_SID *sid, int *error) 
-{
-       fstring filter;
-       fstring sid_string;
-       LDAPMessage *result = NULL;
-       int rc;
-       const char *sid_attr[] = {LDAP_ATTRIBUTE_SID, NULL};
-
-       slprintf(filter, sizeof(filter)-1, "(%s=%s)", LDAP_ATTRIBUTE_SID, sid_to_string(sid_string, sid));
-
-       rc = smbldap_search_suffix(state->smbldap_state, 
-                                  filter, sid_attr, &result);
-
-       if (rc != LDAP_SUCCESS) {
-               char *ld_error = NULL;
-               ldap_get_option(state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
-               DEBUG(2, ("Failed to check if sid %s is alredy in use: %s\n",
-                         sid_string, ld_error));
-               SAFE_FREE(ld_error);
-
-               *error = rc;
-               return True;
-       }
-       
-       if ((ldap_count_entries(state->smbldap_state->ldap_struct, result)) > 0) {
-               DEBUG(3, ("Sid %s already in use - trying next RID\n",
-                         sid_string));
-               ldap_msgfree(result);
-               return True;
-       }
-
-       ldap_msgfree(result);
-
-       /* good, sid is not in use */
-       return False;
-}
-
-/**********************************************************************
- Set the new nextRid attribute, and return one we can use.
-
- This also checks that this RID is actually free - in case the admin
- manually stole it :-).
-*********************************************************************/
-
-static NTSTATUS ldap_next_rid(struct ldap_idmap_state *state, uint32 *rid, 
-                              int rid_type)
-{
-       NTSTATUS ret = NT_STATUS_UNSUCCESSFUL;
-       LDAPMessage *domain_result = NULL;
-       LDAPMessage *entry  = NULL;
-       char *dn;
-       LDAPMod **mods = NULL;
-       fstring old_rid_string;
-       fstring next_rid_string;
-       fstring algorithmic_rid_base_string;
-       uint32 next_rid;
-       uint32 alg_rid_base;
-       int attempts = 0;
-       char *ld_error = NULL;
-
-       while (attempts < 10) {
-               if (!NT_STATUS_IS_OK(ret = smbldap_search_domain_info(state->smbldap_state, 
-                               &domain_result, get_global_sam_name(), True))) {
-                       return ret;
-               }
-       
-               entry = ldap_first_entry(state->smbldap_state->ldap_struct, domain_result);
-               if (!entry) {
-                       DEBUG(0, ("Could not get domain info entry\n"));
-                       ldap_msgfree(domain_result);
-                       return ret;
-               }
-
-               if ((dn = smbldap_get_dn(state->smbldap_state->ldap_struct, entry)) == NULL) {
-                       DEBUG(0, ("Could not get domain info DN\n"));
-                       ldap_msgfree(domain_result);
-                       return ret;
-               }
-
-               /* yes, we keep 3 seperate counters, one for rids between 1000 (BASE_RID) and 
-                  algorithmic_rid_base.  The other two are to avoid stomping on the
-                  different sets of algorithmic RIDs */
-               
-               if (smbldap_get_single_pstring(state->smbldap_state->ldap_struct, entry,
-                                        get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE),
-                                        algorithmic_rid_base_string)) {
-                       
-                       alg_rid_base = (uint32)atol(algorithmic_rid_base_string);
-               } else {
-                       alg_rid_base = algorithmic_rid_base();
-                       /* Try to make the modification atomically by enforcing the
-                          old value in the delete mod. */
-                       slprintf(algorithmic_rid_base_string, sizeof(algorithmic_rid_base_string)-1, "%d", alg_rid_base);
-                       smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods, 
-                                        get_attr_key2string(dominfo_attr_list, LDAP_ATTR_ALGORITHMIC_RID_BASE), 
-                                        algorithmic_rid_base_string);
-               }
-
-               next_rid = 0;
-
-               if (alg_rid_base > BASE_RID) {
-                       /* we have a non-default 'algorithmic rid base', so we have 'low' rids that we 
-                          can allocate to new users */
-                       if (smbldap_get_single_pstring(state->smbldap_state->ldap_struct, entry,
-                                                get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID),
-                                                old_rid_string)) {
-                               *rid = (uint32)atol(old_rid_string);
-                       } else {
-                               *rid = BASE_RID;
-                       }
-
-                       next_rid = *rid+1;
-                       if (next_rid >= alg_rid_base) {
-                               ldap_msgfree(domain_result);
-                               return NT_STATUS_UNSUCCESSFUL;
-                       }
-                       
-                       slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid);
-                               
-                       /* Try to make the modification atomically by enforcing the
-                          old value in the delete mod. */
-                       smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods, 
-                                        get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_RID), 
-                                        next_rid_string);
-               }
-
-               if (!next_rid) { /* not got one already */
-                       switch (rid_type) {
-                       case USER_RID_TYPE:
-                               if (smbldap_get_single_pstring(state->smbldap_state->ldap_struct, entry,
-                                                        get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID),
-                                                        old_rid_string)) {
-                                       *rid = (uint32)atol(old_rid_string);                                    
-                               }
-                               break;
-                       case GROUP_RID_TYPE:
-                               if (smbldap_get_single_pstring(state->smbldap_state->ldap_struct, entry, 
-                                                        get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
-                                                        old_rid_string)) {
-                                       *rid = (uint32)atol(old_rid_string);
-                               }
-                               break;
-                       }
-                       
-                       /* This is the core of the whole routine. If we had
-                          scheme-style closures, there would be a *lot* less code
-                          duplication... */
-
-                       next_rid = *rid+RID_MULTIPLIER;
-                       slprintf(next_rid_string, sizeof(next_rid_string)-1, "%d", next_rid);
-                       
-                       switch (rid_type) {
-                       case USER_RID_TYPE:
-                               /* Try to make the modification atomically by enforcing the
-                                  old value in the delete mod. */
-                               smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods, 
-                                                get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_USERRID), 
-                                                next_rid_string);
-                               break;
-                               
-                       case GROUP_RID_TYPE:
-                               /* Try to make the modification atomically by enforcing the
-                                  old value in the delete mod. */
-                               smbldap_make_mod(state->smbldap_state->ldap_struct, entry, &mods,
-                                                get_attr_key2string(dominfo_attr_list, LDAP_ATTR_NEXT_GROUPRID),
-                                                next_rid_string);
-                               break;
-                       }
-               }
-
-               if ((smbldap_modify(state->smbldap_state, dn, mods)) == LDAP_SUCCESS) {
-                       DOM_SID dom_sid;
-                       DOM_SID sid;
-                       pstring domain_sid_string;
-                       int error = 0;
-
-                       if (!smbldap_get_single_pstring(state->smbldap_state->ldap_struct, domain_result,
-                                       get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOM_SID),
-                                       domain_sid_string)) {
-                               ldap_mods_free(mods, True);
-                               SAFE_FREE(dn);
-                               ldap_msgfree(domain_result);
-                               return ret;
-                       }
-
-                       if (!string_to_sid(&dom_sid, domain_sid_string)) { 
-                               ldap_mods_free(mods, True);
-                               SAFE_FREE(dn);
-                               ldap_msgfree(domain_result);
-                               return ret;
-                       }
-
-                       ldap_mods_free(mods, True);
-                       mods = NULL;
-                       SAFE_FREE(dn);
-                       ldap_msgfree(domain_result);
-
-                       sid_copy(&sid, &dom_sid);
-                       sid_append_rid(&sid, *rid);
-
-                       /* check RID is not in use */
-                       if (sid_in_use(state, &sid, &error)) {
-                               if (error) {
-                                       return ret;
-                               }
-                               continue;
-                       }
-
-                       return NT_STATUS_OK;
-               }
-
-               ld_error = NULL;
-               ldap_get_option(state->smbldap_state->ldap_struct, LDAP_OPT_ERROR_STRING, &ld_error);
-               DEBUG(2, ("Failed to modify rid: %s\n", ld_error ? ld_error : "(NULL"));
-               SAFE_FREE(ld_error);
-
-               ldap_mods_free(mods, True);
-               mods = NULL;
-
-               SAFE_FREE(dn);
-
-               ldap_msgfree(domain_result);
-               domain_result = NULL;
-
-               {
-                       /* Sleep for a random timeout */
-                       unsigned sleeptime = (sys_random()*sys_getpid()*attempts);
-                       attempts += 1;
-                       
-                       sleeptime %= 100;
-                       smb_msleep(sleeptime);
-               }
-       }
-
-       DEBUG(0, ("Failed to set new RID\n"));
-       return ret;
-}
-
-
-/*****************************************************************************
- Allocate a new RID
-*****************************************************************************/
-
-static NTSTATUS ldap_allocate_rid(uint32 *rid, int rid_type)
-{
-       return ldap_next_rid( &ldap_state, rid, rid_type );
-}
-
 /*****************************************************************************
  Allocate a new uid or gid
 *****************************************************************************/
@@ -394,12 +140,12 @@ static NTSTATUS ldap_allocate_id(unid_t *id, int id_type)
 
        pstr_sprintf(filter, "(objectClass=%s)", LDAP_OBJ_IDPOOL);
 
-       attr_list = get_attr_list( idpool_attr_list );
+       attr_list = get_attr_list( NULL, idpool_attr_list );
 
        rc = smbldap_search(ldap_state.smbldap_state, lp_ldap_idmap_suffix(),
                               LDAP_SCOPE_SUBTREE, filter,
                               attr_list, 0, &result);
-       free_attr_list( attr_list );
+       talloc_free( attr_list );
         
        if (rc != LDAP_SUCCESS) {
                DEBUG(0,("ldap_allocate_id: %s object not found\n", LDAP_OBJ_IDPOOL));
@@ -505,7 +251,7 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
                LDAP_OBJ_IDMAP_ENTRY, type,  
                ((id_type & ID_USERID) ? (unsigned long)id.uid : (unsigned long)id.gid));
                
-       attr_list = get_attr_list( sidmap_attr_list );
+       attr_list = get_attr_list( NULL, sidmap_attr_list );
        rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, 
                filter, attr_list, 0, &result);
 
@@ -534,7 +280,7 @@ static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type)
 
        ret = NT_STATUS_OK;
 out:
-       free_attr_list( attr_list );     
+       talloc_free( attr_list );        
 
        if (result)
                ldap_msgfree(result);
@@ -577,7 +323,7 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si
 
        /* do the search and check for errors */
 
-       attr_list = get_attr_list( sidmap_attr_list );
+       attr_list = get_attr_list( NULL, sidmap_attr_list );
        rc = smbldap_search(ldap_state.smbldap_state, suffix, LDAP_SCOPE_SUBTREE, 
                filter, attr_list, 0, &result);
                        
@@ -651,7 +397,7 @@ static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, const DOM_SID *si
        }
        
 out:
-       free_attr_list( attr_list );
+       talloc_free( attr_list );
        if (result)
                ldap_msgfree(result);
        SAFE_FREE(dn);
@@ -674,10 +420,10 @@ static NTSTATUS verify_idpool( void )
        
        fstr_sprintf( filter, "(objectclass=%s)", LDAP_OBJ_IDPOOL );
        
-       attr_list = get_attr_list( idpool_attr_list );
+       attr_list = get_attr_list( NULL, idpool_attr_list );
        rc = smbldap_search(ldap_state.smbldap_state, lp_ldap_idmap_suffix(), 
                LDAP_SCOPE_SUBTREE, filter, attr_list, 0, &result);
-       free_attr_list ( attr_list );
+       talloc_free ( attr_list );
 
        if (rc != LDAP_SUCCESS)
                return NT_STATUS_UNSUCCESSFUL;
@@ -776,7 +522,6 @@ static void ldap_idmap_status(void)
 
 static struct idmap_methods ldap_methods = {
        ldap_idmap_init,
-       ldap_allocate_rid,
        ldap_allocate_id,
        ldap_get_sid_from_id,
        ldap_get_id_from_sid,
index eced549a55734febae7c8bdb93bcee8a75223231..0922000fa12fc08bbdec439487af501d03fb6d20 100644 (file)
@@ -527,11 +527,6 @@ static NTSTATUS rid_idmap_close(void)
        return NT_STATUS_OK;
 }
 
-static NTSTATUS rid_idmap_allocate_rid(uint32 *rid, int rid_type)
-{
-       return NT_STATUS_NOT_IMPLEMENTED;
-}
-
 static NTSTATUS rid_idmap_allocate_id(unid_t *id, int id_type)
 {
        return NT_STATUS_NOT_IMPLEMENTED;
@@ -544,7 +539,6 @@ static void rid_idmap_status(void)
 
 static struct idmap_methods rid_methods = {
        rid_idmap_init,
-       rid_idmap_allocate_rid,
        rid_idmap_allocate_id,
        rid_idmap_get_sid_from_id,
        rid_idmap_get_id_from_sid,
index b1aae2b86f7875426600764b26182ff5f2555752..4d80364437cb000bb6eabaad28c01d987cdd3f4b 100644 (file)
@@ -86,15 +86,6 @@ static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
        return ret;
 }
 
-/*****************************************************************************
- Allocate a new RID
-*****************************************************************************/
-
-static NTSTATUS ldap_allocate_rid(uint32 *rid, int rid_type)
-{
-       return NT_STATUS_UNSUCCESSFUL;
-}
-
 /*****************************************************************************
  Allocate a new uid or gid
 *****************************************************************************/
@@ -437,7 +428,6 @@ static void ldap_idmap_status(void)
 
 static struct idmap_methods ldap_methods = {
        ldap_idmap_init,
-       ldap_allocate_rid,
        ldap_allocate_id,
        ldap_get_sid_from_id,
        ldap_get_id_from_sid,
index e89a6cf547cf585b36eb06e04ed62b844d20eb24..665c56d2f679523f7d76dbb249f287d5e256908c 100644 (file)
@@ -31,9 +31,6 @@
 #define HWM_GROUP  "GROUP HWM"
 #define HWM_USER   "USER HWM"
 
-/* idmap version determines auto-conversion */
-#define IDMAP_VERSION 2
-
 /* Globals */
 static TDB_CONTEXT *idmap_tdb;
 
@@ -45,41 +42,6 @@ static struct idmap_state {
        gid_t gid_low, gid_high;               /* Range of gids to allocate */
 } idmap_state;
 
-/**********************************************************************
- allocate a new RID; We don't care if is a user or group
-**********************************************************************/
-
-static NTSTATUS db_allocate_rid(uint32 *rid, int rid_type)
-{
-       uint32 lowrid, highrid;
-       uint32 tmp_rid;
-
-       /* can't handle group rids right now.  This is such a mess.... */
-
-       if ( rid_type == GROUP_RID_TYPE )
-               return NT_STATUS_UNSUCCESSFUL;
-       
-       /* cannot fail since idmap is only called winbindd */
-       
-       get_free_rid_range( &lowrid, &highrid );
-       
-       tmp_rid = lowrid;
-       
-       if ( !tdb_change_uint32_atomic(idmap_tdb, "RID_COUNTER", &tmp_rid, RID_MULTIPLIER) ) {
-               DEBUG(3,("db_allocate_rid: Failed to locate next rid record in idmap db\n"));
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-       
-       if ( tmp_rid > highrid ) {
-               DEBUG(0, ("db_allocate_rid: no RIDs available!\n"));
-               return NT_STATUS_UNSUCCESSFUL;
-       }
-       
-       *rid = tmp_rid;
-
-       return NT_STATUS_OK;
-}
-
 /**********************************************************************
  Allocate either a user or group id from the pool 
 **********************************************************************/
@@ -660,7 +622,6 @@ TDB_CONTEXT *idmap_tdb_handle( void )
 static struct idmap_methods db_methods = {
 
        db_idmap_init,
-       db_allocate_rid,
        db_allocate_id,
        db_get_sid_from_id,
        db_get_id_from_sid,
index cac8934f7b65743387af719741863abca356f544..7233cb48cd1ef34fd5a94bc101af3e24634d5b72 100644 (file)
 #undef DBGC_CLASS
 #define DBGC_CLASS DBGC_IDMAP
 
-#if 0  /* NOT USED */
-
-/**********************************************************************
- Get the free RID base if idmap is configured, otherwise return 0
-**********************************************************************/
-
-uint32 idmap_get_free_rid_base(void)
-{
-       uint32 low, high;
-       if (idmap_get_free_rid_range(&low, &high)) {
-               return low;
-       }
-       return 0;
-}
-
-/**********************************************************************
-**********************************************************************/
-
-BOOL idmap_check_ugid_is_in_free_range(uint32 id)
-{
-       uint32 low, high;
-
-       if (!idmap_get_free_ugid_range(&low, &high)) {
-               return False;
-       }
-       if (id < low || id > high) {
-               return False;
-       }
-       return True;
-}
-
-/**********************************************************************
-**********************************************************************/
-
-BOOL idmap_check_rid_is_in_free_range(uint32 rid)
-{
-       uint32 low, high;
-
-       if (!idmap_get_free_rid_range(&low, &high)) {
-               return False;
-       }
-       if (rid < algorithmic_rid_base()) {
-               return True;
-       }
-
-       if (rid < low || rid > high) {
-               return False;
-       }
-
-       return True;
-}
-
-/**********************************************************************
- if it is a foreign SID or if the SID is in the free range, return true
-**********************************************************************/
-
-BOOL idmap_check_sid_is_in_free_range(const DOM_SID *sid)
-{
-       if (sid_compare_domain(get_global_sam_sid(), sid) == 0) {
-       
-               uint32 rid;
-
-               if (sid_peek_rid(sid, &rid)) {
-                       return idmap_check_rid_is_in_free_range(rid);
-               }
-
-               return False;
-       }
-
-       return True;
-}
-
-#endif /* NOT USED */
-
 /*****************************************************************
  Returns SID pointer.
 *****************************************************************/  
index 9235217ff00af3ca1c1f7f33ccde02721db1efc8..3bbca1a8aa5641f03f74f720066c75d8ad8b4423 100755 (executable)
@@ -19,7 +19,8 @@ if test ! -d $SRCDIR../docs/manpages; then
 fi
 
 # Get the configured feature set
-test -f "${SRCDIR}/config.log" && eval `grep '^[A-Za-z0-9]*=.*' ${SRCDIR}/config.log`
+test -f "${SRCDIR}/config.log" && \
+       eval $( grep "^[[:alnum:]]*=.*" "${SRCDIR}/config.log")
 
 for lang in $langs; do
     if [ "X$lang" = XC ]; then
@@ -43,7 +44,7 @@ for lang in $langs; do
     for sect in 1 5 7 8 ; do
        for m in $langdir/man$sect ; do
            for s in $SRCDIR../docs/manpages/$lang/*$sect; do
-           MP_BASENAME=`basename $s`
+           MP_BASENAME=${s##*/}
 
            # Check if this man page if required by the configured feature set
            case "${MP_BASENAME}" in
index c66fd29485d879939f00725740acae9b7faf5eba..c5c285894e7bf5945388d46ee0a9abca70d493ce 100755 (executable)
@@ -3,7 +3,7 @@
 
 SWATDIR=`echo $1 | sed 's/\/\//\//g'`
 SRCDIR=$2/
-BOOKDIR=$SWATDIR/help/using_samba
+BOOKDIR=$SWATDIR/using_samba
 
 echo Installing SWAT in $SWATDIR
 echo Installing the Samba Web Administration Tool
@@ -14,7 +14,7 @@ echo Installing langs are `cd $SRCDIR../swat/lang/; /bin/echo ??`
 for ln in $LANGS; do 
  SWATLANGDIR=$SWATDIR/$ln
  for d in $SWATLANGDIR $SWATLANGDIR/help $SWATLANGDIR/images \
-       $SWATLANGDIR/include; do
+       $SWATLANGDIR/include $SWATLANGDIR/js; do
     if [ ! -d $d ]; then
        mkdir -p $d
        if [ ! -d $d ]; then
@@ -28,7 +28,7 @@ done
 # Install images
 for ln in $LANGS; do
 
-  for f in $SRCDIR../swat/$ln/images/*.gif; do
+  for f in $SRCDIR../swat/$ln/images/*.png; do
       if [ ! -f $f ] ; then
        continue
       fi
@@ -59,7 +59,7 @@ for ln in $LANGS; do
 
   # Install "server-side" includes
 
-  for f in $SRCDIR../swat/$ln/include/*.html; do
+  for f in $SRCDIR../swat/$ln/include/*; do
       if [ ! -f $f ] ; then
        continue
       fi
@@ -69,6 +69,18 @@ for ln in $LANGS; do
       chmod 0644 $FNAME
   done
 
+  # Install javascripts
+
+  for f in $SRCDIR../swat/$ln/js/*.js; do
+      if [ ! -f $f ] ; then
+       continue
+      fi
+      FNAME=$SWATDIR/$ln/js/`basename $f`
+      echo $FNAME
+      cp $f $FNAME || echo Cannot install $FNAME. Does $USER have privileges?
+      chmod 0644 $FNAME
+  done
+
 done
 
 # Install html documentation (if html documentation tree is here)
index bb3051931962103a0f731c35b23a961562ba53de..0798541cb502c3f87c51056c28c0638a10dc7dfc 100644 (file)
@@ -690,7 +690,7 @@ BOOL change_lanman_password(SAM_ACCOUNT *sampass, uchar *pass2)
        }
  
        /* Now flush the sam_passwd struct to persistent storage */
-       ret = pdb_update_sam_account (sampass);
+       ret = NT_STATUS_IS_OK(pdb_update_sam_account (sampass));
 
        return ret;
 }
@@ -828,7 +828,7 @@ static NTSTATUS check_oem_password(const char *user,
                        DEBUG(1, ("LM password change supplied for user %s, but we have disabled LanMan authentication\n", 
                                  user));
                }
-                       pdb_free_sam(&sampass);
+               pdb_free_sam(&sampass);
                return NT_STATUS_WRONG_PASSWORD;
        } else {
                DEBUG(1, ("password change requested for user %s, but no password supplied!\n", 
@@ -1009,7 +1009,6 @@ static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext)
 
 NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passwd, BOOL as_root)
 {
-       BOOL ret;
        uint32 min_len, min_age;
        struct passwd *pass = NULL;
        const char *username = pdb_get_username(hnd);
@@ -1090,11 +1089,5 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw
        }
 
        /* Now write it into the file. */
-       ret = pdb_update_sam_account (hnd);
-
-       if (!ret) {
-               return NT_STATUS_ACCESS_DENIED;
-       }
-       
-       return NT_STATUS_OK;
+       return pdb_update_sam_account (hnd);
 }
index bb000bac30ec86ee39045e3b3410911f51c48f66..bf4db99ea659434fab42f34ea2309d8b07b45155 100644 (file)
@@ -249,7 +249,7 @@ void conn_free_internal(connection_struct *conn)
        }
 
        if (conn->nt_user_token) {
-               delete_nt_token(&(conn->nt_user_token));
+               talloc_free(conn->nt_user_token);
        }
 
        free_namearray(conn->veto_list);
index 4778702e7acd96e96c65bca15eccad297ee10894..83dfdf0d8bca3ced02e3182b4ee06af3fb017534 100644 (file)
@@ -1034,107 +1034,111 @@ static int get_server_info(uint32 servertype,
                           struct srv_info_struct **servers,
                           const char *domain)
 {
-  int count=0;
-  int alloced=0;
-  char **lines;
-  BOOL local_list_only;
-  int i;
+       int count=0;
+       int alloced=0;
+       char **lines;
+       BOOL local_list_only;
+       int i;
 
-  lines = file_lines_load(lock_path(SERVER_LIST), NULL);
-  if (!lines) {
-    DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
-    return(0);
-  }
+       lines = file_lines_load(lock_path(SERVER_LIST), NULL, 0);
+       if (!lines) {
+               DEBUG(4,("Can't open %s - %s\n",lock_path(SERVER_LIST),strerror(errno)));
+               return 0;
+       }
 
-  /* request for everything is code for request all servers */
-  if (servertype == SV_TYPE_ALL) 
-       servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
+       /* request for everything is code for request all servers */
+       if (servertype == SV_TYPE_ALL) {
+               servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
+       }
 
-  local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
+       local_list_only = (servertype & SV_TYPE_LOCAL_LIST_ONLY);
 
-  DEBUG(4,("Servertype search: %8x\n",servertype));
+       DEBUG(4,("Servertype search: %8x\n",servertype));
 
-  for (i=0;lines[i];i++) {
-    fstring stype;
-    struct srv_info_struct *s;
-    const char *ptr = lines[i];
-    BOOL ok = True;
+       for (i=0;lines[i];i++) {
+               fstring stype;
+               struct srv_info_struct *s;
+               const char *ptr = lines[i];
+               BOOL ok = True;
 
-    if (!*ptr) continue;
+               if (!*ptr) {
+                       continue;
+               }
     
-    if (count == alloced) {
-      struct srv_info_struct *ts;
+               if (count == alloced) {
+                       struct srv_info_struct *ts;
       
-      alloced += 10;
-      ts = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
-      if (!ts) {
-       DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
-       return(0);
-      }
-      else *servers = ts;
-      memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
-    }
-    s = &(*servers)[count];
+                       alloced += 10;
+                       ts = SMB_REALLOC_ARRAY(*servers,struct srv_info_struct, alloced);
+                       if (!ts) {
+                               DEBUG(0,("get_server_info: failed to enlarge servers info struct!\n"));
+                               return 0;
+                       } else {
+                               *servers = ts;
+                       }
+                       memset((char *)((*servers)+count),'\0',sizeof(**servers)*(alloced-count));
+               }
+               s = &(*servers)[count];
     
-    if (!next_token(&ptr,s->name   , NULL, sizeof(s->name))) continue;
-    if (!next_token(&ptr,stype     , NULL, sizeof(stype))) continue;
-    if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) continue;
-    if (!next_token(&ptr,s->domain , NULL, sizeof(s->domain))) {
-      /* this allows us to cope with an old nmbd */
-      fstrcpy(s->domain,lp_workgroup()); 
-    }
+               if (!next_token(&ptr,s->name, NULL, sizeof(s->name))) {
+                       continue;
+               }
+               if (!next_token(&ptr,stype, NULL, sizeof(stype))) {
+                       continue;
+               }
+               if (!next_token(&ptr,s->comment, NULL, sizeof(s->comment))) {
+                       continue;
+               }
+               if (!next_token(&ptr,s->domain, NULL, sizeof(s->domain))) {
+                       /* this allows us to cope with an old nmbd */
+                       fstrcpy(s->domain,lp_workgroup()); 
+               }
     
-    if (sscanf(stype,"%X",&s->type) != 1) { 
-      DEBUG(4,("r:host file ")); 
-      ok = False; 
-    }
+               if (sscanf(stype,"%X",&s->type) != 1) { 
+                       DEBUG(4,("r:host file ")); 
+                       ok = False; 
+               }
     
-       /* Filter the servers/domains we return based on what was asked for. */
+               /* Filter the servers/domains we return based on what was asked for. */
 
-       /* Check to see if we are being asked for a local list only. */
-       if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
-         DEBUG(4,("r: local list only"));
-         ok = False;
-       }
+               /* Check to see if we are being asked for a local list only. */
+               if(local_list_only && ((s->type & SV_TYPE_LOCAL_LIST_ONLY) == 0)) {
+                       DEBUG(4,("r: local list only"));
+                       ok = False;
+               }
 
-    /* doesn't match up: don't want it */
-    if (!(servertype & s->type)) { 
-      DEBUG(4,("r:serv type ")); 
-      ok = False; 
-    }
+               /* doesn't match up: don't want it */
+               if (!(servertype & s->type)) { 
+                       DEBUG(4,("r:serv type ")); 
+                       ok = False; 
+               }
     
-    if ((servertype & SV_TYPE_DOMAIN_ENUM) != 
-       (s->type & SV_TYPE_DOMAIN_ENUM))
-      {
-       DEBUG(4,("s: dom mismatch "));
-       ok = False;
-      }
+               if ((servertype & SV_TYPE_DOMAIN_ENUM) != 
+                               (s->type & SV_TYPE_DOMAIN_ENUM)) {
+                       DEBUG(4,("s: dom mismatch "));
+                       ok = False;
+               }
     
-    if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM))
-      {
-       ok = False;
-      }
+               if (!strequal(domain, s->domain) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
+                       ok = False;
+               }
     
-       /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
-       s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
+               /* We should never return a server type with a SV_TYPE_LOCAL_LIST_ONLY set. */
+               s->type &= ~SV_TYPE_LOCAL_LIST_ONLY;
 
-    if (ok)
-      {
-       DEBUG(4,("**SV** %20s %8x %25s %15s\n",
-                s->name, s->type, s->comment, s->domain));
-       
-       s->server_added = True;
-       count++;
-      }
-    else
-      {
-       DEBUG(4,("%20s %8x %25s %15s\n",
-                s->name, s->type, s->comment, s->domain));
-      }
-  }
+               if (ok) {
+                       DEBUG(4,("**SV** %20s %8x %25s %15s\n",
+                               s->name, s->type, s->comment, s->domain));
+                       s->server_added = True;
+                       count++;
+               } else {
+                       DEBUG(4,("%20s %8x %25s %15s\n",
+                               s->name, s->type, s->comment, s->domain));
+               }
+       }
   
-  file_lines_free(lines);
-  return(count);
+       file_lines_free(lines);
+       return count;
 }
 
 /*******************************************************************
@@ -1145,75 +1149,79 @@ static int fill_srv_info(struct srv_info_struct *service,
                         int uLevel, char **buf, int *buflen, 
                         char **stringbuf, int *stringspace, char *baseaddr)
 {
-  int struct_len;
-  char* p;
-  char* p2;
-  int l2;
-  int len;
+       int struct_len;
+       char* p;
+       char* p2;
+       int l2;
+       int len;
  
-  switch (uLevel) {
-  case 0: struct_len = 16; break;
-  case 1: struct_len = 26; break;
-  default: return -1;
-  }  
-  if (!buf)
-    {
-      len = 0;
-      switch (uLevel) 
-       {
-       case 1:
-         len = strlen(service->comment)+1;
-         break;
+       switch (uLevel) {
+               case 0:
+                       struct_len = 16;
+                       break;
+               case 1:
+                       struct_len = 26;
+                       break;
+               default:
+                       return -1;
        }
+       if (!buf) {
+               len = 0;
+               switch (uLevel) {
+                       case 1:
+                               len = strlen(service->comment)+1;
+                               break;
+               }
 
-      if (buflen) *buflen = struct_len;
-      if (stringspace) *stringspace = len;
-      return struct_len + len;
-    }
+               if (buflen) {
+                       *buflen = struct_len;
+               }
+               if (stringspace) {
+                       *stringspace = len;
+               }
+               return struct_len + len;
+       }
   
-  len = struct_len;
-  p = *buf;
-  if (*buflen < struct_len) return -1;
-  if (stringbuf)
-    {
-      p2 = *stringbuf;
-      l2 = *stringspace;
-    }
-  else
-    {
-      p2 = p + struct_len;
-      l2 = *buflen - struct_len;
-    }
-  if (!baseaddr) baseaddr = p;
+       len = struct_len;
+       p = *buf;
+       if (*buflen < struct_len) {
+               return -1;
+       }
+       if (stringbuf) {
+               p2 = *stringbuf;
+               l2 = *stringspace;
+       } else {
+               p2 = p + struct_len;
+               l2 = *buflen - struct_len;
+       }
+       if (!baseaddr) {
+               baseaddr = p;
+       }
   
-  switch (uLevel)
-    {
-    case 0:
-           push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
-           break;
-
-    case 1:
-           push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
-           SIVAL(p,18,service->type);
-           SIVAL(p,22,PTR_DIFF(p2,baseaddr));
-           len += CopyAndAdvance(&p2,service->comment,&l2);
-           break;
-    }
-
-  if (stringbuf)
-    {
-      *buf = p + struct_len;
-      *buflen -= struct_len;
-      *stringbuf = p2;
-      *stringspace = l2;
-    }
-  else
-    {
-      *buf = p2;
-      *buflen -= len;
-    }
-  return len;
+       switch (uLevel) {
+               case 0:
+                       push_ascii(p,service->name, MAX_NETBIOSNAME_LEN, STR_TERMINATE);
+                       break;
+
+               case 1:
+                       push_ascii(p,service->name,MAX_NETBIOSNAME_LEN, STR_TERMINATE);
+                       SIVAL(p,18,service->type);
+                       SIVAL(p,22,PTR_DIFF(p2,baseaddr));
+                       len += CopyAndAdvance(&p2,service->comment,&l2);
+                       break;
+       }
+
+       if (stringbuf) {
+               *buf = p + struct_len;
+               *buflen -= struct_len;
+               *stringbuf = p2;
+               *stringspace = l2;
+       } else {
+               *buf = p2;
+               *buflen -= len;
+       }
+       return len;
 }
 
 
@@ -1231,124 +1239,137 @@ static BOOL api_RNetServerEnum(connection_struct *conn, uint16 vuid, char *param
                               int mdrcnt, int mprcnt, char **rdata, 
                               char **rparam, int *rdata_len, int *rparam_len)
 {
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *p = skip_string(str2,1);
-  int uLevel = SVAL(p,0);
-  int buf_len = SVAL(p,2);
-  uint32 servertype = IVAL(p,4);
-  char *p2;
-  int data_len, fixed_len, string_len;
-  int f_len = 0, s_len = 0;
-  struct srv_info_struct *servers=NULL;
-  int counted=0,total=0;
-  int i,missed;
-  fstring domain;
-  BOOL domain_request;
-  BOOL local_request;
-
-  /* If someone sets all the bits they don't really mean to set
-     DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
-     known servers. */
-
-  if (servertype == SV_TYPE_ALL) 
-    servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
-
-  /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
-     any other bit (they may just set this bit on it's own) they 
-     want all the locally seen servers. However this bit can be 
-     set on its own so set the requested servers to be 
-     ALL - DOMAIN_ENUM. */
-
-  if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) 
-    servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
-
-  domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
-  local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
-
-  p += 8;
-
-  if (!prefix_ok(str1,"WrLehD")) return False;
-  if (!check_server_info(uLevel,str2)) return False;
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *p = skip_string(str2,1);
+       int uLevel = SVAL(p,0);
+       int buf_len = SVAL(p,2);
+       uint32 servertype = IVAL(p,4);
+       char *p2;
+       int data_len, fixed_len, string_len;
+       int f_len = 0, s_len = 0;
+       struct srv_info_struct *servers=NULL;
+       int counted=0,total=0;
+       int i,missed;
+       fstring domain;
+       BOOL domain_request;
+       BOOL local_request;
+
+       /* If someone sets all the bits they don't really mean to set
+          DOMAIN_ENUM and LOCAL_LIST_ONLY, they just want all the
+          known servers. */
+
+       if (servertype == SV_TYPE_ALL) {
+               servertype &= ~(SV_TYPE_DOMAIN_ENUM|SV_TYPE_LOCAL_LIST_ONLY);
+       }
+
+       /* If someone sets SV_TYPE_LOCAL_LIST_ONLY but hasn't set
+          any other bit (they may just set this bit on it's own) they 
+          want all the locally seen servers. However this bit can be 
+          set on its own so set the requested servers to be 
+          ALL - DOMAIN_ENUM. */
+
+       if ((servertype & SV_TYPE_LOCAL_LIST_ONLY) && !(servertype & SV_TYPE_DOMAIN_ENUM)) {
+               servertype = SV_TYPE_ALL & ~(SV_TYPE_DOMAIN_ENUM);
+       }
+
+       domain_request = ((servertype & SV_TYPE_DOMAIN_ENUM) != 0);
+       local_request = ((servertype & SV_TYPE_LOCAL_LIST_ONLY) != 0);
+
+       p += 8;
+
+       if (!prefix_ok(str1,"WrLehD")) {
+               return False;
+       }
+       if (!check_server_info(uLevel,str2)) {
+               return False;
+       }
   
-  DEBUG(4, ("server request level: %s %8x ", str2, servertype));
-  DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
-  DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
-
-  if (strcmp(str1, "WrLehDz") == 0) {
-         pull_ascii_fstring(domain, p);
-  } else {
-         fstrcpy(domain, lp_workgroup());
-  }
-
-  if (lp_browse_list())
-    total = get_server_info(servertype,&servers,domain);
-
-  data_len = fixed_len = string_len = 0;
-  missed = 0;
-
-  if (total > 0)
-    qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
-
-  {
-    char *lastname=NULL;
-
-    for (i=0;i<total;i++)
-    {
-      struct srv_info_struct *s = &servers[i];
-      if (lastname && strequal(lastname,s->name)) continue;
-      lastname = s->name;
-      data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
-      DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
-              s->name, s->type, s->comment, s->domain));
+       DEBUG(4, ("server request level: %s %8x ", str2, servertype));
+       DEBUG(4, ("domains_req:%s ", BOOLSTR(domain_request)));
+       DEBUG(4, ("local_only:%s\n", BOOLSTR(local_request)));
+
+       if (strcmp(str1, "WrLehDz") == 0) {
+               pull_ascii_fstring(domain, p);
+       } else {
+               fstrcpy(domain, lp_workgroup());
+       }
+
+       if (lp_browse_list()) {
+               total = get_server_info(servertype,&servers,domain);
+       }
+
+       data_len = fixed_len = string_len = 0;
+       missed = 0;
+
+       if (total > 0) {
+               qsort(servers,total,sizeof(servers[0]),QSORT_CAST srv_comp);
+       }
+
+       {
+               char *lastname=NULL;
+
+               for (i=0;i<total;i++) {
+                       struct srv_info_struct *s = &servers[i];
+
+                       if (lastname && strequal(lastname,s->name)) {
+                               continue;
+                       }
+                       lastname = s->name;
+                       data_len += fill_srv_info(s,uLevel,0,&f_len,0,&s_len,0);
+                       DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
+                               s->name, s->type, s->comment, s->domain));
       
-      if (data_len <= buf_len) {
-         counted++;
-         fixed_len += f_len;
-         string_len += s_len;
-      } else {
-       missed++;
-      }
-    }
-  }
-
-  *rdata_len = fixed_len + string_len;
-  *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
-  memset(*rdata,'\0',*rdata_len);
+                       if (data_len <= buf_len) {
+                               counted++;
+                               fixed_len += f_len;
+                               string_len += s_len;
+                       } else {
+                               missed++;
+                       }
+               }
+       }
+
+       *rdata_len = fixed_len + string_len;
+       *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       memset(*rdata,'\0',*rdata_len);
   
-  p2 = (*rdata) + fixed_len;   /* auxilliary data (strings) will go here */
-  p = *rdata;
-  f_len = fixed_len;
-  s_len = string_len;
-
-  {
-    char *lastname=NULL;
-    int count2 = counted;
-    for (i = 0; i < total && count2;i++)
-      {
-       struct srv_info_struct *s = &servers[i];
-       if (lastname && strequal(lastname,s->name)) continue;
-       lastname = s->name;
-       fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
-       DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
-                s->name, s->type, s->comment, s->domain));
-       count2--;
-      }
-  }
+       p2 = (*rdata) + fixed_len;      /* auxilliary data (strings) will go here */
+       p = *rdata;
+       f_len = fixed_len;
+       s_len = string_len;
+
+       {
+               char *lastname=NULL;
+               int count2 = counted;
+
+               for (i = 0; i < total && count2;i++) {
+                       struct srv_info_struct *s = &servers[i];
+
+                       if (lastname && strequal(lastname,s->name)) {
+                               continue;
+                       }
+                       lastname = s->name;
+                       fill_srv_info(s,uLevel,&p,&f_len,&p2,&s_len,*rdata);
+                       DEBUG(4,("fill_srv_info %20s %8x %25s %15s\n",
+                               s->name, s->type, s->comment, s->domain));
+                       count2--;
+               }
+       }
   
-  *rparam_len = 8;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-  SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
-  SSVAL(*rparam,2,0);
-  SSVAL(*rparam,4,counted);
-  SSVAL(*rparam,6,counted+missed);
+       *rparam_len = 8;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       SSVAL(*rparam,0,(missed == 0 ? NERR_Success : ERRmoredata));
+       SSVAL(*rparam,2,0);
+       SSVAL(*rparam,4,counted);
+       SSVAL(*rparam,6,counted+missed);
 
-  SAFE_FREE(servers);
+       SAFE_FREE(servers);
 
-  DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
-          domain,uLevel,counted,counted+missed));
+       DEBUG(3,("NetServerEnum domain = %s uLevel=%d counted=%d total=%d\n",
+               domain,uLevel,counted,counted+missed));
 
-  return(True);
+       return True;
 }
 
 /****************************************************************************
@@ -1359,30 +1380,32 @@ static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *pa
                               int mdrcnt, int mprcnt, char **rdata, 
                               char **rparam, int *rdata_len, int *rparam_len)
 {
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *p = skip_string(str2,1);
-  int uLevel = SVAL(p,0);
-  int buf_len = SVAL(p,2);
-  int counted=0;
-  int missed=0;
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *p = skip_string(str2,1);
+       int uLevel = SVAL(p,0);
+       int buf_len = SVAL(p,2);
+       int counted=0;
+       int missed=0;
 
        DEBUG(5,("RNetGroupGetUsers: %s %s %s %d %d\n",
                str1, str2, p, uLevel, buf_len));
 
-  if (!prefix_ok(str1,"zWrLeh")) return False;
+       if (!prefix_ok(str1,"zWrLeh")) {
+               return False;
+       }
   
-  *rdata_len = 0;
+       *rdata_len = 0;
   
-  *rparam_len = 8;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rparam_len = 8;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
 
-  SSVAL(*rparam,0,0x08AC); /* informational warning message */
-  SSVAL(*rparam,2,0);
-  SSVAL(*rparam,4,counted);
-  SSVAL(*rparam,6,counted+missed);
+       SSVAL(*rparam,0,0x08AC); /* informational warning message */
+       SSVAL(*rparam,2,0);
+       SSVAL(*rparam,4,counted);
+       SSVAL(*rparam,6,counted+missed);
 
-  return(True);
+       return True;
 }
 
 /****************************************************************************
@@ -1391,117 +1414,146 @@ static BOOL api_RNetGroupGetUsers(connection_struct *conn, uint16 vuid, char *pa
 
 static BOOL check_share_info(int uLevel, char* id)
 {
-  switch( uLevel ) {
-  case 0:
-    if (strcmp(id,"B13") != 0) return False;
-    break;
-  case 1:
-    if (strcmp(id,"B13BWz") != 0) return False;
-    break;
-  case 2:
-    if (strcmp(id,"B13BWzWWWzB9B") != 0) return False;
-    break;
-  case 91:
-    if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) return False;
-    break;
-  default: return False;
-  }
-  return True;
+       switch( uLevel ) {
+               case 0:
+                       if (strcmp(id,"B13") != 0) {
+                               return False;
+                       }
+                       break;
+               case 1:
+                       if (strcmp(id,"B13BWz") != 0) {
+                               return False;
+                       }
+                       break;
+               case 2:
+                       if (strcmp(id,"B13BWzWWWzB9B") != 0) {
+                               return False;
+                       }
+                       break;
+               case 91:
+                       if (strcmp(id,"B13BWzWWWzB9BB9BWzWWzWW") != 0) {
+                               return False;
+                       }
+                       break;
+               default:
+                       return False;
+       }
+       return True;
 }
 
 static int fill_share_info(connection_struct *conn, int snum, int uLevel,
                           char** buf, int* buflen,
                           char** stringbuf, int* stringspace, char* baseaddr)
 {
-  int struct_len;
-  char* p;
-  char* p2;
-  int l2;
-  int len;
+       int struct_len;
+       char* p;
+       char* p2;
+       int l2;
+       int len;
  
-  switch( uLevel ) {
-  case 0: struct_len = 13; break;
-  case 1: struct_len = 20; break;
-  case 2: struct_len = 40; break;
-  case 91: struct_len = 68; break;
-  default: return -1;
-  }
+       switch( uLevel ) {
+               case 0:
+                       struct_len = 13;
+                       break;
+               case 1:
+                       struct_len = 20;
+                       break;
+               case 2:
+                       struct_len = 40;
+                       break;
+               case 91:
+                       struct_len = 68;
+                       break;
+               default:
+                       return -1;
+       }
   
  
-  if (!buf)
-    {
-      len = 0;
-      if (uLevel > 0) len += StrlenExpanded(conn,snum,lp_comment(snum));
-      if (uLevel > 1) len += strlen(lp_pathname(snum)) + 1;
-      if (buflen) *buflen = struct_len;
-      if (stringspace) *stringspace = len;
-      return struct_len + len;
-    }
+       if (!buf) {
+               len = 0;
+
+               if (uLevel > 0) {
+                       len += StrlenExpanded(conn,snum,lp_comment(snum));
+               }
+               if (uLevel > 1) {
+                       len += strlen(lp_pathname(snum)) + 1;
+               }
+               if (buflen) {
+                       *buflen = struct_len;
+               }
+               if (stringspace) {
+                       *stringspace = len;
+               }
+               return struct_len + len;
+       }
   
-  len = struct_len;
-  p = *buf;
-  if ((*buflen) < struct_len) return -1;
-  if (stringbuf)
-    {
-      p2 = *stringbuf;
-      l2 = *stringspace;
-    }
-  else
-    {
-      p2 = p + struct_len;
-      l2 = (*buflen) - struct_len;
-    }
-  if (!baseaddr) baseaddr = p;
+       len = struct_len;
+       p = *buf;
+       if ((*buflen) < struct_len) {
+               return -1;
+       }
+
+       if (stringbuf) {
+               p2 = *stringbuf;
+               l2 = *stringspace;
+       } else {
+               p2 = p + struct_len;
+               l2 = (*buflen) - struct_len;
+       }
+
+       if (!baseaddr) {
+               baseaddr = p;
+       }
   
-  push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
+       push_ascii(p,lp_servicename(snum),13, STR_TERMINATE);
   
-  if (uLevel > 0)
-    {
-      int type;
-      SCVAL(p,13,0);
-      type = STYPE_DISKTREE;
-      if (lp_print_ok(snum)) type = STYPE_PRINTQ;
-      if (strequal("IPC",lp_fstype(snum))) type = STYPE_IPC;
-      SSVAL(p,14,type);                /* device type */
-      SIVAL(p,16,PTR_DIFF(p2,baseaddr));
-      len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
-    }
+       if (uLevel > 0) {
+               int type;
+
+               SCVAL(p,13,0);
+               type = STYPE_DISKTREE;
+               if (lp_print_ok(snum)) {
+                       type = STYPE_PRINTQ;
+               }
+               if (strequal("IPC",lp_fstype(snum))) {
+                       type = STYPE_IPC;
+               }
+               SSVAL(p,14,type);               /* device type */
+               SIVAL(p,16,PTR_DIFF(p2,baseaddr));
+               len += CopyExpanded(conn,snum,&p2,lp_comment(snum),&l2);
+       }
   
-  if (uLevel > 1)
-    {
-      SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
-      SSVALS(p,22,-1);         /* max uses */
-      SSVAL(p,24,1); /* current uses */
-      SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
-      len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
-      memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
-    }
+       if (uLevel > 1) {
+               SSVAL(p,20,ACCESS_READ|ACCESS_WRITE|ACCESS_CREATE); /* permissions */
+               SSVALS(p,22,-1);                /* max uses */
+               SSVAL(p,24,1); /* current uses */
+               SIVAL(p,26,PTR_DIFF(p2,baseaddr)); /* local pathname */
+               len += CopyAndAdvance(&p2,lp_pathname(snum),&l2);
+               memset(p+30,0,SHPWLEN+2); /* passwd (reserved), pad field */
+       }
   
-  if (uLevel > 2)
-    {
-      memset(p+40,0,SHPWLEN+2);
-      SSVAL(p,50,0);
-      SIVAL(p,52,0);
-      SSVAL(p,56,0);
-      SSVAL(p,58,0);
-      SIVAL(p,60,0);
-      SSVAL(p,64,0);
-      SSVAL(p,66,0);
-    }
+       if (uLevel > 2) {
+               memset(p+40,0,SHPWLEN+2);
+               SSVAL(p,50,0);
+               SIVAL(p,52,0);
+               SSVAL(p,56,0);
+               SSVAL(p,58,0);
+               SIVAL(p,60,0);
+               SSVAL(p,64,0);
+               SSVAL(p,66,0);
+       }
        
-  if (stringbuf)
-    {
-      (*buf) = p + struct_len;
-      (*buflen) -= struct_len;
-      (*stringbuf) = p2;
-      (*stringspace) = l2;
-    }
-  else
-    {
-      (*buf) = p2;
-      (*buflen) -= len;
-    }
-  return len;
+       if (stringbuf) {
+               (*buf) = p + struct_len;
+               (*buflen) -= struct_len;
+               (*stringbuf) = p2;
+               (*stringspace) = l2;
+       } else {
+               (*buf) = p2;
+               (*buflen) -= len;
+       }
+
+       return len;
 }
 
 static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
@@ -1509,31 +1561,39 @@ static BOOL api_RNetShareGetInfo(connection_struct *conn,uint16 vuid, char *para
                                 char **rdata,char **rparam,
                                 int *rdata_len,int *rparam_len)
 {
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *netname = skip_string(str2,1);
-  char *p = skip_string(netname,1);
-  int uLevel = SVAL(p,0);
-  int snum = find_service(netname);
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *netname = skip_string(str2,1);
+       char *p = skip_string(netname,1);
+       int uLevel = SVAL(p,0);
+       int snum = find_service(netname);
   
-  if (snum < 0) return False;
+       if (snum < 0) {
+               return False;
+       }
   
-  /* check it's a supported varient */
-  if (!prefix_ok(str1,"zWrLh")) return False;
-  if (!check_share_info(uLevel,str2)) return False;
+       /* check it's a supported varient */
+       if (!prefix_ok(str1,"zWrLh")) {
+               return False;
+       }
+       if (!check_share_info(uLevel,str2)) {
+               return False;
+       }
  
-  *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
-  p = *rdata;
-  *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
-  if (*rdata_len < 0) return False;
+       *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+       p = *rdata;
+       *rdata_len = fill_share_info(conn,snum,uLevel,&p,&mdrcnt,0,0,0);
+       if (*rdata_len < 0) {
+               return False;
+       }
  
-  *rparam_len = 6;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-  SSVAL(*rparam,0,NERR_Success);
-  SSVAL(*rparam,2,0);          /* converter word */
-  SSVAL(*rparam,4,*rdata_len);
+       *rparam_len = 6;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       SSVAL(*rparam,0,NERR_Success);
+       SSVAL(*rparam,2,0);             /* converter word */
+       SSVAL(*rparam,4,*rdata_len);
  
-  return(True);
+       return True;
 }
 
 /****************************************************************************
@@ -1557,78 +1617,87 @@ static BOOL api_RNetShareEnum( connection_struct *conn,
                                int               *rdata_len,
                                int               *rparam_len )
 {
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *p = skip_string(str2,1);
-  int uLevel = SVAL(p,0);
-  int buf_len = SVAL(p,2);
-  char *p2;
-  int count=lp_numservices();
-  int total=0,counted=0;
-  BOOL missed = False;
-  int i;
-  int data_len, fixed_len, string_len;
-  int f_len = 0, s_len = 0;
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *p = skip_string(str2,1);
+       int uLevel = SVAL(p,0);
+       int buf_len = SVAL(p,2);
+       char *p2;
+       int count = 0;
+       int total=0,counted=0;
+       BOOL missed = False;
+       int i;
+       int data_len, fixed_len, string_len;
+       int f_len = 0, s_len = 0;
  
-  if (!prefix_ok(str1,"WrLeh")) return False;
-  if (!check_share_info(uLevel,str2)) return False;
+       if (!prefix_ok(str1,"WrLeh")) {
+               return False;
+       }
+       if (!check_share_info(uLevel,str2)) {
+               return False;
+       }
   
-  data_len = fixed_len = string_len = 0;
-  for (i=0;i<count;i++) {
-    fstring servicename_dos;
-    if (!(lp_browseable(i) && lp_snum_ok(i)))
-           continue;
-    push_ascii_fstring(servicename_dos, lp_servicename(i));
-    if( lp_browseable( i )
-        && lp_snum_ok( i )
-        && (strlen(servicename_dos) < 13) )   /* Maximum name length. */
-    {
-      total++;
-      data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
-      if (data_len <= buf_len)
-      {
-        counted++;
-        fixed_len += f_len;
-        string_len += s_len;
-      }
-      else
-        missed = True;
-    }
-  }
-  *rdata_len = fixed_len + string_len;
-  *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
-  memset(*rdata,0,*rdata_len);
+       /* Ensure all the usershares are loaded. */
+       become_root();
+       count = load_usershare_shares();
+       unbecome_root();
+
+       data_len = fixed_len = string_len = 0;
+       for (i=0;i<count;i++) {
+               fstring servicename_dos;
+               if (!(lp_browseable(i) && lp_snum_ok(i))) {
+                       continue;
+               }
+               push_ascii_fstring(servicename_dos, lp_servicename(i));
+               /* Maximum name length = 13. */
+               if( lp_browseable( i ) && lp_snum_ok( i ) && (strlen(servicename_dos) < 13)) {
+                       total++;
+                       data_len += fill_share_info(conn,i,uLevel,0,&f_len,0,&s_len,0);
+                       if (data_len <= buf_len) {
+                               counted++;
+                               fixed_len += f_len;
+                               string_len += s_len;
+                       } else {
+                               missed = True;
+                       }
+               }
+       }
+
+       *rdata_len = fixed_len + string_len;
+       *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       memset(*rdata,0,*rdata_len);
   
-  p2 = (*rdata) + fixed_len;   /* auxiliary data (strings) will go here */
-  p = *rdata;
-  f_len = fixed_len;
-  s_len = string_len;
-  for( i = 0; i < count; i++ )
-    {
-    fstring servicename_dos;
-    if (!(lp_browseable(i) && lp_snum_ok(i)))
-           continue;
-    push_ascii_fstring(servicename_dos, lp_servicename(i));
-    if( lp_browseable( i )
-        && lp_snum_ok( i )
-        && (strlen(servicename_dos) < 13) )
-      {
-      if( fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0 )
-       break;
-      }
-    }
+       p2 = (*rdata) + fixed_len;      /* auxiliary data (strings) will go here */
+       p = *rdata;
+       f_len = fixed_len;
+       s_len = string_len;
+
+       for( i = 0; i < count; i++ ) {
+               fstring servicename_dos;
+               if (!(lp_browseable(i) && lp_snum_ok(i))) {
+                       continue;
+               }
+
+               push_ascii_fstring(servicename_dos, lp_servicename(i));
+               if (lp_browseable(i) && lp_snum_ok(i) && (strlen(servicename_dos) < 13)) {
+                       if (fill_share_info( conn,i,uLevel,&p,&f_len,&p2,&s_len,*rdata ) < 0) {
+                               break;
+                       }
+               }
+       }
   
-  *rparam_len = 8;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-  SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
-  SSVAL(*rparam,2,0);
-  SSVAL(*rparam,4,counted);
-  SSVAL(*rparam,6,total);
+       *rparam_len = 8;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       SSVAL(*rparam,0,missed ? ERRmoredata : NERR_Success);
+       SSVAL(*rparam,2,0);
+       SSVAL(*rparam,4,counted);
+       SSVAL(*rparam,6,total);
   
-  DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
-          counted,total,uLevel,
-          buf_len,*rdata_len,mdrcnt));
-  return(True);
+       DEBUG(3,("RNetShareEnum gave %d entries of %d (%d %d %d %d)\n",
+               counted,total,uLevel,
+               buf_len,*rdata_len,mdrcnt));
+
+       return True;
 }
 
 /****************************************************************************
@@ -1640,122 +1709,142 @@ static BOOL api_RNetShareAdd(connection_struct *conn,uint16 vuid, char *param,ch
                                 char **rdata,char **rparam,
                                 int *rdata_len,int *rparam_len)
 {
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *p = skip_string(str2,1);
-  int uLevel = SVAL(p,0);
-  fstring sharename;
-  fstring comment;
-  pstring pathname;
-  char *command, *cmdname;
-  unsigned int offset;
-  int snum;
-  int res = ERRunsup;
-  
-  /* check it's a supported varient */
-  if (!prefix_ok(str1,RAP_WShareAdd_REQ)) return False;
-  if (!check_share_info(uLevel,str2)) return False;
-  if (uLevel != 2) return False;
-
-  pull_ascii_fstring(sharename,data);
-  snum = find_service(sharename);
-  if (snum >= 0) { /* already exists */
-    res = ERRfilexists;
-    goto error_exit;
-  }
-
-  /* only support disk share adds */
-  if (SVAL(data,14)!=STYPE_DISKTREE) return False;
-
-  offset = IVAL(data, 16);
-  if (offset >= mdrcnt) {
-    res = ERRinvalidparam;
-    goto error_exit;
-  }
-  pull_ascii_fstring(comment, offset? (data+offset) : "");
-
-  offset = IVAL(data, 26);
-  if (offset >= mdrcnt) {
-    res = ERRinvalidparam;
-    goto error_exit;
-  }
-  pull_ascii_pstring(pathname, offset? (data+offset) : "");
-
-  string_replace(sharename, '"', ' ');
-  string_replace(pathname, '"', ' ');
-  string_replace(comment, '"', ' ');
-
-  cmdname = lp_add_share_cmd();
-
-  if (!cmdname || *cmdname == '\0') return False;
-
-  asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
-          lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
-
-  if (command) {
-    DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
-    if ((res = smbrun(command, NULL)) != 0) {
-      DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
-      SAFE_FREE(command);
-      res = ERRnoaccess;
-      goto error_exit;
-    } else {
-      SAFE_FREE(command);
-      message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
-    }
-  } else return False;
-
-  *rparam_len = 6;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-  SSVAL(*rparam,0,NERR_Success);
-  SSVAL(*rparam,2,0);          /* converter word */
-  SSVAL(*rparam,4,*rdata_len);
-  *rdata_len = 0;
-  
-  return True;
-
- error_exit:
-  *rparam_len = 4;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-  *rdata_len = 0;
-  SSVAL(*rparam,0,res);
-  SSVAL(*rparam,2,0);
-  return True;
-}
-
-/****************************************************************************
-  view list of groups available
-  ****************************************************************************/
-
-static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
-                             int mdrcnt,int mprcnt,
-                             char **rdata,char **rparam,
-                             int *rdata_len,int *rparam_len)
-{
-       int i;
-       int errflags=0;
-       int resume_context, cli_buf_size;
        char *str1 = param+2;
        char *str2 = skip_string(str1,1);
        char *p = skip_string(str2,1);
+       int uLevel = SVAL(p,0);
+       fstring sharename;
+       fstring comment;
+       pstring pathname;
+       char *command, *cmdname;
+       unsigned int offset;
+       int snum;
+       int res = ERRunsup;
+  
+       /* check it's a supported varient */
+       if (!prefix_ok(str1,RAP_WShareAdd_REQ)) {
+               return False;
+       }
+       if (!check_share_info(uLevel,str2)) {
+               return False;
+       }
+       if (uLevel != 2) {
+               return False;
+       }
 
-       struct pdb_search *search;
-       struct samr_displayentry *entries;
+       pull_ascii_fstring(sharename,data);
+       snum = find_service(sharename);
+       if (snum >= 0) { /* already exists */
+               res = ERRfilexists;
+               goto error_exit;
+       }
 
-       int num_entries;
-       if (strcmp(str1,"WrLeh") != 0)
+       /* only support disk share adds */
+       if (SVAL(data,14)!=STYPE_DISKTREE) {
                return False;
+       }
 
-         /* parameters  
-          * W-> resume context (number of users to skip)
-          * r -> return parameter pointer to receive buffer 
-          * L -> length of receive buffer
-          * e -> return parameter number of entries
-          * h -> return parameter total number of users
-          */
-       if (strcmp("B21",str2) != 0)
-               return False;
+       offset = IVAL(data, 16);
+       if (offset >= mdrcnt) {
+               res = ERRinvalidparam;
+               goto error_exit;
+       }
+
+       pull_ascii_fstring(comment, offset? (data+offset) : "");
+
+       offset = IVAL(data, 26);
+
+       if (offset >= mdrcnt) {
+               res = ERRinvalidparam;
+               goto error_exit;
+       }
+
+       pull_ascii_pstring(pathname, offset? (data+offset) : "");
+
+       string_replace(sharename, '"', ' ');
+       string_replace(pathname, '"', ' ');
+       string_replace(comment, '"', ' ');
+
+       cmdname = lp_add_share_cmd();
+
+       if (!cmdname || *cmdname == '\0') {
+               return False;
+       }
+
+       asprintf(&command, "%s \"%s\" \"%s\" \"%s\" \"%s\"",
+               lp_add_share_cmd(), dyn_CONFIGFILE, sharename, pathname, comment);
+
+       if (command) {
+               DEBUG(10,("api_RNetShareAdd: Running [%s]\n", command ));
+
+               if ((res = smbrun(command, NULL)) != 0) {
+                       DEBUG(1,("api_RNetShareAdd: Running [%s] returned (%d)\n", command, res ));
+                       SAFE_FREE(command);
+                       res = ERRnoaccess;
+                       goto error_exit;
+               } else {
+                       SAFE_FREE(command);
+                       message_send_all(conn_tdb_ctx(), MSG_SMB_CONF_UPDATED, NULL, 0, False, NULL);
+               }
+       } else {
+               return False;
+       }
+
+       *rparam_len = 6;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       SSVAL(*rparam,0,NERR_Success);
+       SSVAL(*rparam,2,0);             /* converter word */
+       SSVAL(*rparam,4,*rdata_len);
+       *rdata_len = 0;
+  
+       return True;
+
+  error_exit:
+
+       *rparam_len = 4;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       *rdata_len = 0;
+       SSVAL(*rparam,0,res);
+       SSVAL(*rparam,2,0);
+       return True;
+}
+
+/****************************************************************************
+  view list of groups available
+  ****************************************************************************/
+
+static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
+                             int mdrcnt,int mprcnt,
+                             char **rdata,char **rparam,
+                             int *rdata_len,int *rparam_len)
+{
+       int i;
+       int errflags=0;
+       int resume_context, cli_buf_size;
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *p = skip_string(str2,1);
+
+       struct pdb_search *search;
+       struct samr_displayentry *entries;
+
+       int num_entries;
+       if (strcmp(str1,"WrLeh") != 0) {
+               return False;
+       }
+
+       /* parameters  
+        * W-> resume context (number of users to skip)
+        * r -> return parameter pointer to receive buffer 
+        * L -> length of receive buffer
+        * e -> return parameter number of entries
+        * h -> return parameter total number of users
+        */
+
+       if (strcmp("B21",str2) != 0) {
+               return False;
+       }
 
        /* get list of domain groups SID_DOMAIN_GRP=2 */
        become_root();
@@ -1837,8 +1926,10 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para
        gid_t *gids;
        size_t num_groups;
        size_t i;
-       struct passwd *passwd;
        NTSTATUS result;
+       DOM_SID user_sid;
+       enum SID_NAME_USE type;
+       TALLOC_CTX *mem_ctx;
 
        *rparam_len = 8;
        *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
@@ -1867,45 +1958,64 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para
 
        p = *rdata;
 
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
+               return False;
+       }
+
        /* Lookup the user information; This should only be one of 
           our accounts (not remote domains) */
 
-       passwd = getpwnam_alloc(UserName);
-
-       if (passwd == NULL)
-               return False;
-          
-       pdb_init_sam( &sampw );
-       
        become_root();                                  /* ROOT BLOCK */
 
-       if ( !pdb_getsampwnam(sampw, UserName) )
-               goto out;
+       if (!lookup_name(mem_ctx, UserName, LOOKUP_NAME_ALL,
+                        NULL, NULL, &user_sid, &type)) {
+               DEBUG(10, ("lookup_name(%s) failed\n", UserName));
+               goto done;
+       }
+
+       if (type != SID_NAME_USER) {
+               DEBUG(10, ("%s is a %s, not a user\n", UserName,
+                          sid_type_lookup(type)));
+               goto done;
+       }
+
+       if (!NT_STATUS_IS_OK(pdb_init_sam_talloc(mem_ctx, &sampw))) {
+               DEBUG(10, ("pdb_init_sam_talloc failed\n"));
+               goto done;
+       }
+
+       if ( !pdb_getsampwsid(sampw, &user_sid) ) {
+               DEBUG(10, ("pdb_getsampwsid(%s) failed for user %s\n",
+                          sid_string_static(&user_sid), UserName));
+               goto done;
+       }
 
+       gids = NULL;
        sids = NULL;
        num_groups = 0;
 
-       result = pdb_enum_group_memberships(pdb_get_username(sampw),
-                                           passwd->pw_gid,
+       result = pdb_enum_group_memberships(mem_ctx, sampw,
                                            &sids, &gids, &num_groups);
 
-       if (!NT_STATUS_IS_OK(result))
-               goto out;
+       if (!NT_STATUS_IS_OK(result)) {
+               DEBUG(10, ("pdb_enum_group_memberships failed for %s\n",
+                          UserName));
+               goto done;
+       }
 
        for (i=0; i<num_groups; i++) {
 
                const char *grp_name;
        
-               if ( lookup_sid(sampw->mem_ctx, &sids[i], NULL, &grp_name,
-                               NULL) ) {
+               if ( lookup_sid(mem_ctx, &sids[i], NULL, &grp_name, NULL) ) {
                        pstrcpy(p, grp_name);
                        p += 21; 
                        count++;
                }
        }
 
-       SAFE_FREE(sids);
-       
        *rdata_len = PTR_DIFF(p,*rdata);
 
        SSVAL(*rparam,4,count); /* is this right?? */
@@ -1913,11 +2023,10 @@ static BOOL api_NetUserGetGroups(connection_struct *conn,uint16 vuid, char *para
 
        ret = True;
 
-out:
+done:
        unbecome_root();                                /* END ROOT BLOCK */
 
-       pdb_free_sam( &sampw );
-       passwd_free(&passwd);
+       talloc_free(mem_ctx);
 
        return ret;
 }
@@ -2023,43 +2132,42 @@ static BOOL api_NetRemoteTOD(connection_struct *conn,uint16 vuid, char *param,ch
                             char **rdata,char **rparam,
                             int *rdata_len,int *rparam_len)
 {
-  char *p;
-  *rparam_len = 4;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-
-  *rdata_len = 21;
-  *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
-
-  SSVAL(*rparam,0,NERR_Success);
-  SSVAL(*rparam,2,0);          /* converter word */
-
-  p = *rdata;
-
-  {
-    struct tm *t;
-    time_t unixdate = time(NULL);
-
-    srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
-                                   by NT in a "net time" operation,
-                                   it seems to ignore the one below */
-
-    /* the client expects to get localtime, not GMT, in this bit 
-       (I think, this needs testing) */
-    t = localtime(&unixdate);
-
-    SIVAL(p,4,0);              /* msecs ? */
-    SCVAL(p,8,t->tm_hour);
-    SCVAL(p,9,t->tm_min);
-    SCVAL(p,10,t->tm_sec);
-    SCVAL(p,11,0);             /* hundredths of seconds */
-    SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
-    SSVAL(p,14,10000);         /* timer interval in 0.0001 of sec */
-    SCVAL(p,16,t->tm_mday);
-    SCVAL(p,17,t->tm_mon + 1);
-    SSVAL(p,18,1900+t->tm_year);
-    SCVAL(p,20,t->tm_wday);
-  }
-  return(True);
+       struct tm *t;
+       time_t unixdate = time(NULL);
+       char *p;
+
+       *rparam_len = 4;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+
+       *rdata_len = 21;
+       *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+
+       SSVAL(*rparam,0,NERR_Success);
+       SSVAL(*rparam,2,0);             /* converter word */
+
+       p = *rdata;
+
+       srv_put_dos_date3(p,0,unixdate); /* this is the time that is looked at
+                                           by NT in a "net time" operation,
+                                           it seems to ignore the one below */
+
+       /* the client expects to get localtime, not GMT, in this bit 
+               (I think, this needs testing) */
+       t = localtime(&unixdate);
+
+       SIVAL(p,4,0);           /* msecs ? */
+       SCVAL(p,8,t->tm_hour);
+       SCVAL(p,9,t->tm_min);
+       SCVAL(p,10,t->tm_sec);
+       SCVAL(p,11,0);          /* hundredths of seconds */
+       SSVALS(p,12,get_time_zone(unixdate)/60); /* timezone in minutes from GMT */
+       SSVAL(p,14,10000);              /* timer interval in 0.0001 of sec */
+       SCVAL(p,16,t->tm_mday);
+       SCVAL(p,17,t->tm_mon + 1);
+       SSVAL(p,18,1900+t->tm_year);
+       SCVAL(p,20,t->tm_wday);
+
+       return True;
 }
 
 /****************************************************************************
@@ -2111,7 +2219,7 @@ static BOOL api_SetUserPassword(connection_struct *conn,uint16 vuid, char *param
                        }
                        unbecome_root();
 
-                       free_server_info(&server_info);
+                       talloc_free(server_info);
                }
                data_blob_clear_free(&password);
        }
@@ -2421,103 +2529,117 @@ static BOOL api_RNetServerGetInfo(connection_struct *conn,uint16 vuid, char *par
                                  char **rdata,char **rparam,
                                  int *rdata_len,int *rparam_len)
 {
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *p = skip_string(str2,1);
-  int uLevel = SVAL(p,0);
-  char *p2;
-  int struct_len;
-
-  DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
-
-  /* check it's a supported varient */
-  if (!prefix_ok(str1,"WrLh")) return False;
-  switch( uLevel ) {
-  case 0:
-    if (strcmp(str2,"B16") != 0) return False;
-    struct_len = 16;
-    break;
-  case 1:
-    if (strcmp(str2,"B16BBDz") != 0) return False;
-    struct_len = 26;
-    break;
-  case 2:
-    if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")
-       != 0) return False;
-    struct_len = 134;
-    break;
-  case 3:
-    if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz")
-       != 0) return False;
-    struct_len = 144;
-    break;
-  case 20:
-    if (strcmp(str2,"DN") != 0) return False;
-    struct_len = 6;
-    break;
-  case 50:
-    if (strcmp(str2,"B16BBDzWWzzz") != 0) return False;
-    struct_len = 42;
-    break;
-  default: return False;
-  }
-
-  *rdata_len = mdrcnt;
-  *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
-
-  p = *rdata;
-  p2 = p + struct_len;
-  if (uLevel != 20) {
-    srvstr_push(NULL, p,get_local_machine_name(),16, 
-               STR_ASCII|STR_UPPER|STR_TERMINATE);
-  }
-  p += 16;
-  if (uLevel > 0)
-    {
-      struct srv_info_struct *servers=NULL;
-      int i,count;
-      pstring comment;
-      uint32 servertype= lp_default_server_announce();
-
-      push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
-
-      if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
-       for (i=0;i<count;i++) {
-         if (strequal(servers[i].name,get_local_machine_name())) {
-           servertype = servers[i].type;
-           push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);           
-         }
-       }
-      }
-      SAFE_FREE(servers);
-
-      SCVAL(p,0,lp_major_announce_version());
-      SCVAL(p,1,lp_minor_announce_version());
-      SIVAL(p,2,servertype);
-
-      if (mdrcnt == struct_len) {
-       SIVAL(p,6,0);
-      } else {
-       SIVAL(p,6,PTR_DIFF(p2,*rdata));
-       standard_sub_conn(conn,comment,sizeof(comment));
-       StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
-       p2 = skip_string(p2,1);
-      }
-    }
-  if (uLevel > 1)
-    {
-      return False;            /* not yet implemented */
-    }
-
-  *rdata_len = PTR_DIFF(p2,*rdata);
-
-  *rparam_len = 6;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-  SSVAL(*rparam,0,NERR_Success);
-  SSVAL(*rparam,2,0);          /* converter word */
-  SSVAL(*rparam,4,*rdata_len);
-
-  return(True);
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *p = skip_string(str2,1);
+       int uLevel = SVAL(p,0);
+       char *p2;
+       int struct_len;
+
+       DEBUG(4,("NetServerGetInfo level %d\n",uLevel));
+
+       /* check it's a supported varient */
+       if (!prefix_ok(str1,"WrLh")) {
+               return False;
+       }
+
+       switch( uLevel ) {
+               case 0:
+                       if (strcmp(str2,"B16") != 0) {
+                               return False;
+                       }
+                       struct_len = 16;
+                       break;
+               case 1:
+                       if (strcmp(str2,"B16BBDz") != 0) {
+                               return False;
+                       }
+                       struct_len = 26;
+                       break;
+               case 2:
+                       if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWz")!= 0) {
+                               return False;
+                       }
+                       struct_len = 134;
+                       break;
+               case 3:
+                       if (strcmp(str2,"B16BBDzDDDWWzWWWWWWWBB21zWWWWWWWWWWWWWWWWWWWWWWzDWz") != 0) {
+                               return False;
+                       }
+                       struct_len = 144;
+                       break;
+               case 20:
+                       if (strcmp(str2,"DN") != 0) {
+                               return False;
+                       }
+                       struct_len = 6;
+                       break;
+               case 50:
+                       if (strcmp(str2,"B16BBDzWWzzz") != 0) {
+                               return False;
+                       }
+                       struct_len = 42;
+                       break;
+               default:
+                       return False;
+       }
+
+       *rdata_len = mdrcnt;
+       *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+
+       p = *rdata;
+       p2 = p + struct_len;
+       if (uLevel != 20) {
+               srvstr_push(NULL, p,get_local_machine_name(),16, 
+                       STR_ASCII|STR_UPPER|STR_TERMINATE);
+       }
+       p += 16;
+       if (uLevel > 0) {
+               struct srv_info_struct *servers=NULL;
+               int i,count;
+               pstring comment;
+               uint32 servertype= lp_default_server_announce();
+
+               push_ascii(comment,lp_serverstring(), MAX_SERVER_STRING_LENGTH,STR_TERMINATE);
+
+               if ((count=get_server_info(SV_TYPE_ALL,&servers,lp_workgroup()))>0) {
+                       for (i=0;i<count;i++) {
+                               if (strequal(servers[i].name,get_local_machine_name())) {
+                                       servertype = servers[i].type;
+                                       push_ascii(comment,servers[i].comment,sizeof(pstring),STR_TERMINATE);
+                               }
+                       }
+               }
+
+               SAFE_FREE(servers);
+
+               SCVAL(p,0,lp_major_announce_version());
+               SCVAL(p,1,lp_minor_announce_version());
+               SIVAL(p,2,servertype);
+
+               if (mdrcnt == struct_len) {
+                       SIVAL(p,6,0);
+               } else {
+                       SIVAL(p,6,PTR_DIFF(p2,*rdata));
+                       standard_sub_conn(conn,comment,sizeof(comment));
+                       StrnCpy(p2,comment,MAX(mdrcnt - struct_len,0));
+                       p2 = skip_string(p2,1);
+               }
+       }
+
+       if (uLevel > 1) {
+               return False;           /* not yet implemented */
+       }
+
+       *rdata_len = PTR_DIFF(p2,*rdata);
+
+       *rparam_len = 6;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       SSVAL(*rparam,0,NERR_Success);
+       SSVAL(*rparam,2,0);             /* converter word */
+       SSVAL(*rparam,4,*rdata_len);
+
+       return True;
 }
 
 /****************************************************************************
@@ -2529,67 +2651,67 @@ static BOOL api_NetWkstaGetInfo(connection_struct *conn,uint16 vuid, char *param
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
 {
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *p = skip_string(str2,1);
-  char *p2;
-  int level = SVAL(p,0);
-
-  DEBUG(4,("NetWkstaGetInfo level %d\n",level));
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *p = skip_string(str2,1);
+       char *p2;
+       int level = SVAL(p,0);
 
-  *rparam_len = 6;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       DEBUG(4,("NetWkstaGetInfo level %d\n",level));
 
-  /* check it's a supported varient */
-  if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz")))
-    return(False);
+       *rparam_len = 6;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
 
-  *rdata_len = mdrcnt + 1024;
-  *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
+       /* check it's a supported varient */
+       if (!(level==10 && strcsequal(str1,"WrLh") && strcsequal(str2,"zzzBBzz"))) {
+               return False;
+       }
 
-  SSVAL(*rparam,0,NERR_Success);
-  SSVAL(*rparam,2,0);          /* converter word */
+       *rdata_len = mdrcnt + 1024;
+       *rdata = SMB_REALLOC_LIMIT(*rdata,*rdata_len);
 
-  p = *rdata;
-  p2 = p + 22;
+       SSVAL(*rparam,0,NERR_Success);
+       SSVAL(*rparam,2,0);             /* converter word */
 
+       p = *rdata;
+       p2 = p + 22;
 
-  SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
-  pstrcpy(p2,get_local_machine_name());
-  strupper_m(p2);
-  p2 = skip_string(p2,1);
-  p += 4;
+       SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* host name */
+       pstrcpy(p2,get_local_machine_name());
+       strupper_m(p2);
+       p2 = skip_string(p2,1);
+       p += 4;
 
-  SIVAL(p,0,PTR_DIFF(p2,*rdata));
-  pstrcpy(p2,current_user_info.smb_name);
-  p2 = skip_string(p2,1);
-  p += 4;
+       SIVAL(p,0,PTR_DIFF(p2,*rdata));
+       pstrcpy(p2,current_user_info.smb_name);
+       p2 = skip_string(p2,1);
+       p += 4;
 
-  SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
-  pstrcpy(p2,lp_workgroup());
-  strupper_m(p2);
-  p2 = skip_string(p2,1);
-  p += 4;
+       SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* login domain */
+       pstrcpy(p2,lp_workgroup());
+       strupper_m(p2);
+       p2 = skip_string(p2,1);
+       p += 4;
 
-  SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
-  SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
-  p += 2;
+       SCVAL(p,0,lp_major_announce_version()); /* system version - e.g 4 in 4.1 */
+       SCVAL(p,1,lp_minor_announce_version()); /* system version - e.g .1 in 4.1 */
+       p += 2;
 
-  SIVAL(p,0,PTR_DIFF(p2,*rdata));
-  pstrcpy(p2,lp_workgroup());  /* don't know.  login domain?? */
-  p2 = skip_string(p2,1);
-  p += 4;
+       SIVAL(p,0,PTR_DIFF(p2,*rdata));
+       pstrcpy(p2,lp_workgroup());     /* don't know.  login domain?? */
+       p2 = skip_string(p2,1);
+       p += 4;
 
-  SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
-  pstrcpy(p2,"");
-  p2 = skip_string(p2,1);
-  p += 4;
+       SIVAL(p,0,PTR_DIFF(p2,*rdata)); /* don't know */
+       pstrcpy(p2,"");
+       p2 = skip_string(p2,1);
+       p += 4;
 
-  *rdata_len = PTR_DIFF(p2,*rdata);
+       *rdata_len = PTR_DIFF(p2,*rdata);
 
-  SSVAL(*rparam,4,*rdata_len);
+       SSVAL(*rparam,4,*rdata_len);
 
-  return(True);
+       return True;
 }
 
 /****************************************************************************
@@ -2929,75 +3051,83 @@ static BOOL api_WWkstaUserLogon(connection_struct *conn,uint16 vuid, char *param
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
 {
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *p = skip_string(str2,1);
-  int uLevel;
-  struct pack_desc desc;
-  char* name;
-    /* With share level security vuid will always be zero.
-       Don't depend on vuser being non-null !!. JRA */
-    user_struct *vuser = get_valid_user_struct(vuid);
-    if(vuser != NULL)
-      DEBUG(3,("  Username of UID %d is %s\n", (int)vuser->uid, 
-              vuser->user.unix_name));
-
-  uLevel = SVAL(p,0);
-  name = p + 2;
-
-  memset((char *)&desc,'\0',sizeof(desc));
-
-  DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
-
-  /* check it's a supported varient */
-  if (strcmp(str1,"OOWb54WrLh") != 0) return False;
-  if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) return False;
-  if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
-  desc.base = *rdata;
-  desc.buflen = mdrcnt;
-  desc.subformat = NULL;
-  desc.format = str2;
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *p = skip_string(str2,1);
+       int uLevel;
+       struct pack_desc desc;
+       char* name;
+               /* With share level security vuid will always be zero.
+                  Don't depend on vuser being non-null !!. JRA */
+       user_struct *vuser = get_valid_user_struct(vuid);
+
+       if(vuser != NULL) {
+               DEBUG(3,("  Username of UID %d is %s\n", (int)vuser->uid, 
+                       vuser->user.unix_name));
+       }
+
+       uLevel = SVAL(p,0);
+       name = p + 2;
+
+       memset((char *)&desc,'\0',sizeof(desc));
+
+       DEBUG(3,("WWkstaUserLogon uLevel=%d name=%s\n",uLevel,name));
+
+       /* check it's a supported varient */
+       if (strcmp(str1,"OOWb54WrLh") != 0) {
+               return False;
+       }
+       if (uLevel != 1 || strcmp(str2,"WB21BWDWWDDDDDDDzzzD") != 0) {
+               return False;
+       }
+       if (mdrcnt > 0) {
+               *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+       }
+
+       desc.base = *rdata;
+       desc.buflen = mdrcnt;
+       desc.subformat = NULL;
+       desc.format = str2;
   
-  if (init_package(&desc,1,0))
-  {
-    PACKI(&desc,"W",0);                /* code */
-    PACKS(&desc,"B21",name);   /* eff. name */
-    PACKS(&desc,"B","");               /* pad */
-    PACKI(&desc,"W",
-         conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
-    PACKI(&desc,"D",0);                /* auth flags XXX */
-    PACKI(&desc,"W",0);                /* num logons */
-    PACKI(&desc,"W",0);                /* bad pw count */
-    PACKI(&desc,"D",0);                /* last logon */
-    PACKI(&desc,"D",-1);               /* last logoff */
-    PACKI(&desc,"D",-1);               /* logoff time */
-    PACKI(&desc,"D",-1);               /* kickoff time */
-    PACKI(&desc,"D",0);                /* password age */
-    PACKI(&desc,"D",0);                /* password can change */
-    PACKI(&desc,"D",-1);               /* password must change */
-    {
-      fstring mypath;
-      fstrcpy(mypath,"\\\\");
-      fstrcat(mypath,get_local_machine_name());
-      strupper_m(mypath);
-      PACKS(&desc,"z",mypath); /* computer */
-    }
-    PACKS(&desc,"z",lp_workgroup());/* domain */
-
-    PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :"");          /* script path */
-
-    PACKI(&desc,"D",0x00000000);               /* reserved */
-  }
-
-  *rdata_len = desc.usedlen;
-  *rparam_len = 6;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-  SSVALS(*rparam,0,desc.errcode);
-  SSVAL(*rparam,2,0);
-  SSVAL(*rparam,4,desc.neededlen);
-
-  DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
-  return(True);
+       if (init_package(&desc,1,0)) {
+               PACKI(&desc,"W",0);             /* code */
+               PACKS(&desc,"B21",name);        /* eff. name */
+               PACKS(&desc,"B","");            /* pad */
+               PACKI(&desc,"W", conn->admin_user?USER_PRIV_ADMIN:USER_PRIV_USER);
+               PACKI(&desc,"D",0);             /* auth flags XXX */
+               PACKI(&desc,"W",0);             /* num logons */
+               PACKI(&desc,"W",0);             /* bad pw count */
+               PACKI(&desc,"D",0);             /* last logon */
+               PACKI(&desc,"D",-1);            /* last logoff */
+               PACKI(&desc,"D",-1);            /* logoff time */
+               PACKI(&desc,"D",-1);            /* kickoff time */
+               PACKI(&desc,"D",0);             /* password age */
+               PACKI(&desc,"D",0);             /* password can change */
+               PACKI(&desc,"D",-1);            /* password must change */
+
+               {
+                       fstring mypath;
+                       fstrcpy(mypath,"\\\\");
+                       fstrcat(mypath,get_local_machine_name());
+                       strupper_m(mypath);
+                       PACKS(&desc,"z",mypath); /* computer */
+               }
+
+               PACKS(&desc,"z",lp_workgroup());/* domain */
+               PACKS(&desc,"z", vuser && vuser->logon_script ? vuser->logon_script :""); /* script path */
+               PACKI(&desc,"D",0x00000000);            /* reserved */
+       }
+
+       *rdata_len = desc.usedlen;
+       *rparam_len = 6;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       SSVALS(*rparam,0,desc.errcode);
+       SSVAL(*rparam,2,0);
+       SSVAL(*rparam,4,desc.neededlen);
+
+       DEBUG(4,("WWkstaUserLogon: errorcode %d\n",desc.errcode));
+
+       return True;
 }
 
 /****************************************************************************
@@ -3009,24 +3139,28 @@ static BOOL api_WAccessGetUserPerms(connection_struct *conn,uint16 vuid, char *p
                                    char **rdata,char **rparam,
                                    int *rdata_len,int *rparam_len)
 {
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *user = skip_string(str2,1);
-  char *resource = skip_string(user,1);
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *user = skip_string(str2,1);
+       char *resource = skip_string(user,1);
 
-  DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
+       DEBUG(3,("WAccessGetUserPerms user=%s resource=%s\n",user,resource));
 
-  /* check it's a supported varient */
-  if (strcmp(str1,"zzh") != 0) return False;
-  if (strcmp(str2,"") != 0) return False;
+       /* check it's a supported varient */
+       if (strcmp(str1,"zzh") != 0) {
+               return False;
+       }
+       if (strcmp(str2,"") != 0) {
+               return False;
+       }
 
-  *rparam_len = 6;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-  SSVALS(*rparam,0,0);         /* errorcode */
-  SSVAL(*rparam,2,0);          /* converter word */
-  SSVAL(*rparam,4,0x7f);       /* permission flags */
+       *rparam_len = 6;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       SSVALS(*rparam,0,0);            /* errorcode */
+       SSVAL(*rparam,2,0);             /* converter word */
+       SSVAL(*rparam,4,0x7f);  /* permission flags */
 
-  return(True);
+       return True;
 }
 
 /****************************************************************************
@@ -3038,192 +3172,224 @@ static BOOL api_WPrintJobGetInfo(connection_struct *conn,uint16 vuid, char *para
                                 char **rdata,char **rparam,
                                 int *rdata_len,int *rparam_len)
 {
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *p = skip_string(str2,1);
-  int uLevel;
-  int count;
-  int i;
-  int snum;
-  fstring sharename;
-  uint32 jobid;
-  struct pack_desc desc;
-  print_queue_struct *queue=NULL;
-  print_status_struct status;
-  char *tmpdata=NULL;
-
-  uLevel = SVAL(p,2);
-
-  memset((char *)&desc,'\0',sizeof(desc));
-  memset((char *)&status,'\0',sizeof(status));
-
-  DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
-
-  /* check it's a supported varient */
-  if (strcmp(str1,"WWrLh") != 0) return False;
-  if (!check_printjob_info(&desc,uLevel,str2)) return False;
-
-  if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid))
-    return False;
-
-  snum = lp_servicenumber( sharename);
-  if (snum < 0 || !VALID_SNUM(snum)) return(False);
-
-  count = print_queue_status(snum,&queue,&status);
-  for (i = 0; i < count; i++) {
-    if (queue[i].job == jobid) break;
-  }
-
-  if (mdrcnt > 0) {
-    *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
-    desc.base = *rdata;
-    desc.buflen = mdrcnt;
-  } else {
-    /*
-     * Don't return data but need to get correct length
-     *  init_package will return wrong size if buflen=0
-     */
-    desc.buflen = getlen(desc.format);
-    desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
-  }
-
-  if (init_package(&desc,1,0)) {
-    if (i < count) {
-      fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
-      *rdata_len = desc.usedlen;
-    }
-    else {
-      desc.errcode = NERR_JobNotFound;
-      *rdata_len = 0;
-    }
-  }
-
-  *rparam_len = 6;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-  SSVALS(*rparam,0,desc.errcode);
-  SSVAL(*rparam,2,0);
-  SSVAL(*rparam,4,desc.neededlen);
-
-  SAFE_FREE(queue);
-  SAFE_FREE(tmpdata);
-
-  DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
-  return(True);
-}
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *p = skip_string(str2,1);
+       int uLevel;
+       int count;
+       int i;
+       int snum;
+       fstring sharename;
+       uint32 jobid;
+       struct pack_desc desc;
+       print_queue_struct *queue=NULL;
+       print_status_struct status;
+       char *tmpdata=NULL;
 
-static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
-                                  int mdrcnt,int mprcnt,
-                                  char **rdata,char **rparam,
-                                  int *rdata_len,int *rparam_len)
-{
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *p = skip_string(str2,1);
-  char* name = p;
-  int uLevel;
-  int count;
-  int i, succnt=0;
-  int snum;
-  struct pack_desc desc;
-  print_queue_struct *queue=NULL;
-  print_status_struct status;
-
-  memset((char *)&desc,'\0',sizeof(desc));
-  memset((char *)&status,'\0',sizeof(status));
-
-  p = skip_string(p,1);
-  uLevel = SVAL(p,0);
-
-  DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
-
-  /* check it's a supported variant */
-  if (strcmp(str1,"zWrLeh") != 0) 
-    return False;
-    
-  if (uLevel > 2) 
-    return False;      /* defined only for uLevel 0,1,2 */
-    
-  if (!check_printjob_info(&desc,uLevel,str2)) 
-    return False;
-
-  snum = find_service(name);
-  if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) )
-    return False;
-
-  count = print_queue_status(snum,&queue,&status);
-  if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
-  desc.base = *rdata;
-  desc.buflen = mdrcnt;
-
-  if (init_package(&desc,count,0)) {
-    succnt = 0;
-    for (i = 0; i < count; i++) {
-      fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
-      if (desc.errcode == NERR_Success) succnt = i+1;
-    }
-  }
-
-  *rdata_len = desc.usedlen;
-
-  *rparam_len = 8;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-  SSVALS(*rparam,0,desc.errcode);
-  SSVAL(*rparam,2,0);
-  SSVAL(*rparam,4,succnt);
-  SSVAL(*rparam,6,count);
-
-  SAFE_FREE(queue);
-
-  DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
-  return(True);
-}
+       uLevel = SVAL(p,2);
+
+       memset((char *)&desc,'\0',sizeof(desc));
+       memset((char *)&status,'\0',sizeof(status));
+
+       DEBUG(3,("WPrintJobGetInfo uLevel=%d uJobId=0x%X\n",uLevel,SVAL(p,0)));
+
+       /* check it's a supported varient */
+       if (strcmp(str1,"WWrLh") != 0) {
+               return False;
+       }
+       if (!check_printjob_info(&desc,uLevel,str2)) {
+               return False;
+       }
+
+       if(!rap_to_pjobid(SVAL(p,0), sharename, &jobid)) {
+               return False;
+       }
+
+       snum = lp_servicenumber( sharename);
+       if (snum < 0 || !VALID_SNUM(snum)) {
+               return(False);
+       }
+
+       count = print_queue_status(snum,&queue,&status);
+       for (i = 0; i < count; i++) {
+               if (queue[i].job == jobid) {
+                       break;
+               }
+       }
+
+       if (mdrcnt > 0) {
+               *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+               desc.base = *rdata;
+               desc.buflen = mdrcnt;
+       } else {
+               /*
+                * Don't return data but need to get correct length
+                *  init_package will return wrong size if buflen=0
+                */
+               desc.buflen = getlen(desc.format);
+               desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
+       }
+
+       if (init_package(&desc,1,0)) {
+               if (i < count) {
+                       fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
+                       *rdata_len = desc.usedlen;
+               } else {
+                       desc.errcode = NERR_JobNotFound;
+                       *rdata_len = 0;
+               }
+       }
+
+       *rparam_len = 6;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       SSVALS(*rparam,0,desc.errcode);
+       SSVAL(*rparam,2,0);
+       SSVAL(*rparam,4,desc.neededlen);
+
+       SAFE_FREE(queue);
+       SAFE_FREE(tmpdata);
+
+       DEBUG(4,("WPrintJobGetInfo: errorcode %d\n",desc.errcode));
+
+       return True;
+}
+
+static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *param,char *data,
+                                  int mdrcnt,int mprcnt,
+                                  char **rdata,char **rparam,
+                                  int *rdata_len,int *rparam_len)
+{
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *p = skip_string(str2,1);
+       char* name = p;
+       int uLevel;
+       int count;
+       int i, succnt=0;
+       int snum;
+       struct pack_desc desc;
+       print_queue_struct *queue=NULL;
+       print_status_struct status;
+
+       memset((char *)&desc,'\0',sizeof(desc));
+       memset((char *)&status,'\0',sizeof(status));
+
+       p = skip_string(p,1);
+       uLevel = SVAL(p,0);
+
+       DEBUG(3,("WPrintJobEnumerate uLevel=%d name=%s\n",uLevel,name));
+
+       /* check it's a supported variant */
+       if (strcmp(str1,"zWrLeh") != 0) {
+               return False;
+       }
+    
+       if (uLevel > 2) {
+               return False;   /* defined only for uLevel 0,1,2 */
+       }
+    
+       if (!check_printjob_info(&desc,uLevel,str2)) { 
+               return False;
+       }
+
+       snum = find_service(name);
+       if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
+               return False;
+       }
+
+       count = print_queue_status(snum,&queue,&status);
+       if (mdrcnt > 0) {
+               *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+       }
+       desc.base = *rdata;
+       desc.buflen = mdrcnt;
+
+       if (init_package(&desc,count,0)) {
+               succnt = 0;
+               for (i = 0; i < count; i++) {
+                       fill_printjob_info(conn,snum,uLevel,&desc,&queue[i],i);
+                       if (desc.errcode == NERR_Success) {
+                               succnt = i+1;
+                       }
+               }
+       }
+
+       *rdata_len = desc.usedlen;
+
+       *rparam_len = 8;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       SSVALS(*rparam,0,desc.errcode);
+       SSVAL(*rparam,2,0);
+       SSVAL(*rparam,4,succnt);
+       SSVAL(*rparam,6,count);
+
+       SAFE_FREE(queue);
+
+       DEBUG(4,("WPrintJobEnumerate: errorcode %d\n",desc.errcode));
+
+       return True;
+}
 
 static int check_printdest_info(struct pack_desc* desc,
                                int uLevel, char* id)
 {
-  desc->subformat = NULL;
-  switch( uLevel ) {
-  case 0: desc->format = "B9"; break;
-  case 1: desc->format = "B9B21WWzW"; break;
-  case 2: desc->format = "z"; break;
-  case 3: desc->format = "zzzWWzzzWW"; break;
-  default: return False;
-  }
-  if (strcmp(desc->format,id) != 0) return False;
-  return True;
+       desc->subformat = NULL;
+       switch( uLevel ) {
+               case 0:
+                       desc->format = "B9";
+                       break;
+               case 1:
+                       desc->format = "B9B21WWzW";
+                       break;
+               case 2:
+                       desc->format = "z";
+                       break;
+               case 3:
+                       desc->format = "zzzWWzzzWW";
+                       break;
+               default:
+                       return False;
+       }
+       if (strcmp(desc->format,id) != 0) {
+               return False;
+       }
+       return True;
 }
 
 static void fill_printdest_info(connection_struct *conn, int snum, int uLevel,
                                struct pack_desc* desc)
 {
-  char buf[100];
-  strncpy(buf,SERVICE(snum),sizeof(buf)-1);
-  buf[sizeof(buf)-1] = 0;
-  strupper_m(buf);
-  if (uLevel <= 1) {
-    PACKS(desc,"B9",buf);      /* szName */
-    if (uLevel == 1) {
-      PACKS(desc,"B21","");    /* szUserName */
-      PACKI(desc,"W",0);               /* uJobId */
-      PACKI(desc,"W",0);               /* fsStatus */
-      PACKS(desc,"z","");      /* pszStatus */
-      PACKI(desc,"W",0);               /* time */
-    }
-  }
-  if (uLevel == 2 || uLevel == 3) {
-    PACKS(desc,"z",buf);               /* pszPrinterName */
-    if (uLevel == 3) {
-      PACKS(desc,"z","");      /* pszUserName */
-      PACKS(desc,"z","");      /* pszLogAddr */
-      PACKI(desc,"W",0);               /* uJobId */
-      PACKI(desc,"W",0);               /* fsStatus */
-      PACKS(desc,"z","");      /* pszStatus */
-      PACKS(desc,"z","");      /* pszComment */
-      PACKS(desc,"z","NULL"); /* pszDrivers */
-      PACKI(desc,"W",0);               /* time */
-      PACKI(desc,"W",0);               /* pad1 */
-    }
-  }
+       char buf[100];
+
+       strncpy(buf,SERVICE(snum),sizeof(buf)-1);
+       buf[sizeof(buf)-1] = 0;
+       strupper_m(buf);
+
+       if (uLevel <= 1) {
+               PACKS(desc,"B9",buf);   /* szName */
+               if (uLevel == 1) {
+                       PACKS(desc,"B21","");   /* szUserName */
+                       PACKI(desc,"W",0);              /* uJobId */
+                       PACKI(desc,"W",0);              /* fsStatus */
+                       PACKS(desc,"z","");     /* pszStatus */
+                       PACKI(desc,"W",0);              /* time */
+               }
+       }
+
+       if (uLevel == 2 || uLevel == 3) {
+               PACKS(desc,"z",buf);            /* pszPrinterName */
+               if (uLevel == 3) {
+                       PACKS(desc,"z","");     /* pszUserName */
+                       PACKS(desc,"z","");     /* pszLogAddr */
+                       PACKI(desc,"W",0);              /* uJobId */
+                       PACKI(desc,"W",0);              /* fsStatus */
+                       PACKS(desc,"z","");     /* pszStatus */
+                       PACKS(desc,"z","");     /* pszComment */
+                       PACKS(desc,"z","NULL"); /* pszDrivers */
+                       PACKI(desc,"W",0);              /* time */
+                       PACKI(desc,"W",0);              /* pad1 */
+               }
+       }
 }
 
 static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *param,char *data,
@@ -3231,60 +3397,64 @@ static BOOL api_WPrintDestGetInfo(connection_struct *conn,uint16 vuid, char *par
                                  char **rdata,char **rparam,
                                  int *rdata_len,int *rparam_len)
 {
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *p = skip_string(str2,1);
-  char* PrinterName = p;
-  int uLevel;
-  struct pack_desc desc;
-  int snum;
-  char *tmpdata=NULL;
-
-  memset((char *)&desc,'\0',sizeof(desc));
-
-  p = skip_string(p,1);
-  uLevel = SVAL(p,0);
-
-  DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
-
-  /* check it's a supported varient */
-  if (strcmp(str1,"zWrLh") != 0) return False;
-  if (!check_printdest_info(&desc,uLevel,str2)) return False;
-
-  snum = find_service(PrinterName);
-  if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
-    *rdata_len = 0;
-    desc.errcode = NERR_DestNotFound;
-    desc.neededlen = 0;
-  }
-  else {
-    if (mdrcnt > 0) {
-      *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
-      desc.base = *rdata;
-      desc.buflen = mdrcnt;
-    } else {
-      /*
-       * Don't return data but need to get correct length
-       *  init_package will return wrong size if buflen=0
-       */
-      desc.buflen = getlen(desc.format);
-      desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
-    }
-    if (init_package(&desc,1,0)) {
-      fill_printdest_info(conn,snum,uLevel,&desc);
-    }
-    *rdata_len = desc.usedlen;
-  }
-
-  *rparam_len = 6;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-  SSVALS(*rparam,0,desc.errcode);
-  SSVAL(*rparam,2,0);
-  SSVAL(*rparam,4,desc.neededlen);
-
-  DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
-  SAFE_FREE(tmpdata);
-  return(True);
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *p = skip_string(str2,1);
+       char* PrinterName = p;
+       int uLevel;
+       struct pack_desc desc;
+       int snum;
+       char *tmpdata=NULL;
+
+       memset((char *)&desc,'\0',sizeof(desc));
+
+       p = skip_string(p,1);
+       uLevel = SVAL(p,0);
+
+       DEBUG(3,("WPrintDestGetInfo uLevel=%d PrinterName=%s\n",uLevel,PrinterName));
+
+       /* check it's a supported varient */
+       if (strcmp(str1,"zWrLh") != 0) {
+               return False;
+       }
+       if (!check_printdest_info(&desc,uLevel,str2)) {
+               return False;
+       }
+
+       snum = find_service(PrinterName);
+       if ( !(lp_snum_ok(snum) && lp_print_ok(snum)) ) {
+               *rdata_len = 0;
+               desc.errcode = NERR_DestNotFound;
+               desc.neededlen = 0;
+       } else {
+               if (mdrcnt > 0) {
+                       *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+                       desc.base = *rdata;
+                       desc.buflen = mdrcnt;
+               } else {
+                       /*
+                        * Don't return data but need to get correct length
+                        * init_package will return wrong size if buflen=0
+                        */
+                       desc.buflen = getlen(desc.format);
+                       desc.base = tmpdata = (char *)SMB_MALLOC( desc.buflen );
+               }
+               if (init_package(&desc,1,0)) {
+                       fill_printdest_info(conn,snum,uLevel,&desc);
+               }
+               *rdata_len = desc.usedlen;
+       }
+
+       *rparam_len = 6;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       SSVALS(*rparam,0,desc.errcode);
+       SSVAL(*rparam,2,0);
+       SSVAL(*rparam,4,desc.neededlen);
+
+       DEBUG(4,("WPrintDestGetInfo: errorcode %d\n",desc.errcode));
+       SAFE_FREE(tmpdata);
+
+       return True;
 }
 
 static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
@@ -3292,56 +3462,68 @@ static BOOL api_WPrintDestEnum(connection_struct *conn,uint16 vuid, char *param,
                               char **rdata,char **rparam,
                               int *rdata_len,int *rparam_len)
 {
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *p = skip_string(str2,1);
-  int uLevel;
-  int queuecnt;
-  int i, n, succnt=0;
-  struct pack_desc desc;
-  int services = lp_numservices();
-
-  memset((char *)&desc,'\0',sizeof(desc));
-
-  uLevel = SVAL(p,0);
-
-  DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
-
-  /* check it's a supported varient */
-  if (strcmp(str1,"WrLeh") != 0) return False;
-  if (!check_printdest_info(&desc,uLevel,str2)) return False;
-
-  queuecnt = 0;
-  for (i = 0; i < services; i++)
-    if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i))
-      queuecnt++;
-
-  if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
-  desc.base = *rdata;
-  desc.buflen = mdrcnt;
-  if (init_package(&desc,queuecnt,0)) {    
-    succnt = 0;
-    n = 0;
-    for (i = 0; i < services; i++) {
-      if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
-       fill_printdest_info(conn,i,uLevel,&desc);
-       n++;
-       if (desc.errcode == NERR_Success) succnt = n;
-      }
-    }
-  }
-
-  *rdata_len = desc.usedlen;
-
-  *rparam_len = 8;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-  SSVALS(*rparam,0,desc.errcode);
-  SSVAL(*rparam,2,0);
-  SSVAL(*rparam,4,succnt);
-  SSVAL(*rparam,6,queuecnt);
-
-  DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
-  return(True);
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *p = skip_string(str2,1);
+       int uLevel;
+       int queuecnt;
+       int i, n, succnt=0;
+       struct pack_desc desc;
+       int services = lp_numservices();
+
+       memset((char *)&desc,'\0',sizeof(desc));
+
+       uLevel = SVAL(p,0);
+
+       DEBUG(3,("WPrintDestEnum uLevel=%d\n",uLevel));
+
+       /* check it's a supported varient */
+       if (strcmp(str1,"WrLeh") != 0) {
+               return False;
+       }
+       if (!check_printdest_info(&desc,uLevel,str2)) {
+               return False;
+       }
+
+       queuecnt = 0;
+       for (i = 0; i < services; i++) {
+               if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
+                       queuecnt++;
+               }
+       }
+
+       if (mdrcnt > 0) {
+               *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+       }
+
+       desc.base = *rdata;
+       desc.buflen = mdrcnt;
+       if (init_package(&desc,queuecnt,0)) {    
+               succnt = 0;
+               n = 0;
+               for (i = 0; i < services; i++) {
+                       if (lp_snum_ok(i) && lp_print_ok(i) && lp_browseable(i)) {
+                               fill_printdest_info(conn,i,uLevel,&desc);
+                               n++;
+                               if (desc.errcode == NERR_Success) {
+                                       succnt = n;
+                               }
+                       }
+               }
+       }
+
+       *rdata_len = desc.usedlen;
+
+       *rparam_len = 8;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       SSVALS(*rparam,0,desc.errcode);
+       SSVAL(*rparam,2,0);
+       SSVAL(*rparam,4,succnt);
+       SSVAL(*rparam,6,queuecnt);
+
+       DEBUG(4,("WPrintDestEnumerate: errorcode %d\n",desc.errcode));
+
+       return True;
 }
 
 static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
@@ -3349,43 +3531,50 @@ static BOOL api_WPrintDriverEnum(connection_struct *conn,uint16 vuid, char *para
                                 char **rdata,char **rparam,
                                 int *rdata_len,int *rparam_len)
 {
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *p = skip_string(str2,1);
-  int uLevel;
-  int succnt;
-  struct pack_desc desc;
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *p = skip_string(str2,1);
+       int uLevel;
+       int succnt;
+       struct pack_desc desc;
 
-  memset((char *)&desc,'\0',sizeof(desc));
+       memset((char *)&desc,'\0',sizeof(desc));
 
-  uLevel = SVAL(p,0);
+       uLevel = SVAL(p,0);
 
-  DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
+       DEBUG(3,("WPrintDriverEnum uLevel=%d\n",uLevel));
 
-  /* check it's a supported varient */
-  if (strcmp(str1,"WrLeh") != 0) return False;
-  if (uLevel != 0 || strcmp(str2,"B41") != 0) return False;
+       /* check it's a supported varient */
+       if (strcmp(str1,"WrLeh") != 0) {
+               return False;
+       }
+       if (uLevel != 0 || strcmp(str2,"B41") != 0) {
+               return False;
+       }
+
+       if (mdrcnt > 0) {
+               *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+       }
+       desc.base = *rdata;
+       desc.buflen = mdrcnt;
+       if (init_package(&desc,1,0)) {
+               PACKS(&desc,"B41","NULL");
+       }
 
-  if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
-  desc.base = *rdata;
-  desc.buflen = mdrcnt;
-  if (init_package(&desc,1,0)) {
-    PACKS(&desc,"B41","NULL");
-  }
+       succnt = (desc.errcode == NERR_Success ? 1 : 0);
 
-  succnt = (desc.errcode == NERR_Success ? 1 : 0);
+       *rdata_len = desc.usedlen;
 
-  *rdata_len = desc.usedlen;
+       *rparam_len = 8;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       SSVALS(*rparam,0,desc.errcode);
+       SSVAL(*rparam,2,0);
+       SSVAL(*rparam,4,succnt);
+       SSVAL(*rparam,6,1);
 
-  *rparam_len = 8;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-  SSVALS(*rparam,0,desc.errcode);
-  SSVAL(*rparam,2,0);
-  SSVAL(*rparam,4,succnt);
-  SSVAL(*rparam,6,1);
+       DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
 
-  DEBUG(4,("WPrintDriverEnum: errorcode %d\n",desc.errcode));
-  return(True);
+       return True;
 }
 
 static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
@@ -3393,44 +3582,51 @@ static BOOL api_WPrintQProcEnum(connection_struct *conn,uint16 vuid, char *param
                                char **rdata,char **rparam,
                                int *rdata_len,int *rparam_len)
 {
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *p = skip_string(str2,1);
-  int uLevel;
-  int succnt;
-  struct pack_desc desc;
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *p = skip_string(str2,1);
+       int uLevel;
+       int succnt;
+       struct pack_desc desc;
 
-  memset((char *)&desc,'\0',sizeof(desc));
+       memset((char *)&desc,'\0',sizeof(desc));
 
-  uLevel = SVAL(p,0);
+       uLevel = SVAL(p,0);
 
-  DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
+       DEBUG(3,("WPrintQProcEnum uLevel=%d\n",uLevel));
 
-  /* check it's a supported varient */
-  if (strcmp(str1,"WrLeh") != 0) return False;
-  if (uLevel != 0 || strcmp(str2,"B13") != 0) return False;
+       /* check it's a supported varient */
+       if (strcmp(str1,"WrLeh") != 0) {
+               return False;
+       }
+       if (uLevel != 0 || strcmp(str2,"B13") != 0) {
+               return False;
+       }
 
-  if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
-  desc.base = *rdata;
-  desc.buflen = mdrcnt;
-  desc.format = str2;
-  if (init_package(&desc,1,0)) {
-    PACKS(&desc,"B13","lpd");
-  }
+       if (mdrcnt > 0) {
+               *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+       }
+       desc.base = *rdata;
+       desc.buflen = mdrcnt;
+       desc.format = str2;
+       if (init_package(&desc,1,0)) {
+               PACKS(&desc,"B13","lpd");
+       }
+
+       succnt = (desc.errcode == NERR_Success ? 1 : 0);
 
-  succnt = (desc.errcode == NERR_Success ? 1 : 0);
+       *rdata_len = desc.usedlen;
 
-  *rdata_len = desc.usedlen;
+       *rparam_len = 8;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       SSVALS(*rparam,0,desc.errcode);
+       SSVAL(*rparam,2,0);
+       SSVAL(*rparam,4,succnt);
+       SSVAL(*rparam,6,1);
 
-  *rparam_len = 8;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-  SSVALS(*rparam,0,desc.errcode);
-  SSVAL(*rparam,2,0);
-  SSVAL(*rparam,4,succnt);
-  SSVAL(*rparam,6,1);
+       DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
 
-  DEBUG(4,("WPrintQProcEnum: errorcode %d\n",desc.errcode));
-  return(True);
+       return True;
 }
 
 static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,char *data,
@@ -3438,45 +3634,52 @@ static BOOL api_WPrintPortEnum(connection_struct *conn,uint16 vuid, char *param,
                               char **rdata,char **rparam,
                               int *rdata_len,int *rparam_len)
 {
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *p = skip_string(str2,1);
-  int uLevel;
-  int succnt;
-  struct pack_desc desc;
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *p = skip_string(str2,1);
+       int uLevel;
+       int succnt;
+       struct pack_desc desc;
+
+       memset((char *)&desc,'\0',sizeof(desc));
 
-  memset((char *)&desc,'\0',sizeof(desc));
+       uLevel = SVAL(p,0);
 
-  uLevel = SVAL(p,0);
+       DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
 
-  DEBUG(3,("WPrintPortEnum uLevel=%d\n",uLevel));
+       /* check it's a supported varient */
+       if (strcmp(str1,"WrLeh") != 0) {
+               return False;
+       }
+       if (uLevel != 0 || strcmp(str2,"B9") != 0) {
+               return False;
+       }
 
-  /* check it's a supported varient */
-  if (strcmp(str1,"WrLeh") != 0) return False;
-  if (uLevel != 0 || strcmp(str2,"B9") != 0) return False;
+       if (mdrcnt > 0) {
+               *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+       }
+       memset((char *)&desc,'\0',sizeof(desc));
+       desc.base = *rdata;
+       desc.buflen = mdrcnt;
+       desc.format = str2;
+       if (init_package(&desc,1,0)) {
+               PACKS(&desc,"B13","lp0");
+       }
 
-  if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
-  memset((char *)&desc,'\0',sizeof(desc));
-  desc.base = *rdata;
-  desc.buflen = mdrcnt;
-  desc.format = str2;
-  if (init_package(&desc,1,0)) {
-    PACKS(&desc,"B13","lp0");
-  }
+       succnt = (desc.errcode == NERR_Success ? 1 : 0);
 
-  succnt = (desc.errcode == NERR_Success ? 1 : 0);
+       *rdata_len = desc.usedlen;
 
-  *rdata_len = desc.usedlen;
+       *rparam_len = 8;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       SSVALS(*rparam,0,desc.errcode);
+       SSVAL(*rparam,2,0);
+       SSVAL(*rparam,4,succnt);
+       SSVAL(*rparam,6,1);
 
-  *rparam_len = 8;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-  SSVALS(*rparam,0,desc.errcode);
-  SSVAL(*rparam,2,0);
-  SSVAL(*rparam,4,succnt);
-  SSVAL(*rparam,6,1);
+       DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
 
-  DEBUG(4,("WPrintPortEnum: errorcode %d\n",desc.errcode));
-  return(True);
+       return True;
 }
 
 
@@ -3489,59 +3692,66 @@ static BOOL api_RNetSessionEnum(connection_struct *conn,uint16 vuid, char *param
                               int *rdata_len,int *rparam_len)
 
 {
-  char *str1 = param+2;
-  char *str2 = skip_string(str1,1);
-  char *p = skip_string(str2,1);
-  int uLevel;
-  struct pack_desc desc;
-  struct sessionid *session_list;
-  int i, num_sessions;
-
-  memset((char *)&desc,'\0',sizeof(desc));
-
-  uLevel = SVAL(p,0);
-
-  DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
-  DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
-  DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
-
-  /* check it's a supported varient */
-  if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) return False;
-  if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) return False;
-
-  num_sessions = list_sessions(&session_list);
-
-  if (mdrcnt > 0) *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
-  memset((char *)&desc,'\0',sizeof(desc));
-  desc.base = *rdata;
-  desc.buflen = mdrcnt;
-  desc.format = str2;
-  if (!init_package(&desc,num_sessions,0)) {
-    return False;
-  }
-
-  for(i=0; i<num_sessions; i++) {
-    PACKS(&desc, "z", session_list[i].remote_machine);
-    PACKS(&desc, "z", session_list[i].username);
-    PACKI(&desc, "W", 1); /* num conns */
-    PACKI(&desc, "W", 0); /* num opens */
-    PACKI(&desc, "W", 1); /* num users */
-    PACKI(&desc, "D", 0); /* session time */
-    PACKI(&desc, "D", 0); /* idle time */
-    PACKI(&desc, "D", 0); /* flags */
-    PACKS(&desc, "z", "Unknown Client"); /* client type string */
-  }
-
-  *rdata_len = desc.usedlen;
-
-  *rparam_len = 8;
-  *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
-  SSVALS(*rparam,0,desc.errcode);
-  SSVAL(*rparam,2,0); /* converter */
-  SSVAL(*rparam,4,num_sessions); /* count */
-
-  DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
-  return True;
+       char *str1 = param+2;
+       char *str2 = skip_string(str1,1);
+       char *p = skip_string(str2,1);
+       int uLevel;
+       struct pack_desc desc;
+       struct sessionid *session_list;
+       int i, num_sessions;
+
+       memset((char *)&desc,'\0',sizeof(desc));
+
+       uLevel = SVAL(p,0);
+
+       DEBUG(3,("RNetSessionEnum uLevel=%d\n",uLevel));
+       DEBUG(7,("RNetSessionEnum req string=%s\n",str1));
+       DEBUG(7,("RNetSessionEnum ret string=%s\n",str2));
+
+       /* check it's a supported varient */
+       if (strcmp(str1,RAP_NetSessionEnum_REQ) != 0) {
+               return False;
+       }
+       if (uLevel != 2 || strcmp(str2,RAP_SESSION_INFO_L2) != 0) {
+               return False;
+       }
+
+       num_sessions = list_sessions(&session_list);
+
+       if (mdrcnt > 0) {
+               *rdata = SMB_REALLOC_LIMIT(*rdata,mdrcnt);
+       }
+       memset((char *)&desc,'\0',sizeof(desc));
+       desc.base = *rdata;
+       desc.buflen = mdrcnt;
+       desc.format = str2;
+       if (!init_package(&desc,num_sessions,0)) {
+               return False;
+       }
+
+       for(i=0; i<num_sessions; i++) {
+               PACKS(&desc, "z", session_list[i].remote_machine);
+               PACKS(&desc, "z", session_list[i].username);
+               PACKI(&desc, "W", 1); /* num conns */
+               PACKI(&desc, "W", 0); /* num opens */
+               PACKI(&desc, "W", 1); /* num users */
+               PACKI(&desc, "D", 0); /* session time */
+               PACKI(&desc, "D", 0); /* idle time */
+               PACKI(&desc, "D", 0); /* flags */
+               PACKS(&desc, "z", "Unknown Client"); /* client type string */
+       }
+
+       *rdata_len = desc.usedlen;
+
+       *rparam_len = 8;
+       *rparam = SMB_REALLOC_LIMIT(*rparam,*rparam_len);
+       SSVALS(*rparam,0,desc.errcode);
+       SSVAL(*rparam,2,0); /* converter */
+       SSVAL(*rparam,4,num_sessions); /* count */
+
+       DEBUG(4,("RNetSessionEnum: errorcode %d\n",desc.errcode));
+
+       return True;
 }
 
 
index 1279fe185d20f60c0e0d22e3a41c0467bbb0915e..4f7858d98590291d40f50e382f406734b1da26d2 100644 (file)
@@ -1094,13 +1094,19 @@ out:
 int enum_msdfs_links(TALLOC_CTX *ctx, struct junction_map *jucn, int jn_max)
 {
        int i=0;
+       int sharecount = 0;
        int jn_count = 0;
 
        if(!lp_host_msdfs()) {
                return 0;
        }
 
-       for(i=0;i < lp_numservices() && (jn_max - jn_count) > 0;i++) {
+       /* Ensure all the usershares are loaded. */
+       become_root();
+       sharecount = load_usershare_shares();
+       unbecome_root();
+
+       for(i=0;i < sharecount && (jn_max - jn_count) > 0;i++) {
                if(lp_msdfs_root(i)) {
                        jn_count += form_junctions(ctx, i,jucn,jn_max - jn_count);
                }
index 9bc444d2536700327075bd69e221fa7c28421ef1..a824978eceab41401ad2b72e209a619e349449f0 100644 (file)
@@ -87,7 +87,7 @@ int vfs_get_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid,
 
        id.uid = -1;
 
-       if (psid && !NT_STATUS_IS_OK(sid_to_uid(psid, &id.uid))) {
+       if (psid && !sid_to_uid(psid, &id.uid)) {
                DEBUG(0,("sid_to_uid: failed, SID[%s]\n",
                        sid_string_static(psid)));      
        }
@@ -131,7 +131,7 @@ int vfs_set_ntquota(files_struct *fsp, enum SMB_QUOTA_TYPE qtype, DOM_SID *psid,
        D.isoftlimit = limit_blk2inodes(D.softlimit);
        D.ihardlimit = limit_blk2inodes(D.hardlimit);
 
-       if (psid && !NT_STATUS_IS_OK(sid_to_uid(psid, &id.uid))) {
+       if (psid && !sid_to_uid(psid, &id.uid)) {
                DEBUG(0,("sid_to_uid: failed, SID[%s]\n",
                        sid_string_static(psid)));      
        }
@@ -185,10 +185,7 @@ int vfs_get_user_ntquota_list(files_struct *fsp, SMB_NTQUOTA_LIST **qt_list)
                        continue;
                }
 
-               if (!NT_STATUS_IS_OK(uid_to_sid(&sid, usr->pw_uid))) {
-                       DEBUG(0,("uid_to_sid failed for %ld\n",(long)usr->pw_uid));
-                       continue;
-               }
+               uid_to_sid(&sid, usr->pw_uid);
 
                if (vfs_get_ntquota(fsp, SMB_USER_QUOTA_TYPE, &sid, &tmp_qt)!=0) {
                        DEBUG(5,("no quota entry for sid[%s] path[%s]\n",
index e12a24968b04981e73eead80bc0429ebac9fc4ab..417e3421cb22b8760e588ad578e0ca0f4cf6f403 100644 (file)
@@ -2309,7 +2309,7 @@ static int call_nt_transact_ioctl(connection_struct *conn, char *inbuf, char *ou
                sid_parse(pdata+4,sid_len,&sid);
                DEBUGADD(10,("for SID: %s\n",sid_string_static(&sid)));
 
-               if (!NT_STATUS_IS_OK(sid_to_uid(&sid, &uid))) {
+               if (!sid_to_uid(&sid, &uid)) {
                        DEBUG(0,("sid_to_uid: failed, sid[%s] sid_len[%lu]\n",
                                sid_string_static(&sid),(unsigned long)sid_len));
                        uid = (-1);
index 4b13e28f8e1318a1efca6453452b13c3cf176350..4f28e291cd67caca2e4ae9eccdd62aef2db75830 100644 (file)
@@ -22,6 +22,7 @@
 
 #include "includes.h"
 
+extern struct generic_mapping file_generic_mapping;
 extern struct current_user current_user;
 extern userdom_struct current_user_info;
 extern uint16 global_smbpid;
@@ -1018,15 +1019,6 @@ BOOL map_open_params_to_ntcreate(const char *fname, int deny_mode, int open_func
 
 }
 
-/* Map generic permissions to file object specific permissions */
-                                                                                                               
-struct generic_mapping file_generic_mapping = {
-       FILE_GENERIC_READ,
-       FILE_GENERIC_WRITE,
-       FILE_GENERIC_EXECUTE,
-       FILE_GENERIC_ALL
-};
-
 /****************************************************************************
  Open a file with a share mode.
 ****************************************************************************/
index 764fbe8a2e92e9e3af487c1ca6bdd0adf3b98849..e64455040090ef5f7e2b5a04b3e5ce29f1f76e91 100644 (file)
@@ -100,7 +100,7 @@ void invalidate_vuid(uint16 vuid)
        session_yield(vuser);
        SAFE_FREE(vuser->session_keystr);
 
-       free_server_info(&vuser->server_info);
+       talloc_free(vuser->server_info);
 
        data_blob_free(&vuser->session_key);
 
@@ -111,7 +111,7 @@ void invalidate_vuid(uint16 vuid)
        conn_clear_vuid_cache(vuid);
 
        SAFE_FREE(vuser->groups);
-       delete_nt_token(&vuser->nt_user_token);
+       talloc_free(vuser->nt_user_token);
        SAFE_FREE(vuser);
        num_validated_vuids--;
 }
@@ -136,9 +136,11 @@ void invalidate_all_vuids(void)
  *  @param server_info The token returned from the authentication process. 
  *   (now 'owned' by register_vuid)
  *
- *  @param session_key The User session key for the login session (now also 'owned' by register_vuid)
+ *  @param session_key The User session key for the login session (now also
+ *  'owned' by register_vuid)
  *
- *  @param respose_blob The NT challenge-response, if available.  (May be freed after this call)
+ *  @param respose_blob The NT challenge-response, if available.  (May be
+ *  freed after this call)
  *
  *  @param smb_name The untranslated name of the user
  *
@@ -147,7 +149,9 @@ void invalidate_all_vuids(void)
  *
  */
 
-int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key, DATA_BLOB response_blob, const char *smb_name)
+int register_vuid(auth_serversupplied_info *server_info,
+                 DATA_BLOB session_key, DATA_BLOB response_blob,
+                 const char *smb_name)
 {
        user_struct *vuser = NULL;
 
@@ -179,7 +183,8 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key,
                        next_vuid = VUID_OFFSET;
        }
 
-       DEBUG(10,("register_vuid: allocated vuid = %u\n", (unsigned int)next_vuid ));
+       DEBUG(10,("register_vuid: allocated vuid = %u\n",
+                 (unsigned int)next_vuid ));
 
        vuser->vuid = next_vuid;
 
@@ -203,11 +208,14 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key,
        
        vuser->n_groups = server_info->n_groups;
        if (vuser->n_groups) {
-               if (!(vuser->groups = (gid_t *)memdup(server_info->groups, sizeof(gid_t) * vuser->n_groups))) {
-                       DEBUG(0,("register_vuid: failed to memdup vuser->groups\n"));
+               if (!(vuser->groups = (gid_t *)memdup(server_info->groups,
+                                                     sizeof(gid_t) *
+                                                     vuser->n_groups))) {
+                       DEBUG(0,("register_vuid: failed to memdup "
+                                "vuser->groups\n"));
                        data_blob_free(&session_key);
                        free(vuser);
-                       free_server_info(&server_info);
+                       talloc_free(server_info);
                        return UID_FIELD_INVALID;
                }
        }
@@ -216,26 +224,35 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key,
        fstrcpy(vuser->user.unix_name, server_info->unix_name); 
 
        /* This is a potentially untrusted username */
-       alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$", sizeof(vuser->user.smb_name));
+       alpha_strcpy(vuser->user.smb_name, smb_name, ". _-$",
+                    sizeof(vuser->user.smb_name));
 
        fstrcpy(vuser->user.domain, pdb_get_domain(server_info->sam_account));
-       fstrcpy(vuser->user.full_name, pdb_get_fullname(server_info->sam_account));
+       fstrcpy(vuser->user.full_name,
+               pdb_get_fullname(server_info->sam_account));
 
        {
                /* Keep the homedir handy */
-               const char *homedir = pdb_get_homedir(server_info->sam_account);
-               const char *logon_script = pdb_get_logon_script(server_info->sam_account);
-
-               if (!IS_SAM_DEFAULT(server_info->sam_account, PDB_UNIXHOMEDIR)) {
-                       const char *unix_homedir = pdb_get_unix_homedir(server_info->sam_account);
+               const char *homedir =
+                       pdb_get_homedir(server_info->sam_account);
+               const char *logon_script =
+                       pdb_get_logon_script(server_info->sam_account);
+
+               if (!IS_SAM_DEFAULT(server_info->sam_account,
+                                   PDB_UNIXHOMEDIR)) {
+                       const char *unix_homedir =
+                               pdb_get_unix_homedir(server_info->sam_account);
                        if (unix_homedir) {
-                               vuser->unix_homedir = smb_xstrdup(unix_homedir);
+                               vuser->unix_homedir =
+                                       smb_xstrdup(unix_homedir);
                        }
                } else {
-                       struct passwd *passwd = getpwnam_alloc(vuser->user.unix_name);
+                       struct passwd *passwd =
+                               getpwnam_alloc(NULL, vuser->user.unix_name);
                        if (passwd) {
-                               vuser->unix_homedir = smb_xstrdup(passwd->pw_dir);
-                               passwd_free(&passwd);
+                               vuser->unix_homedir =
+                                       smb_xstrdup(passwd->pw_dir);
+                               talloc_free(passwd);
                        }
                }
                
@@ -252,15 +269,18 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key,
        DEBUG(10,("register_vuid: (%u,%u) %s %s %s guest=%d\n", 
                  (unsigned int)vuser->uid, 
                  (unsigned int)vuser->gid,
-                 vuser->user.unix_name, vuser->user.smb_name, vuser->user.domain, vuser->guest ));
+                 vuser->user.unix_name, vuser->user.smb_name,
+                 vuser->user.domain, vuser->guest ));
 
-       DEBUG(3, ("User name: %s\tReal name: %s\n",vuser->user.unix_name,vuser->user.full_name));       
+       DEBUG(3, ("User name: %s\tReal name: %s\n", vuser->user.unix_name,
+                 vuser->user.full_name));      
 
        if (server_info->ptok) {
-               vuser->nt_user_token = dup_nt_token(server_info->ptok);
+               vuser->nt_user_token = dup_nt_token(NULL, server_info->ptok);
        } else {
-               DEBUG(1, ("server_info does not contain a user_token - cannot continue\n"));
-               free_server_info(&server_info);
+               DEBUG(1, ("server_info does not contain a user_token - "
+                         "cannot continue\n"));
+               talloc_free(server_info);
                data_blob_free(&session_key);
                SAFE_FREE(vuser->homedir);
                SAFE_FREE(vuser->unix_homedir);
@@ -273,7 +293,8 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key,
        /* use this to keep tabs on all our info from the authentication */
        vuser->server_info = server_info;
 
-       DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",(int)vuser->uid,vuser->user.unix_name, vuser->vuid));
+       DEBUG(3,("UNIX uid %d is UNIX user %s, and will be vuid %u\n",
+                (int)vuser->uid,vuser->user.unix_name, vuser->vuid));
 
        next_vuid++;
        num_validated_vuids++;
@@ -281,7 +302,8 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key,
        DLIST_ADD(validated_users, vuser);
 
        if (!session_claim(vuser)) {
-               DEBUG(1,("Failed to claim session for vuid=%d\n", vuser->vuid));
+               DEBUG(1, ("Failed to claim session for vuid=%d\n",
+                         vuser->vuid));
                invalidate_vuid(vuser->vuid);
                return -1;
        }
@@ -301,19 +323,26 @@ int register_vuid(auth_serversupplied_info *server_info, DATA_BLOB session_key,
                int servicenumber = lp_servicenumber(vuser->user.unix_name);
 
                if ( servicenumber == -1 ) {
-                       DEBUG(3, ("Adding homes service for user '%s' using home directory: '%s'\n", 
+                       DEBUG(3, ("Adding homes service for user '%s' using "
+                                 "home directory: '%s'\n", 
                                vuser->user.unix_name, vuser->unix_homedir));
-                       vuser->homes_snum = add_home_service(vuser->user.unix_name, 
-                                               vuser->user.unix_name, vuser->unix_homedir);
+                       vuser->homes_snum =
+                               add_home_service(vuser->user.unix_name, 
+                                                vuser->user.unix_name,
+                                                vuser->unix_homedir);
                } else {
-                       DEBUG(3, ("Using static (or previously created) service for user '%s'; path = '%s'\n", 
-                               vuser->user.unix_name, lp_pathname(servicenumber) ));
+                       DEBUG(3, ("Using static (or previously created) "
+                                 "service for user '%s'; path = '%s'\n", 
+                                 vuser->user.unix_name,
+                                 lp_pathname(servicenumber) ));
                        vuser->homes_snum = servicenumber;
                }
        } 
        
-       if (srv_is_signing_negotiated() && !vuser->guest && !srv_signing_started()) {
-               /* Try and turn on server signing on the first non-guest sessionsetup. */
+       if (srv_is_signing_negotiated() && !vuser->guest &&
+           !srv_signing_started()) {
+               /* Try and turn on server signing on the first non-guest
+                * sessionsetup. */
                srv_set_signing(vuser->session_key, response_blob);
        }
        
@@ -344,14 +373,19 @@ void add_session_user(const char *user)
        if( session_userlist && in_list(suser,session_userlist,False) )
                return;
 
-       if( !session_userlist || (strlen(suser) + strlen(session_userlist) + 2 >= len_session_userlist) ) {
+       if( !session_userlist ||
+           (strlen(suser) + strlen(session_userlist) + 2 >=
+            len_session_userlist) ) {
                char *newlist;
 
                if (len_session_userlist > 128 * PSTRING_LEN) {
-                       DEBUG(3,("add_session_user: session userlist already too large.\n"));
+                       DEBUG(3,("add_session_user: session userlist already "
+                                "too large.\n"));
                        return;
                }
-               newlist = (char *)SMB_REALLOC( session_userlist, len_session_userlist + PSTRING_LEN );
+               newlist = (char *)SMB_REALLOC(
+                       session_userlist,
+                       len_session_userlist + PSTRING_LEN );
                if( newlist == NULL ) {
                        DEBUG(1,("Unable to resize session_userlist\n"));
                        return;
@@ -371,7 +405,7 @@ void add_session_user(const char *user)
  Check if a username is valid.
 ****************************************************************************/
 
-BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups)
+static BOOL user_ok(const char *user, int snum)
 {
        char **valid, **invalid;
        BOOL ret;
@@ -387,8 +421,7 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups)
                             str_list_sub_basic(invalid,
                                                current_user_info.smb_name) ) {
                                ret = !user_in_list(user,
-                                                   (const char **)invalid,
-                                                   groups, n_groups);
+                                                   (const char **)invalid);
                        }
                }
        }
@@ -402,8 +435,7 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups)
                        if ( valid &&
                             str_list_sub_basic(valid,
                                                current_user_info.smb_name) ) {
-                               ret = user_in_list(user, (const char **)valid,
-                                                  groups, n_groups);
+                               ret = user_in_list(user, (const char **)valid);
                        }
                }
        }
@@ -415,8 +447,7 @@ BOOL user_ok(const char *user,int snum, gid_t *groups, size_t n_groups)
                if (user_list &&
                    str_list_substitute(user_list, "%S",
                                        lp_servicename(snum))) {
-                       ret = user_in_list(user, (const char **)user_list,
-                                          groups, n_groups);
+                       ret = user_in_list(user, (const char **)user_list);
                }
                if (user_list) str_list_free (&user_list);
        }
@@ -436,7 +467,7 @@ static char *validate_group(char *group, DATA_BLOB password,int snum)
                setnetgrent(group);
                while (getnetgrent(&host, &user, &domain)) {
                        if (user) {
-                               if (user_ok(user, snum, NULL, 0) && 
+                               if (user_ok(user, snum) && 
                                    password_ok(user,password)) {
                                        endnetgrent();
                                        return(user);
@@ -472,12 +503,15 @@ static char *validate_group(char *group, DATA_BLOB password,int snum)
                        member = member_list;
 
                        for(i = 0; gptr->gr_mem && gptr->gr_mem[i]; i++) {
-                               size_t member_len = strlen(gptr->gr_mem[i]) + 1;
-                               if( copied_len + member_len < sizeof(pstring)) { 
+                               size_t member_len = strlen(gptr->gr_mem[i])+1;
+                               if(copied_len+member_len < sizeof(pstring)) { 
 
-                                       DEBUG(10,("validate_group: = gr_mem = %s\n", gptr->gr_mem[i]));
+                                       DEBUG(10,("validate_group: = gr_mem = "
+                                                 "%s\n", gptr->gr_mem[i]));
 
-                                       safe_strcpy(member, gptr->gr_mem[i], sizeof(pstring) - copied_len - 1);
+                                       safe_strcpy(member, gptr->gr_mem[i],
+                                                   sizeof(pstring) -
+                                                   copied_len - 1);
                                        copied_len += member_len;
                                        member += copied_len;
                                } else {
@@ -491,13 +525,14 @@ static char *validate_group(char *group, DATA_BLOB password,int snum)
                        while (*member) {
                                static fstring name;
                                fstrcpy(name,member);
-                               if (user_ok(name,snum, NULL, 0) &&
+                               if (user_ok(name,snum) &&
                                    password_ok(name,password)) {
                                        endgrent();
                                        return(&name[0]);
                                }
 
-                               DEBUG(10,("validate_group = member = %s\n", member));
+                               DEBUG(10,("validate_group = member = %s\n",
+                                         member));
 
                                member += strlen(member) + 1;
                        }
@@ -558,7 +593,7 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password,
                     auser = strtok(NULL,LIST_SEP)) {
                        fstring user2;
                        fstrcpy(user2,auser);
-                       if (!user_ok(user2,snum, NULL, 0))
+                       if (!user_ok(user2,snum))
                                continue;
                        
                        if (password_ok(user2,password)) {
@@ -595,7 +630,7 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password,
                        } else {
                                fstring user2;
                                fstrcpy(user2,auser);
-                               if (user_ok(user2,snum, NULL, 0) &&
+                               if (user_ok(user2,snum) &&
                                    password_ok(user2,password)) {
                                        ok = True;
                                        fstrcpy(user,user2);
@@ -624,7 +659,7 @@ BOOL authorise_login(int snum, fstring user, DATA_BLOB password,
                *guest = True;
        }
 
-       if (ok && !user_ok(user, snum, NULL, 0)) {
+       if (ok && !user_ok(user, snum)) {
                DEBUG(0,("authorise_login: rejected invalid user %s\n",user));
                ok = False;
        }
index 5db245ac0ced3a1878800d18bbb685e2848ed6d3..d4dd92608972b952af3815f39c86470b1f82f728 100644 (file)
@@ -925,7 +925,7 @@ static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid
 
        if (security_info_sent & OWNER_SECURITY_INFORMATION) {
                sid_copy(&owner_sid, psd->owner_sid);
-               if (!NT_STATUS_IS_OK(sid_to_uid(&owner_sid, puser))) {
+               if (!sid_to_uid(&owner_sid, puser)) {
                        if (lp_force_unknown_acl_user(snum)) {
                                /* this allows take ownership to work
                                 * reasonably */
@@ -946,7 +946,7 @@ static BOOL unpack_nt_owners(int snum, SMB_STRUCT_STAT *psbuf, uid_t *puser, gid
 
        if (security_info_sent & GROUP_SECURITY_INFORMATION) {
                sid_copy(&grp_sid, psd->grp_sid);
-               if (!NT_STATUS_IS_OK(sid_to_gid( &grp_sid, pgrp))) {
+               if (!sid_to_gid( &grp_sid, pgrp)) {
                        if (lp_force_unknown_acl_user(snum)) {
                                /* this allows take group ownership to work
                                 * reasonably */
@@ -1035,7 +1035,7 @@ static BOOL uid_entry_in_group( canon_ace *uid_ace, canon_ace *group_ace )
         * not uids/gids.
         */
 
-       return user_in_group_list(u_name, g_name, NULL, 0);
+       return user_in_group(u_name, g_name);
 }
 
 /****************************************************************************
@@ -1390,10 +1390,10 @@ static BOOL create_canon_ace_lists(files_struct *fsp, SMB_STRUCT_STAT *pst,
                        if (nt4_compatible_acls())
                                psa->flags |= SEC_ACE_FLAG_INHERIT_ONLY;
 
-               } else if (NT_STATUS_IS_OK(sid_to_uid( &current_ace->trustee, &current_ace->unix_ug.uid))) {
+               } else if (sid_to_uid( &current_ace->trustee, &current_ace->unix_ug.uid)) {
                        current_ace->owner_type = UID_ACE;
                        current_ace->type = SMB_ACL_USER;
-               } else if (NT_STATUS_IS_OK(sid_to_gid( &current_ace->trustee, &current_ace->unix_ug.gid))) {
+               } else if (sid_to_gid( &current_ace->trustee, &current_ace->unix_ug.gid)) {
                        current_ace->owner_type = GID_ACE;
                        current_ace->type = SMB_ACL_GROUP;
                } else {
index 0b7b94cce21152193c438178802701bfbff0995e..d646ebe02db1a64ea79ed43f5a73e0bb7011432f 100644 (file)
@@ -223,115 +223,6 @@ BOOL push_deferred_smb_message(uint16 mid,
                                   private_data, priv_len);
 }
 
-static struct timed_event *timed_events;
-
-struct timed_event {
-       struct timed_event *next, *prev;
-       struct timeval when;
-       const char *event_name;
-       void (*handler)(struct timed_event *te,
-                       const struct timeval *now,
-                       void *private_data);
-       void *private_data;
-};
-
-static int timed_event_destructor(void *p)
-{
-       struct timed_event *te = talloc_get_type_abort(p, struct timed_event);
-       DEBUG(10, ("Destroying timed event %lx \"%s\"\n", (unsigned long)te,
-                  te->event_name));
-       DLIST_REMOVE(timed_events, te);
-       return 0;
-}
-
-/****************************************************************************
- Schedule a function for future calling, cancel with talloc_free().
- It's the responsibility of the handler to call talloc_free() on the event 
- handed to it.
-****************************************************************************/
-
-struct timed_event *add_timed_event(TALLOC_CTX *mem_ctx,
-                                   struct timeval when,
-                                   const char *event_name,
-                                   void (*handler)(struct timed_event *te,
-                                                   const struct timeval *now,
-                                                   void *private_data),
-                                   void *private_data)
-{
-       struct timed_event *te, *last_te, *cur_te;
-
-       te = TALLOC_P(mem_ctx, struct timed_event);
-       if (te == NULL) {
-               DEBUG(0, ("talloc failed\n"));
-               return NULL;
-       }
-
-       te->when = when;
-       te->event_name = event_name;
-       te->handler = handler;
-       te->private_data = private_data;
-
-       /* keep the list ordered */
-       last_te = NULL;
-       for (cur_te = timed_events; cur_te; cur_te = cur_te->next) {
-               /* if the new event comes before the current one break */
-               if (!timeval_is_zero(&cur_te->when) &&
-                   timeval_compare(&te->when, &cur_te->when) < 0) {
-                       break;
-               }
-               last_te = cur_te;
-       }
-
-       DLIST_ADD_AFTER(timed_events, te, last_te);
-       talloc_set_destructor(te, timed_event_destructor);
-
-       DEBUG(10, ("Added timed event \"%s\": %lx\n", event_name,
-                  (unsigned long)te));
-       return te;
-}
-
-static void run_events(void)
-{
-       struct timeval now;
-
-       if (timed_events == NULL) {
-               /* No syscall if there are no events */
-               DEBUG(10, ("run_events: No events\n"));
-               return;
-       }
-
-       GetTimeOfDay(&now);
-
-       if (timeval_compare(&now, &timed_events->when) < 0) {
-               /* Nothing to do yet */
-               DEBUG(10, ("run_events: Nothing to do\n"));
-               return;
-       }
-
-       DEBUG(10, ("Running event \"%s\" %lx\n", timed_events->event_name,
-                  (unsigned long)timed_events));
-
-       timed_events->handler(timed_events, &now, timed_events->private_data);
-       return;
-}
-
-struct timeval timed_events_timeout(void)
-{
-       struct timeval now, timeout;
-
-       if (timed_events == NULL) {
-               return timeval_set(SMBD_SELECT_TIMEOUT, 0);
-       }
-
-       now = timeval_current();
-       timeout = timeval_until(&now, &timed_events->when);
-
-       DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)timeout.tv_sec,
-                  (int)timeout.tv_usec));
-
-       return timeout;
-}
-
 struct idle_event {
        struct timed_event *te;
        struct timeval interval;
@@ -537,8 +428,10 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout)
        }
 
        {
-               struct timeval tmp = timed_events_timeout();
-               to = timeval_min(&to, &tmp);
+               struct timeval tmp;
+               struct timeval *tp = get_timed_events_timeout(&tmp,SMBD_SELECT_TIMEOUT);
+
+               to = timeval_min(&to, tp);
                if (timeval_is_zero(&to)) {
                        return True;
                }
index fc6a8589747e65f6727422942684222d5b79ca06..ebc47c51d9d07c5271dedf342d4b46dc842c3e9b 100644 (file)
@@ -129,7 +129,7 @@ static void gain_root(void)
  Get the list of current groups.
 ****************************************************************************/
 
-int get_current_groups(gid_t gid, int *p_ngroups, gid_t **p_groups)
+static int get_current_groups(gid_t gid, int *p_ngroups, gid_t **p_groups)
 {
        int i;
        gid_t grp;
@@ -179,51 +179,6 @@ fail:
        return -1;
 }
 
-/****************************************************************************
- Initialize the groups a user belongs to.
-****************************************************************************/
-
-BOOL initialise_groups(char *user, uid_t uid, gid_t gid)
-{
-       struct sec_ctx *prev_ctx_p;
-       BOOL result = True;
-
-       if (non_root_mode()) {
-               return True;
-       }
-
-       become_root();
-
-       /* Call initgroups() to get user groups */
-
-       if (winbind_initgroups(user,gid) == -1) {
-               DEBUG(0,("Unable to initgroups. Error was %s\n", strerror(errno) ));
-               if (getuid() == 0) {
-                       if (gid < 0 || gid > 32767 || uid < 0 || uid > 32767) {
-                               DEBUG(0,("This is probably a problem with the account %s\n", user));
-                       }
-               }
-               result = False;
-               goto done;
-       }
-
-       /* Store groups in previous user's security context.  This will
-          always work as the become_root() call increments the stack
-          pointer. */
-
-       prev_ctx_p = &sec_ctx_stack[sec_ctx_stack_ndx - 1];
-
-       SAFE_FREE(prev_ctx_p->ut.groups);
-       prev_ctx_p->ut.ngroups = 0;
-
-       get_current_groups(gid, &prev_ctx_p->ut.ngroups, &prev_ctx_p->ut.groups);
-
- done:
-       unbecome_root();
-
-       return result;
-}
-
 /****************************************************************************
  Create a new security context on the stack.  It is the same as the old
  one.  User changes are done using the set_sec_ctx() function.
@@ -252,14 +207,15 @@ BOOL push_sec_ctx(void)
        DEBUG(3, ("push_sec_ctx(%u, %u) : sec_ctx_stack_ndx = %d\n", 
                  (unsigned int)ctx_p->ut.uid, (unsigned int)ctx_p->ut.gid, sec_ctx_stack_ndx ));
 
-       ctx_p->token = dup_nt_token(sec_ctx_stack[sec_ctx_stack_ndx-1].token);
+       ctx_p->token = dup_nt_token(NULL,
+                                   sec_ctx_stack[sec_ctx_stack_ndx-1].token);
 
        ctx_p->ut.ngroups = sys_getgroups(0, NULL);
 
        if (ctx_p->ut.ngroups != 0) {
                if (!(ctx_p->ut.groups = SMB_MALLOC_ARRAY(gid_t, ctx_p->ut.ngroups))) {
                        DEBUG(0, ("Out of memory in push_sec_ctx()\n"));
-                       delete_nt_token(&ctx_p->token);
+                       talloc_free(ctx_p->token);
                        return False;
                }
 
@@ -299,10 +255,10 @@ void set_sec_ctx(uid_t uid, gid_t gid, int ngroups, gid_t *groups, NT_USER_TOKEN
        if (token && (token == ctx_p->token))
                smb_panic("DUPLICATE_TOKEN");
 
-       delete_nt_token(&ctx_p->token);
+       talloc_free(ctx_p->token);
        
        ctx_p->ut.groups = memdup(groups, sizeof(gid_t) * ngroups);
-       ctx_p->token = dup_nt_token(token);
+       ctx_p->token = dup_nt_token(NULL, token);
 
        become_id(uid, gid);
 
@@ -355,7 +311,7 @@ BOOL pop_sec_ctx(void)
        SAFE_FREE(ctx_p->ut.groups);
        ctx_p->ut.ngroups = 0;
 
-       delete_nt_token(&ctx_p->token);
+       talloc_free(ctx_p->token);
 
        /* Pop back previous user */
 
index 3e970ec16c2a8d5213836a43241ec15e39b7e362..6c2034988a7f9bab7b851cedcf270626c61a669d 100644 (file)
@@ -62,6 +62,18 @@ static void smbd_set_server_fd(int fd)
        client_setfd(fd);
 }
 
+/*******************************************************************
+ What to do when smb.conf is updated.
+ ********************************************************************/
+
+static void smb_conf_updated(int msg_type, struct process_id src,
+                            void *buf, size_t len)
+{
+       DEBUG(10,("smb_conf_updated: Got message saying smb.conf was updated. Reloading.\n"));
+       reload_services(False);
+}
+
+
 /****************************************************************************
  Terminate signal.
 ****************************************************************************/
@@ -331,6 +343,7 @@ static BOOL open_sockets_smbd(BOOL is_daemon, BOOL interactive, const char *smb_
         message_register(MSG_SMB_SAM_REPL, msg_sam_repl);
         message_register(MSG_SHUTDOWN, msg_exit_server);
         message_register(MSG_SMB_FILE_RENAME, msg_file_was_renamed);
+       message_register(MSG_SMB_CONF_UPDATED, smb_conf_updated); 
 
        /* now accept incoming connections - forking a new process
           for each incoming connection */
@@ -697,6 +710,7 @@ void build_options(BOOL screen);
 
  int main(int argc,const char *argv[])
 {
+       extern BOOL in_server;
        /* shall I run as a daemon */
        static BOOL is_daemon = False;
        static BOOL interactive = False;
@@ -718,6 +732,8 @@ void build_options(BOOL screen);
        { NULL }
        };
 
+       in_server = True;
+
        load_case_tables();
 
 #ifdef HAVE_SET_AUTH_PARAMETERS
@@ -826,11 +842,6 @@ void build_options(BOOL screen);
 
        init_structs();
 
-       if (!init_guest_info()) {
-               DEBUG(0,("ERROR: failed to setup guest info.\n"));
-               return -1;
-       }
-
 #ifdef WITH_PROFILE
        if (!profile_setup(False)) {
                DEBUG(0,("ERROR: failed to setup profiling\n"));
@@ -885,9 +896,6 @@ void build_options(BOOL screen);
        if (!locking_init(0))
                exit(1);
 
-       if (!share_info_db_init())
-               exit(1);
-
        namecache_enable();
 
        if (!init_registry())
@@ -901,6 +909,11 @@ void build_options(BOOL screen);
        if (!print_backend_init())
                exit(1);
 
+       if (!init_guest_info()) {
+               DEBUG(0,("ERROR: failed to setup guest info.\n"));
+               return -1;
+       }
+
        /* Setup the main smbd so that we can get messages. */
        /* don't worry about general printing messages here */
 
index 7640559d538a2ef0d4cd050d4f18ea56a9f815fb..cf0116cc091fbc1a449937adee7dcab947258544 100644 (file)
@@ -299,6 +299,13 @@ int find_service(fstring service)
                }
        }
 
+       /* Is it a usershare service ? */
+       if (iService < 0 && *lp_usershare_path()) {
+               /* Ensure the name is canonicalized. */
+               strlower_m(service);
+               iService = load_usershare_service(service);
+       }
+
        if (iService >= 0) {
                if (!VALID_SNUM(iService)) {
                        DEBUG(0,("Invalid snum %d for %s\n",iService, service));
@@ -359,6 +366,131 @@ static NTSTATUS share_sanity_checks(int snum, fstring dev)
        return NT_STATUS_OK;
 }
 
+static NTSTATUS find_forced_user(int snum, BOOL vuser_is_guest,
+                                uid_t *uid, gid_t *gid, fstring username,
+                                struct nt_user_token **token)
+{
+       TALLOC_CTX *mem_ctx;
+       char *fuser, *found_username;
+       NTSTATUS result;
+
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       fuser = talloc_string_sub(mem_ctx, lp_force_user(snum), "%S",
+                                 lp_servicename(snum));
+       if (fuser == NULL) {
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+
+       result = create_token_from_username(mem_ctx, fuser, vuser_is_guest,
+                                           uid, gid, &found_username,
+                                           token);
+       if (!NT_STATUS_IS_OK(result)) {
+               goto done;
+       }
+
+       talloc_steal(NULL, *token);
+       fstrcpy(username, found_username);
+
+       result = NT_STATUS_OK;
+ done:
+       talloc_free(mem_ctx);
+       return result;
+}
+
+/*
+ * Go through lookup_name etc to find the force'd group.  
+ *
+ * Create a new token from src_token, replacing the primary group sid with the
+ * one found.
+ */
+
+static NTSTATUS find_forced_group(BOOL force_user,
+                                 int snum, const char *username,
+                                 DOM_SID *pgroup_sid,
+                                 gid_t *pgid)
+{
+       NTSTATUS result = NT_STATUS_NO_SUCH_GROUP;
+       TALLOC_CTX *mem_ctx;
+       DOM_SID group_sid;
+       enum SID_NAME_USE type;
+       char *groupname;
+       BOOL user_must_be_member = False;
+       gid_t gid;
+
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               DEBUG(0, ("talloc_new failed\n"));
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       groupname = talloc_strdup(mem_ctx, lp_force_group(snum));
+       if (groupname == NULL) {
+               DEBUG(1, ("talloc_strdup failed\n"));
+               result = NT_STATUS_NO_MEMORY;
+               goto done;
+       }
+
+       if (groupname[0] == '+') {
+               user_must_be_member = True;
+               groupname += 1;
+       }
+
+       groupname = talloc_string_sub(mem_ctx, groupname,
+                                     "%S", lp_servicename(snum));
+
+       if (!lookup_name(mem_ctx, groupname,
+                        LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
+                        NULL, NULL, &group_sid, &type)) {
+               DEBUG(10, ("lookup_name(%s) failed\n",
+                          groupname));
+               goto done;
+       }
+
+       if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
+           (type != SID_NAME_WKN_GRP)) {
+               DEBUG(10, ("%s is a %s, not a group\n", groupname,
+                          sid_type_lookup(type)));
+               goto done;
+       }
+
+       if (!sid_to_gid(&group_sid, &gid)) {
+               DEBUG(10, ("sid_to_gid(%s) for %s failed\n",
+                          sid_string_static(&group_sid), groupname));
+               goto done;
+       }
+
+       /*
+        * If the user has been forced and the forced group starts with a '+',
+        * then we only set the group to be the forced group if the forced
+        * user is a member of that group.  Otherwise, the meaning of the '+'
+        * would be ignored.
+        */
+
+       if (force_user && user_must_be_member) {
+               if (user_in_group(username, groupname)) {
+                       sid_copy(pgroup_sid, &group_sid);
+                       *pgid = gid;
+                       DEBUG(3,("Forced group %s for member %s\n",
+                                groupname, username));
+               }
+       } else {
+               sid_copy(pgroup_sid, &group_sid);
+               *pgid = gid;
+               DEBUG(3,("Forced group %s\n", groupname));
+       }
+
+       result = NT_STATUS_OK;
+ done:
+       talloc_free(mem_ctx);
+       return result;
+}
+
 /****************************************************************************
   Make a connection, given the snum to connect to, and the vuser of the
   connecting user if appropriate.
@@ -395,7 +527,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
        if (lp_guest_only(snum)) {
                const char *guestname = lp_guestaccount();
                guest = True;
-               pass = getpwnam_alloc(guestname);
+               pass = getpwnam_alloc(NULL, guestname);
                if (!pass) {
                        DEBUG(0,("make_connection_snum: Invalid guest "
                                 "account %s??\n",guestname));
@@ -408,7 +540,7 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                conn->uid = pass->pw_uid;
                conn->gid = pass->pw_gid;
                string_set(&conn->user,pass->pw_name);
-               passwd_free(&pass);
+               talloc_free(pass);
                DEBUG(3,("Guest only user %s\n",user));
        } else if (vuser) {
                if (vuser->guest) {
@@ -421,8 +553,8 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                                      return NULL;
                        }
                } else {
-                       if (!user_ok(vuser->user.unix_name, snum,
-                                    vuser->groups, vuser->n_groups)) {
+                       if (!user_ok_token(vuser->user.unix_name,
+                                          vuser->nt_user_token, snum)) {
                                DEBUG(2, ("user '%s' (from session setup) not "
                                          "permitted to access this share "
                                          "(%s)\n", vuser->user.unix_name,
@@ -501,86 +633,98 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
        conn->admin_user = False;
 
        /*
-        * If force user is true, then store the
-        * given userid and also the groups
-        * of the user we're forcing.
+        * If force user is true, then store the given userid and the gid of
+        * the user we're forcing.
+        * For auxiliary groups see below.
         */
        
        if (*lp_force_user(snum)) {
-               struct passwd *pass2;
-               pstring fuser;
-               pstrcpy(fuser,lp_force_user(snum));
-
-               /* Allow %S to be used by force user. */
-               pstring_sub(fuser,"%S",lp_servicename(snum));
-
-               pass2 = (struct passwd *)Get_Pwnam(fuser);
-               if (pass2) {
-                       conn->uid = pass2->pw_uid;
-                       conn->gid = pass2->pw_gid;
-                       string_set(&conn->user,pass2->pw_name);
-                       fstrcpy(user,pass2->pw_name);
-                       conn->force_user = True;
-                       DEBUG(3,("Forced user %s\n",user));       
-               } else {
-                       DEBUG(1,("Couldn't find user %s\n",fuser));
+               NTSTATUS status2;
+
+               status2 = find_forced_user(snum,
+                                          (vuser != NULL) && vuser->guest,
+                                          &conn->uid, &conn->gid, user,
+                                          &conn->nt_user_token);
+               if (!NT_STATUS_IS_OK(status2)) {
                        conn_free(conn);
-                       *status = NT_STATUS_NO_SUCH_USER;
+                       *status = status2;
                        return NULL;
                }
+               string_set(&conn->user,user);
+               conn->force_user = True;
+               DEBUG(3,("Forced user %s\n",user));       
        }
 
-#ifdef HAVE_GETGRNAM 
        /*
         * If force group is true, then override
         * any groupid stored for the connecting user.
         */
        
        if (*lp_force_group(snum)) {
-               gid_t gid;
-               pstring gname;
-               pstring tmp_gname;
-               BOOL user_must_be_member = False;
-               
-               pstrcpy(tmp_gname,lp_force_group(snum));
-               
-               if (tmp_gname[0] == '+') {
-                       user_must_be_member = True;
-                       /* even now, tmp_gname is null terminated */
-                       pstrcpy(gname,&tmp_gname[1]);
-               } else {
-                       pstrcpy(gname,tmp_gname);
-               }
-               /* default service may be a group name          */
-               pstring_sub(gname,"%S",lp_servicename(snum));
-               gid = nametogid(gname);
-               
-               if (gid == (gid_t)-1) {
-                       DEBUG(1,("Couldn't find group %s\n",gname));
+               NTSTATUS status2;
+               DOM_SID group_sid;
+
+               status2 = find_forced_group(conn->force_user,
+                                           snum, user,
+                                           &group_sid, &conn->gid);
+               if (!NT_STATUS_IS_OK(status2)) {
                        conn_free(conn);
-                       *status = NT_STATUS_NO_SUCH_GROUP;
+                       *status = status2;
                        return NULL;
                }
 
-               /*
-                * If the user has been forced and the forced group starts
-                * with a '+', then we only set the group to be the forced
-                * group if the forced user is a member of that group.
-                * Otherwise, the meaning of the '+' would be ignored.
-                */
-               if (conn->force_user && user_must_be_member) {
-                       if (user_in_group_list( user, gname, NULL, 0)) {
-                               conn->gid = gid;
-                               DEBUG(3,("Forced group %s for member %s\n",
-                                        gname,user));
+               if ((conn->nt_user_token == NULL) && (vuser != NULL)) {
+
+                       /* Not force user and not security=share, but force
+                        * group. vuser has a token to copy */
+                       
+                       conn->nt_user_token = dup_nt_token(
+                               NULL, vuser->nt_user_token);
+                       if (conn->nt_user_token == NULL) {
+                               DEBUG(0, ("dup_nt_token failed\n"));
+                               conn_free(conn);
+                               *status = NT_STATUS_NO_MEMORY;
+                               return NULL;
                        }
-               } else {
-                       conn->gid = gid;
-                       DEBUG(3,("Forced group %s\n",gname));
+               }
+
+               /* If conn->nt_user_token is still NULL, we have
+                * security=share. This means ignore the SID, as we had no
+                * vuser to copy from */
+
+               if (conn->nt_user_token != NULL) {
+                       /* Overwrite the primary group sid */
+                       sid_copy(&conn->nt_user_token->user_sids[1],
+                                &group_sid);
+
                }
                conn->force_group = True;
        }
-#endif /* HAVE_GETGRNAM */
+
+       if (conn->nt_user_token != NULL) {
+               size_t i;
+
+               /* We have a share-specific token from force [user|group].
+                * This means we have to create the list of unix groups from
+                * the list of sids. */
+
+               conn->ngroups = 0;
+               conn->groups = NULL;
+
+               for (i=0; i<conn->nt_user_token->num_sids; i++) {
+                       gid_t gid;
+                       DOM_SID *sid = &conn->nt_user_token->user_sids[i];
+
+                       if (!sid_to_gid(sid, &gid)) {
+                               DEBUG(10, ("Could not convert SID %s to gid, "
+                                          "ignoring it\n",
+                                          sid_string_static(sid)));
+                               continue;
+                       }
+                       add_gid_to_array_unique(NULL, gid, &conn->groups,
+                                               &conn->ngroups);
+               }
+       }
 
        {
                pstring s;
@@ -591,25 +735,6 @@ static connection_struct *make_connection_snum(int snum, user_struct *vuser,
                         lp_servicename(snum)));
        }
 
-       if (conn->force_user || conn->force_group) {
-               int ngroups = 0;
-
-               /* groups stuff added by ih */
-               conn->ngroups = 0;
-               conn->groups = NULL;
-               
-               /* Find all the groups this uid is in and
-                  store them. Used by change_to_user() */
-               initialise_groups(conn->user, conn->uid, conn->gid); 
-               get_current_groups(conn->gid, &ngroups, &conn->groups);
-               conn->ngroups = ngroups;
-               
-               conn->nt_user_token =
-                       create_nt_token(conn->uid, conn->gid,
-                                       conn->ngroups, conn->groups,
-                                       guest);
-       }
-
        /*
         * New code to check if there's a share security descripter
         * added from NT server manager. This is done after the
index a22a575c762ccabe3127db4cd45cd8c0b4490df5..38e16126e2135d62f89be88f46a8d42ca75f3a03 100644 (file)
@@ -267,7 +267,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
 
        map_username( user );
 
-       pw = smb_getpwnam( user, real_username, True );
+       pw = smb_getpwnam( mem_ctx, user, real_username, True );
        if (!pw) {
 
                /* this was originally the behavior of Samba 2.2, if a user
@@ -277,7 +277,7 @@ static int reply_spnego_kerberos(connection_struct *conn,
                if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_UID){ 
                        map_domainuser_to_guest = True;
                        fstrcpy(user,lp_guestaccount());
-                       pw = smb_getpwnam( user, real_username, True );
+                       pw = smb_getpwnam( mem_ctx, user, real_username, True );
                } 
 
                /* extra sanity check that the guest account is valid */
@@ -302,11 +302,11 @@ static int reply_spnego_kerberos(connection_struct *conn,
                ret = make_server_info_pac(&server_info, real_username, pw, logon_info);
 
                if ( !NT_STATUS_IS_OK(ret) ) {
-                       DEBUG(1,("make_server_info_pac failed!\n"));
+                       DEBUG(1,("make_server_info_pac failed: %s!\n",
+                                nt_errstr(ret)));
                        SAFE_FREE(client);
                        data_blob_free(&ap_rep);
                        data_blob_free(&session_key);
-                       passwd_free(&pw);
                        talloc_destroy(mem_ctx);
                        return ERROR_NT(ret);
                }
@@ -315,26 +315,24 @@ static int reply_spnego_kerberos(connection_struct *conn,
                ret = make_server_info_pw(&server_info, real_username, pw);
 
                if ( !NT_STATUS_IS_OK(ret) ) {
-                       DEBUG(1,("make_server_info_from_pw failed!\n"));
+                       DEBUG(1,("make_server_info_pw failed: %s!\n",
+                                nt_errstr(ret)));
                        SAFE_FREE(client);
                        data_blob_free(&ap_rep);
                        data_blob_free(&session_key);
-                       passwd_free(&pw);
                        talloc_destroy(mem_ctx);
                        return ERROR_NT(ret);
                }
 
-               /* make_server_info_pw does not set the domain. Without this we end up
-                * with the local netbios name in substitutions for %D. */
+               /* make_server_info_pw does not set the domain. Without this
+                * we end up with the local netbios name in substitutions for
+                * %D. */
 
                if (server_info->sam_account != NULL) {
                        pdb_set_domain(server_info->sam_account, domain, PDB_SET);
                }
        }
 
-
-       passwd_free(&pw);
-
        /* register_vuid keeps the server info */
        /* register_vuid takes ownership of session_key, no need to free after this.
           A better interface would copy it.... */
@@ -1063,6 +1061,16 @@ int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,
                return ERROR_NT(nt_status_squash(nt_status));
        }
 
+       nt_status = create_local_token(server_info);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               DEBUG(10, ("create_local_token failed: %s\n",
+                          nt_errstr(nt_status)));
+               data_blob_free(&nt_resp);
+               data_blob_free(&lm_resp);
+               data_blob_clear_free(&plaintext_password);
+               return ERROR_NT(nt_status_squash(nt_status));
+       }
+
        if (server_info->user_session_key.data) {
                session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length);
        } else {
diff --git a/source3/smbd/share_access.c b/source3/smbd/share_access.c
new file mode 100644 (file)
index 0000000..11e52b0
--- /dev/null
@@ -0,0 +1,264 @@
+/* 
+   Unix SMB/CIFS implementation.
+   Check access based on valid users, read list and friends
+   Copyright (C) Volker Lendecke 2005
+   
+   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"
+
+/*
+ * No prefix means direct username
+ * @name means netgroup first, then unix group
+ * &name means netgroup
+ * +name means unix group
+ * + and & may be combined
+ */
+
+static BOOL do_group_checks(const char **name, const char **pattern)
+{
+       if ((*name)[0] == '@') {
+               *pattern = "&+";
+               *name += 1;
+               return True;
+       }
+
+       if (((*name)[0] == '+') && ((*name)[1] == '&')) {
+               *pattern = "+&";
+               *name += 2;
+               return True;
+       }
+
+       if ((*name)[0] == '+') {
+               *pattern = "+";
+               *name += 1;
+               return True;
+       }
+
+       if (((*name)[0] == '&') && ((*name)[1] == '+')) {
+               *pattern = "&+";
+               *name += 2;
+               return True;
+       }
+
+       if ((*name)[0] == '&') {
+               *pattern = "&";
+               *name += 1;
+               return True;
+       }
+
+       return False;
+}
+
+static BOOL token_contains_name(TALLOC_CTX *mem_ctx,
+                               const char *username,
+                               const char *sharename,
+                               const struct nt_user_token *token,
+                               const char *name)
+{
+       const char *prefix;
+       DOM_SID sid;
+       enum SID_NAME_USE type;
+
+       if (username != NULL) {
+               name = talloc_sub_basic(mem_ctx, username, name);
+       }
+       if (sharename != NULL) {
+               name = talloc_string_sub(mem_ctx, name, "%S", sharename);
+       }
+
+       if (name == NULL) {
+               /* This is too security sensitive, better panic than return a
+                * result that might be interpreted in a wrong way. */
+               smb_panic("substitutions failed\n");
+       }
+
+       if (!do_group_checks(&name, &prefix)) {
+               if (!lookup_name(mem_ctx, name, LOOKUP_NAME_ALL,
+                                NULL, NULL, &sid, &type)) {
+                       DEBUG(5, ("lookup_name %s failed\n", name));
+                       return False;
+               }
+               if (type != SID_NAME_USER) {
+                       DEBUG(5, ("%s is a %s, expected a user\n",
+                                 name, sid_type_lookup(type)));
+                       return False;
+               }
+               return nt_token_check_sid(&sid, token);
+       }
+
+       for (/* initialized above */ ; *prefix != '\0'; prefix++) {
+               if (*prefix == '+') {
+                       if (!lookup_name(mem_ctx, name,
+                                        LOOKUP_NAME_ALL|LOOKUP_NAME_GROUP,
+                                        NULL, NULL, &sid, &type)) {
+                               DEBUG(5, ("lookup_name %s failed\n", name));
+                               return False;
+                       }
+                       if ((type != SID_NAME_DOM_GRP) &&
+                           (type != SID_NAME_ALIAS) &&
+                           (type != SID_NAME_WKN_GRP)) {
+                               DEBUG(5, ("%s is a %s, expected a group\n",
+                                         name, sid_type_lookup(type)));
+                               return False;
+                       }
+                       if (nt_token_check_sid(&sid, token)) {
+                               return True;
+                       }
+                       continue;
+               }
+               if (*prefix == '&') {
+                       if (user_in_netgroup(username, name)) {
+                               return True;
+                       }
+                       continue;
+               }
+               smb_panic("got invalid prefix from do_groups_check\n");
+       }
+       return False;
+}
+
+/*
+ * Check whether a user is contained in the list provided.
+ *
+ * Please note that the user name and share names passed in here mainly for
+ * the substitution routines that expand the parameter values, the decision
+ * whether a user is in the list is done after a lookup_name on the expanded
+ * parameter value, solely based on comparing the SIDs in token.
+ *
+ * The other use is the netgroup check when using @group or &group.
+ */
+
+BOOL token_contains_name_in_list(const char *username,
+                                const char *sharename,
+                                const struct nt_user_token *token,
+                                const char **list)
+{
+       TALLOC_CTX *mem_ctx;
+
+       if (list == NULL) {
+               return False;
+       }
+
+       mem_ctx = talloc_new(NULL);
+       if (mem_ctx == NULL) {
+               smb_panic("talloc_new failed\n");
+       }
+
+       while (*list != NULL) {
+               if (token_contains_name(mem_ctx, username, sharename,
+                                       token, *list)) {
+                       talloc_free(mem_ctx);
+                       return True;
+               }
+               list += 1;
+       }
+
+       talloc_free(mem_ctx);
+       return False;
+}
+
+/*
+ * Check whether the user described by "token" has access to share snum.
+ *
+ * This looks at "invalid users", "valid users" and "only user/username"
+ *
+ * Please note that the user name and share names passed in here mainly for
+ * the substitution routines that expand the parameter values, the decision
+ * whether a user is in the list is done after a lookup_name on the expanded
+ * parameter value, solely based on comparing the SIDs in token.
+ *
+ * The other use is the netgroup check when using @group or &group.
+ */
+
+BOOL user_ok_token(const char *username, struct nt_user_token *token, int snum)
+{
+       if (lp_invalid_users(snum) != NULL) {
+               if (token_contains_name_in_list(username, lp_servicename(snum),
+                                               token,
+                                               lp_invalid_users(snum))) {
+                       DEBUG(10, ("User %s in 'invalid users'\n", username));
+                       return False;
+               }
+       }
+
+       if (lp_valid_users(snum) != NULL) {
+               if (!token_contains_name_in_list(username,
+                                                lp_servicename(snum), token,
+                                                lp_valid_users(snum))) {
+                       DEBUG(10, ("User %s no in 'valid users'\n", username));
+                       return False;
+               }
+       }
+
+       if (lp_onlyuser(snum)) {
+               const char *list[2];
+               list[0] = lp_username(snum);
+               list[1] = NULL;
+               if (!token_contains_name_in_list(NULL, lp_servicename(snum),
+                                                token, list)) {
+                       DEBUG(10, ("%s != 'username'\n", username));
+                       return False;
+               }
+       }
+
+       DEBUG(10, ("user_ok_token: share %s is ok for unix user %s\n",
+                  lp_servicename(snum), username));
+
+       return True;
+}
+
+/*
+ * Check whether the user described by "token" is restricted to read-only
+ * access on share snum.
+ *
+ * This looks at "invalid users", "valid users" and "only user/username"
+ *
+ * Please note that the user name and share names passed in here mainly for
+ * the substitution routines that expand the parameter values, the decision
+ * whether a user is in the list is done after a lookup_name on the expanded
+ * parameter value, solely based on comparing the SIDs in token.
+ *
+ * The other use is the netgroup check when using @group or &group.
+ */
+
+BOOL is_share_read_only_for_token(const char *username,
+                                 struct nt_user_token *token, int snum)
+{
+       BOOL result = lp_readonly(snum);
+
+       if (lp_readlist(snum) != NULL) {
+               if (token_contains_name_in_list(username,
+                                               lp_servicename(snum), token,
+                                               lp_readlist(snum))) {
+                       result = True;
+               }
+       }
+
+       if (lp_writelist(snum) != NULL) {
+               if (token_contains_name_in_list(username,
+                                               lp_servicename(snum), token,
+                                               lp_writelist(snum))) {
+                       result = False;
+               }
+       }
+
+       DEBUG(10,("is_share_read_only_for_user: share %s is %s for unix user "
+                 "%s\n", lp_servicename(snum),
+                 result ? "read-only" : "read-write", username));
+
+       return result;
+}
index d419720c33e6f91f2c4dae014fd927617f9f5f85..6e516d35628bfc3705c028f2bfed14aded539328 100644 (file)
@@ -56,7 +56,7 @@ BOOL change_to_guest(void)
 
        if (!pass) {
                /* Don't need to free() this as its stored in a static */
-               pass = getpwnam_alloc(lp_guestaccount());
+               pass = getpwnam_alloc(NULL, lp_guestaccount());
                if (!pass)
                        return(False);
        }
@@ -71,67 +71,13 @@ BOOL change_to_guest(void)
        
        current_user.conn = NULL;
        current_user.vuid = UID_FIELD_INVALID;
-       
-       passwd_free(&pass);
 
+       talloc_free(pass);
+       pass = NULL;
+       
        return True;
 }
 
-/****************************************************************************
- Readonly share for this user ?
-****************************************************************************/
-
-static BOOL is_share_read_only_for_user(int snum, user_struct *vuser)
-{
-       char **list;
-       const char *service = lp_servicename(snum);
-       BOOL read_only_ret = lp_readonly(snum);
-
-       if (!service)
-               return read_only_ret;
-
-       str_list_copy(&list, lp_readlist(snum));
-       if (list) {
-               if (!str_list_sub_basic(list, vuser->user.smb_name) ) {
-                       DEBUG(0, ("is_share_read_only_for_user: ERROR: read "
-                                 "list substitution failed\n"));
-               }
-               if (!str_list_substitute(list, "%S", service)) {
-                       DEBUG(0, ("is_share_read_only_for_user: ERROR: read "
-                                 "list service substitution failed\n"));
-               }
-               if (user_in_list(vuser->user.unix_name, (const char **)list,
-                                vuser->groups, vuser->n_groups)) {
-                       read_only_ret = True;
-               }
-               str_list_free(&list);
-       }
-
-       str_list_copy(&list, lp_writelist(snum));
-       if (list) {
-               if (!str_list_sub_basic(list, vuser->user.smb_name) ) {
-                       DEBUG(0, ("is_share_read_only_for_user: ERROR: write "
-                                 "list substitution failed\n"));
-               }
-               if (!str_list_substitute(list, "%S", service)) {
-                       DEBUG(0, ("is_share_read_only_for_user: ERROR: write "
-                                 "list service substitution failed\n"));
-               }
-               if (user_in_list(vuser->user.unix_name, (const char **)list,
-                                vuser->groups, vuser->n_groups)) {
-                       read_only_ret = False;
-               }
-               str_list_free(&list);
-       }
-
-       DEBUG(10,("is_share_read_only_for_user: share %s is %s for unix user "
-                 "%s\n", service,
-                 read_only_ret ? "read-only" : "read-write",
-                 vuser->user.unix_name ));
-
-       return read_only_ret;
-}
-
 /*******************************************************************
  Check if a username is OK.
 ********************************************************************/
@@ -151,20 +97,25 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
                }
        }
 
-       if (!user_ok(vuser->user.unix_name,snum, vuser->groups, vuser->n_groups))
+       if (!user_ok_token(vuser->user.unix_name, vuser->nt_user_token, snum))
                return(False);
 
-       readonly_share = is_share_read_only_for_user(conn->service, vuser);
+       readonly_share = is_share_read_only_for_token(vuser->user.unix_name,
+                                                     vuser->nt_user_token,
+                                                     conn->service);
 
        if (!readonly_share &&
            !share_access_check(conn, snum, vuser, FILE_WRITE_DATA)) {
                /* smb.conf allows r/w, but the security descriptor denies
                 * write. Fall back to looking at readonly. */
                readonly_share = True;
-               DEBUG(5,("falling back to read-only access-evaluation due to security descriptor\n"));
+               DEBUG(5,("falling back to read-only access-evaluation due to "
+                        "security descriptor\n"));
        }
 
-       if (!share_access_check(conn, snum, vuser, readonly_share ? FILE_READ_DATA : FILE_WRITE_DATA)) {
+       if (!share_access_check(conn, snum, vuser,
+                               readonly_share ?
+                               FILE_READ_DATA : FILE_WRITE_DATA)) {
                return False;
        }
 
@@ -176,11 +127,9 @@ static BOOL check_user_ok(connection_struct *conn, user_struct *vuser,int snum)
        ent->vuid = vuser->vuid;
        ent->read_only = readonly_share;
 
-       if (user_in_list(vuser->user.unix_name ,lp_admin_users(conn->service), vuser->groups, vuser->n_groups)) {
-               ent->admin_user = True;
-       } else {
-               ent->admin_user = False;
-       }
+       ent->admin_user = token_contains_name_in_list(
+               vuser->user.unix_name, NULL, vuser->nt_user_token,
+               lp_admin_users(conn->service));
 
        conn->read_only = ent->read_only;
        conn->admin_user = ent->admin_user;
@@ -217,20 +166,24 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid)
 
        if((lp_security() == SEC_SHARE) && (current_user.conn == conn) &&
           (current_user.ut.uid == conn->uid)) {
-               DEBUG(4,("change_to_user: Skipping user change - already user\n"));
+               DEBUG(4,("change_to_user: Skipping user change - already "
+                        "user\n"));
                return(True);
        } else if ((current_user.conn == conn) && 
                   (vuser != 0) && (current_user.vuid == vuid) && 
                   (current_user.ut.uid == vuser->uid)) {
-               DEBUG(4,("change_to_user: Skipping user change - already user\n"));
+               DEBUG(4,("change_to_user: Skipping user change - already "
+                        "user\n"));
                return(True);
        }
 
        snum = SNUM(conn);
 
        if ((vuser) && !check_user_ok(conn, vuser, snum)) {
-               DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) not permitted access to share %s.\n",
-                       vuser->user.smb_name, vuser->user.unix_name, vuid, lp_servicename(snum)));
+               DEBUG(2,("change_to_user: SMB user %s (unix user %s, vuid %d) "
+                        "not permitted access to share %s.\n",
+                        vuser->user.smb_name, vuser->user.unix_name, vuid,
+                        lp_servicename(snum)));
                return False;
        }
 
@@ -247,7 +200,8 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid)
                current_user.ut.groups  = vuser->groups;
                token = vuser->nt_user_token;
        } else {
-               DEBUG(2,("change_to_user: Invalid vuid used %d in accessing share %s.\n",vuid, lp_servicename(snum) ));
+               DEBUG(2,("change_to_user: Invalid vuid used %d in accessing "
+                        "share %s.\n",vuid, lp_servicename(snum) ));
                return False;
        }
 
@@ -258,7 +212,13 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid)
         */
 
        if((group_c = *lp_force_group(snum))) {
-               BOOL is_guest = False;
+
+               token = dup_nt_token(NULL, token);
+               if (token == NULL) {
+                       DEBUG(0, ("dup_nt_token failed\n"));
+                       return False;
+               }
+               must_free_token = True;
 
                if(group_c == '+') {
 
@@ -273,37 +233,25 @@ BOOL change_to_user(connection_struct *conn, uint16 vuid)
                        for (i = 0; i < current_user.ut.ngroups; i++) {
                                if (current_user.ut.groups[i] == conn->gid) {
                                        gid = conn->gid;
+                                       gid_to_sid(&token->user_sids[1], gid);
                                        break;
                                }
                        }
                } else {
                        gid = conn->gid;
+                       gid_to_sid(&token->user_sids[1], gid);
                }
-
-               /*
-                * We've changed the group list in the token - we must
-                * re-create it.
-                */
-
-               if (vuser && vuser->guest)
-                       is_guest = True;
-
-               token = create_nt_token(uid, gid, current_user.ut.ngroups, current_user.ut.groups, is_guest);
-               if (!token) {
-                       DEBUG(1, ("change_to_user: create_nt_token failed!\n"));
-                       return False;
-               }
-               must_free_token = True;
        }
        
-       set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups, token);
+       set_sec_ctx(uid, gid, current_user.ut.ngroups, current_user.ut.groups,
+                   token);
 
        /*
         * Free the new token (as set_sec_ctx copies it).
         */
 
        if (must_free_token)
-               delete_nt_token(&token);
+               talloc_free(token);
 
        current_user.conn = conn;
        current_user.vuid = vuid;
@@ -344,7 +292,8 @@ BOOL become_authenticated_pipe_user(pipes_struct *p)
                return False;
 
        set_sec_ctx(p->pipe_user.ut.uid, p->pipe_user.ut.gid, 
-                   p->pipe_user.ut.ngroups, p->pipe_user.ut.groups, p->pipe_user.nt_user_token);
+                   p->pipe_user.ut.ngroups, p->pipe_user.ut.groups,
+                   p->pipe_user.nt_user_token);
 
        return True;
 }
index 25e10c6a316de1253829cac09889809dbe881c1f..069047c9ec82c4d554232963fe9bab5a23f05b4f 100644 (file)
@@ -132,6 +132,29 @@ int net_run_function(int argc, const char **argv, struct functable *table,
        return usage_fn(argc, argv);
 }
 
+/*
+ * run a function from a function table.
+ */
+int net_run_function2(int argc, const char **argv, const char *whoami,
+                     struct functable2 *table)
+{
+       int i;
+
+       if (argc != 0) {
+               for (i=0; table[i].funcname; i++) {
+                       if (StrCaseCmp(argv[0], table[i].funcname) == 0)
+                               return table[i].fn(argc-1, argv+1);
+               }
+       }
+
+       for (i=0; table[i].funcname != NULL; i++) {
+               d_printf("%s %-15s %s\n", whoami, table[i].funcname,
+                        table[i].helptext);
+       }
+
+       return -1;
+}
+
 /****************************************************************************
 connect to \\server\service 
 ****************************************************************************/
@@ -376,6 +399,8 @@ struct cli_state *net_make_ipc_connection(unsigned flags)
        if (NT_STATUS_IS_OK(nt_status)) {
                return cli;
        } else {
+               d_fprintf(stderr, "Connection failed: %s\n",
+                         nt_errstr(nt_status));
                return NULL;
        }
 }
@@ -705,6 +730,7 @@ static struct functable net_func[] = {
        {"USER", net_user},
        {"GROUP", net_group},
        {"GROUPMAP", net_groupmap},
+       {"SAM", net_sam},
        {"VALIDATE", net_rap_validate},
        {"GROUPMEMBER", net_rap_groupmember},
        {"ADMIN", net_rap_admin},
@@ -722,6 +748,7 @@ static struct functable net_func[] = {
        {"MAXRID", net_maxrid},
        {"IDMAP", net_idmap},
        {"STATUS", net_status},
+       {"USERSHARE", net_usershare},
        {"USERSIDLIST", net_usersidlist},
 #ifdef WITH_FAKE_KASERVER
        {"AFS", net_afs},
index 2df13cfb8f1248d85e0ded24ba8ac10148d23f83..fc3167012d6d41d011ba5a3ddc82077ac4effb8b 100644 (file)
@@ -39,6 +39,29 @@ typedef struct copy_clistate {
        uint16 attribute;
 }copy_clistate;
 
+struct rpc_sh_ctx {
+       struct cli_state *cli;
+
+       DOM_SID *domain_sid;
+       char *domain_name;
+
+       const char *whoami;
+       const char *thiscmd;
+       struct rpc_sh_cmd *cmds;
+       struct rpc_sh_ctx *parent;
+};
+
+struct rpc_sh_cmd {
+       const char *name;
+       struct rpc_sh_cmd *(*sub)(TALLOC_CTX *mem_ctx,
+                                 struct rpc_sh_ctx *ctx);
+       int pipe_idx;
+       NTSTATUS (*fn)(TALLOC_CTX *mem_ctx, struct rpc_sh_ctx *ctx,
+                      struct rpc_pipe_client *pipe_hnd,
+                      int argc, const char **argv);
+       const char *help;
+};
+
 /* INCLUDE FILES */
 
 #include "utils/net_proto.h"
diff --git a/source3/utils/net_ads_gpo.c b/source3/utils/net_ads_gpo.c
new file mode 100644 (file)
index 0000000..fec6fb8
--- /dev/null
@@ -0,0 +1,436 @@
+/* 
+   Samba Unix/Linux SMB client library 
+   net ads commands for Group Policy
+   Copyright (C) 2005 Guenther Deschner (gd@samba.org)
+
+   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"
+#include "utils/net.h"
+
+#ifdef HAVE_ADS
+
+static int net_ads_gpo_usage(int argc, const char **argv)
+{
+       d_printf(
+               "net ads gpo <COMMAND>\n"\
+"<COMMAND> can be either:\n"\
+"  ADDLINK      Link a container to a GPO\n"\
+"  APPLY        Apply all GPOs\n"\
+"  DELETELINK   Delete a gPLink from a container\n"\
+"  EFFECTIVE    Lists all GPOs assigned to a machine\n"\
+"  GETGPO       Lists specified GPO\n"\
+"  GETLINK      Lists gPLink of a containter\n"\
+"  HELP         Prints this help message\n"\
+"  LIST         Lists all GPOs\n"\
+"\n"
+               );
+       return -1;
+}
+
+static int net_ads_gpo_effective(int argc, const char **argv)
+{
+       TALLOC_CTX *mem_ctx;
+       ADS_STRUCT *ads;
+       ADS_STATUS status;
+       const char *attrs[] = {"distinguishedName", "userAccountControl", NULL};
+       void *res = NULL;
+       const char *filter;
+       char *dn = NULL;
+       struct GROUP_POLICY_OBJECT *gpo_list;
+       uint32 uac = 0;
+       uint32 flags = 0;
+       
+       if (argc < 1) {
+               return -1;
+       }
+
+       mem_ctx = talloc_init("net_ads_gpo_effective");
+       if (mem_ctx == NULL) {
+               return -1;
+       }
+
+       filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)(sAMAccountName=%s))", argv[0]);
+       if (filter == NULL) {
+               goto out;
+       }
+
+       if (!(ads = ads_startup())) {
+               goto out;
+       }
+
+       status = ads_do_search_all(ads, ads->config.bind_path,
+                                  LDAP_SCOPE_SUBTREE,
+                                  filter, attrs, &res);
+       
+       if (!ADS_ERR_OK(status)) {
+               goto out;
+       }
+
+       if (ads_count_replies(ads, res) != 1) {
+               printf("no result\n");
+               goto out;
+       }
+
+       dn = ads_get_dn(ads, res);
+       if (dn == NULL) {
+               goto out;
+       }
+
+       if (!ads_pull_uint32(ads, res, "userAccountControl", &uac)) {
+               goto out;
+       }
+
+       if (uac & UF_WORKSTATION_TRUST_ACCOUNT) {
+               flags |= GPO_LIST_FLAG_MACHINE;
+       }
+
+       printf("%s: '%s' has dn: '%s'\n", 
+               (uac & UF_WORKSTATION_TRUST_ACCOUNT) ? "machine" : "user", 
+               argv[0], dn);
+
+       status = ads_get_gpo_list(ads, mem_ctx, dn, flags, &gpo_list);
+       if (!ADS_ERR_OK(status)) {
+               goto out;
+       }
+
+       printf("unsorted full dump of all GPOs for this machine:\n");
+
+       {
+               struct GROUP_POLICY_OBJECT *gpo = gpo_list;
+
+               for (gpo = gpo_list; gpo; gpo = gpo->next) {
+                       dump_gpo(mem_ctx, gpo);
+               }
+       }
+
+       printf("sorted full dump of all GPOs valid for this machine:\n");
+      
+out:
+       ads_memfree(ads, dn);
+       ads_msgfree(ads, res);
+
+       ads_destroy(&ads);
+       talloc_destroy(mem_ctx);
+       return 0;
+}
+
+static int net_ads_gpo_list(int argc, const char **argv)
+{
+       ADS_STRUCT *ads;
+       ADS_STATUS status;
+       void *res = NULL;
+       int num_reply = 0;
+       void *msg = NULL;
+       struct GROUP_POLICY_OBJECT gpo;
+       TALLOC_CTX *mem_ctx;
+
+       mem_ctx = talloc_init("net_ads_gpo_list");
+       if (mem_ctx == NULL) {
+               return -1;
+       }
+
+       if (!(ads = ads_startup())) {
+               goto out;
+       }
+
+       status = ads_do_search_all(ads, ads->config.bind_path,
+                                  LDAP_SCOPE_SUBTREE,
+                                  "(objectclass=groupPolicyContainer)", NULL, &res);
+       if (!ADS_ERR_OK(status)) {
+               d_printf("search failed: %s\n", ads_errstr(status));
+               goto out;
+       }       
+
+       num_reply = ads_count_replies(ads, res);
+       
+       d_printf("Got %d replies\n\n", num_reply);
+
+       /* dump the results */
+       for (msg = ads_first_entry(ads, res); msg; msg = ads_next_entry(ads, msg)) {
+       
+               status = ads_parse_gpo(ads, mem_ctx, msg, ads_get_dn(ads, msg), &gpo);
+
+               if (!ADS_ERR_OK(status)) {
+                       d_printf("parse failed: %s\n", ads_errstr(status));
+                       goto out;
+               }       
+
+               dump_gpo(mem_ctx, &gpo);
+
+       }
+
+out:
+       ads_msgfree(ads, res);
+
+       talloc_destroy(mem_ctx);
+       ads_destroy(&ads);
+       
+       return 0;
+}
+
+static int net_ads_gpo_apply(int argc, const char **argv)
+{
+       TALLOC_CTX *mem_ctx;
+       ADS_STRUCT *ads;
+       ADS_STATUS status;
+       const char *attrs[] = {"distinguishedName", "userAccountControl", NULL};
+       void *res = NULL;
+       const char *filter;
+       char *dn = NULL;
+       struct GROUP_POLICY_OBJECT *gpo_list;
+       uint32 uac = 0;
+       uint32 flags = 0;
+       
+       if (argc < 1) {
+               return -1;
+       }
+
+       mem_ctx = talloc_init("net_ads_gpo_apply");
+       if (mem_ctx == NULL) {
+               goto out;
+       }
+
+       filter = talloc_asprintf(mem_ctx, "(&(objectclass=user)(sAMAccountName=%s))", argv[0]);
+       if (filter == NULL) {
+               goto out;
+       }
+
+       if (!(ads = ads_startup())) {
+               goto out;
+       }
+
+       status = ads_do_search_all(ads, ads->config.bind_path,
+                                  LDAP_SCOPE_SUBTREE,
+                                  filter, attrs, &res);
+       
+       if (!ADS_ERR_OK(status)) {
+               goto out;
+       }
+
+       if (ads_count_replies(ads, res) != 1) {
+               printf("no result\n");
+               goto out;
+       }
+
+       dn = ads_get_dn(ads, res);
+       if (dn == NULL) {
+               goto out;
+       }
+
+       if (!ads_pull_uint32(ads, res, "userAccountControl", &uac)) {
+               goto out;
+       }
+
+       if (uac & UF_WORKSTATION_TRUST_ACCOUNT) {
+               flags |= GPO_LIST_FLAG_MACHINE;
+       }
+
+       printf("%s: '%s' has dn: '%s'\n", 
+               (uac & UF_WORKSTATION_TRUST_ACCOUNT) ? "machine" : "user", 
+               argv[0], dn);
+
+       status = ads_get_gpo_list(ads, mem_ctx, dn, flags, &gpo_list);
+       if (!ADS_ERR_OK(status)) {
+               goto out;
+       }
+
+       /* FIXME: allow to process just a single extension */
+       status = gpo_process_gpo_list(ads, mem_ctx, &gpo_list, NULL, flags); 
+       if (!ADS_ERR_OK(status)) {
+               goto out;
+       }
+
+out:
+       ads_memfree(ads, dn);
+       ads_msgfree(ads, res);
+
+       ads_destroy(&ads);
+       talloc_destroy(mem_ctx);
+       return 0;
+}
+
+
+static int net_ads_gpo_get_link(int argc, const char **argv)
+{
+       ADS_STRUCT *ads;
+       ADS_STATUS status;
+       TALLOC_CTX *mem_ctx;
+       struct GP_LINK gp_link;
+
+       if (argc < 1) {
+               return -1;
+       }
+
+       mem_ctx = talloc_init("add_gpo_link");
+       if (mem_ctx == NULL) {
+               return -1;
+       }
+
+       if (!(ads = ads_startup())) {
+               goto out;
+       }
+
+       status = ads_get_gpo_link(ads, mem_ctx, argv[0], &gp_link);
+       if (!ADS_ERR_OK(status)) {
+               d_printf("get link for %s failed: %s\n", argv[0], ads_errstr(status));
+               goto out;
+       }       
+
+       dump_gplink(ads, mem_ctx, &gp_link);
+
+out:
+       talloc_destroy(mem_ctx);
+       ads_destroy(&ads);
+
+       return 0;
+}
+
+static int net_ads_gpo_add_link(int argc, const char **argv)
+{
+       ADS_STRUCT *ads;
+       ADS_STATUS status;
+       uint32 gpo_opt = 0;
+       TALLOC_CTX *mem_ctx;
+
+       if (argc < 2) {
+               return -1;
+       }
+
+       mem_ctx = talloc_init("add_gpo_link");
+       if (mem_ctx == NULL) {
+               return -1;
+       }
+
+       if (argc == 3) {
+               gpo_opt = atoi(argv[2]);
+       }
+
+       if (!(ads = ads_startup())) {
+               goto out;
+       }
+
+       status = ads_add_gpo_link(ads, mem_ctx, argv[0], argv[1], gpo_opt);
+       if (!ADS_ERR_OK(status)) {
+               d_printf("add link failed: %s\n", ads_errstr(status));
+               goto out;
+       }
+
+out:
+       talloc_destroy(mem_ctx);
+       ads_destroy(&ads);
+
+       return 0;
+}
+
+static int net_ads_gpo_delete_link(int argc, const char **argv)
+{
+       ADS_STRUCT *ads;
+       ADS_STATUS status;
+       TALLOC_CTX *mem_ctx;
+
+       if (argc < 2) {
+               return -1;
+       }
+
+       mem_ctx = talloc_init("delete_gpo_link");
+       if (mem_ctx == NULL) {
+               return -1;
+       }
+
+       if (!(ads = ads_startup())) {
+               goto out;
+       }
+
+       status = ads_delete_gpo_link(ads, mem_ctx, argv[0], argv[1]);
+       if (!ADS_ERR_OK(status)) {
+               d_printf("delete link failed: %s\n", ads_errstr(status));
+               goto out;
+       }       
+
+out:
+       talloc_destroy(mem_ctx);
+       ads_destroy(&ads);
+
+       return 0;
+}
+
+static int net_ads_gpo_get_gpo(int argc, const char **argv)
+{
+       ADS_STRUCT *ads;
+       ADS_STATUS status;
+       TALLOC_CTX *mem_ctx;
+       struct GROUP_POLICY_OBJECT gpo;
+       uint32 sysvol_gpt_version;
+
+       if (argc < 1) {
+               return -1;
+       }
+
+       mem_ctx = talloc_init("add_gpo_get_gpo");
+       if (mem_ctx == NULL) {
+               return -1;
+       }
+
+       if (!(ads = ads_startup())) {
+               goto out;
+       }
+
+       if (strnequal(argv[0], "CN={", strlen("CN={"))) {
+               status = ads_get_gpo(ads, mem_ctx, argv[0], NULL, NULL, &gpo);
+       } else {
+               status = ads_get_gpo(ads, mem_ctx, NULL, argv[0], NULL, &gpo);
+       }
+
+       if (!ADS_ERR_OK(status)) {
+               d_printf("get gpo for [%s] failed: %s\n", argv[0], ads_errstr(status));
+               goto out;
+       }       
+
+       dump_gpo(mem_ctx, &gpo);
+
+       status = ADS_ERROR_NT(ads_gpo_get_sysvol_gpt_version(ads, mem_ctx, gpo.file_sys_path, &sysvol_gpt_version)); 
+       if (!ADS_ERR_OK(status)) {
+               goto out;
+       }
+
+       printf("sysvol GPT version: %d\n", sysvol_gpt_version);
+
+out:
+       talloc_destroy(mem_ctx);
+       ads_destroy(&ads);
+
+       return 0;
+}
+
+int net_ads_gpo(int argc, const char **argv)
+{
+       struct functable func[] = {
+               {"LIST", net_ads_gpo_list},
+               {"EFFECTIVE", net_ads_gpo_effective},
+               {"ADDLINK", net_ads_gpo_add_link},
+               {"DELETELINK", net_ads_gpo_delete_link},
+               {"GETLINK", net_ads_gpo_get_link},
+               {"GETGPO", net_ads_gpo_get_gpo},
+               {"HELP", net_ads_gpo_usage},
+               {"APPLY", net_ads_gpo_apply},
+               {NULL, NULL}
+       };
+
+       return net_run_function(argc, argv, func, net_ads_gpo_usage);
+}
+
+#endif
index 1cff120c393130069f2b5cf804b6d9b164cbd894..96a6aa531aabc98bd007ac911cfbe38169ec1134 100644 (file)
@@ -93,6 +93,7 @@ static void print_map_entry ( GROUP_MAP map, BOOL long_list )
        else {
                d_printf("%s\n", map.nt_name);
                d_printf("\tSID       : %s\n", sid_string_static(&map.sid));
+               d_printf("\tUnix gid  : %d\n", map.gid);
                d_printf("\tUnix group: %s\n", gidtoname(map.gid));
                d_printf("\tGroup type: %s\n",
                         sid_type_lookup(map.sid_name_use));
@@ -261,10 +262,26 @@ static int net_groupmap_add(int argc, const char **argv)
                d_fprintf(stderr, "Can't lookup UNIX group %s\n", unixgrp);
                return -1;
        }
+
+       {
+               GROUP_MAP map;
+               if (pdb_getgrgid(&map, gid)) {
+                       d_printf("Unix group %s already mapped to SID %s\n",
+                                unixgrp, sid_string_static(&map.sid));
+                       return -1;
+               }
+       }
        
        if ( (rid == 0) && (string_sid[0] == '\0') ) {
-               d_printf("No rid or sid specified, choosing algorithmic mapping\n");
-               rid = pdb_gid_to_group_rid(gid);
+               d_printf("No rid or sid specified, choosing a RID\n");
+               if (pdb_rid_algorithm()) {
+                       rid = pdb_gid_to_group_rid(gid);
+               } else {
+                       if (!pdb_new_rid(&rid)) {
+                               d_printf("Could not get new RID\n");
+                       }
+               }
+               d_printf("Got RID %d\n", rid);
        }
 
        /* append the rid to our own domain/machine SID if we don't have a full SID */
@@ -423,7 +440,7 @@ static int net_groupmap_modify(int argc, const char **argv)
                map.gid = gid;
        }
 
-       if ( !pdb_update_group_mapping_entry(&map) ) {
+       if ( !NT_STATUS_IS_OK(pdb_update_group_mapping_entry(&map)) ) {
                d_fprintf(stderr, "Could not update group database\n");
                return -1;
        }
@@ -548,7 +565,7 @@ static int net_groupmap_set(int argc, const char **argv)
                fstrcpy(map.nt_name, ntgroup);
                fstrcpy(map.comment, "");
 
-               if (!pdb_add_group_mapping_entry(&map)) {
+               if (!NT_STATUS_IS_OK(pdb_add_group_mapping_entry(&map))) {
                        d_fprintf(stderr, "Could not add mapping entry for %s\n",
                                 ntgroup);
                        return -1;
@@ -582,7 +599,7 @@ static int net_groupmap_set(int argc, const char **argv)
        if (grp != NULL)
                map.gid = grp->gr_gid;
 
-       if (!pdb_update_group_mapping_entry(&map)) {
+       if (!NT_STATUS_IS_OK(pdb_update_group_mapping_entry(&map))) {
                d_fprintf(stderr, "Could not update group mapping for %s\n", ntgroup);
                return -1;
        }
@@ -633,7 +650,7 @@ static int net_groupmap_addmem(int argc, const char **argv)
                return -1;
        }
 
-       if (!pdb_add_aliasmem(&alias, &member)) {
+       if (!NT_STATUS_IS_OK(pdb_add_aliasmem(&alias, &member))) {
                d_fprintf(stderr, "Could not add sid %s to alias %s\n",
                         argv[1], argv[0]);
                return -1;
@@ -653,7 +670,7 @@ static int net_groupmap_delmem(int argc, const char **argv)
                return -1;
        }
 
-       if (!pdb_del_aliasmem(&alias, &member)) {
+       if (!NT_STATUS_IS_OK(pdb_del_aliasmem(&alias, &member))) {
                d_fprintf(stderr, "Could not delete sid %s from alias %s\n",
                         argv[1], argv[0]);
                return -1;
@@ -677,7 +694,7 @@ static int net_groupmap_listmem(int argc, const char **argv)
        members = NULL;
        num = 0;
 
-       if (!pdb_enum_aliasmem(&alias, &members, &num)) {
+       if (!NT_STATUS_IS_OK(pdb_enum_aliasmem(&alias, &members, &num))) {
                d_fprintf(stderr, "Could not list members for sid %s\n", argv[0]);
                return -1;
        }
@@ -701,8 +718,9 @@ static BOOL print_alias_memberships(TALLOC_CTX *mem_ctx,
        alias_rids = NULL;
        num_alias_rids = 0;
 
-       if (!pdb_enum_alias_memberships(mem_ctx, domain_sid, member, 1,
-                                       &alias_rids, &num_alias_rids)) {
+       if (!NT_STATUS_IS_OK(pdb_enum_alias_memberships(
+                                    mem_ctx, domain_sid, member, 1,
+                                    &alias_rids, &num_alias_rids))) {
                d_fprintf(stderr, "Could not list memberships for sid %s\n",
                         sid_string_static(member));
                return False;
index c5188c3608e4932fa9dd5031d16c5b7513cbfa6a..79062345ab69841b9b66d0235d7c08d2c63077fd 100644 (file)
@@ -61,7 +61,7 @@ static int help_usage(int argc, const char **argv)
 "Valid functions are:\n"\
 "  RPC RAP ADS FILE SHARE SESSION SERVER DOMAIN PRINTQ USER GROUP VALIDATE\n"\
 "  GROUPMEMBER ADMIN SERVICE PASSWORD TIME LOOKUP GETLOCALSID SETLOCALSID\n"\
-"  CHANGESCRETPW IDMAP\n");
+"  CHANGESCRETPW LOOKUP SAM\n");
        return -1;
 }
 
@@ -223,8 +223,9 @@ static int net_usage(int argc, const char **argv)
                 "  net lookup\t\tto lookup host name or ip address\n"\
                 "  net user\t\tto manage users\n"\
                 "  net group\t\tto manage groups\n"\
+                "  net sam\t\tto edit the local user database directly\n"\
+                "  net lookup\t\tto look up various things\n"\
                 "  net groupmap\t\tto manage group mappings\n"\
-                "  net idmap\t\tto manage the idmap id mappings\n"\
                 "  net join\t\tto join a domain\n"\
                 "  net cache\t\tto operate on cache tdb file\n"\
                 "  net getlocalsid [NAME]\tto get the SID for local name\n"\
@@ -233,6 +234,7 @@ static int net_usage(int argc, const char **argv)
                 "                    \tthis requires the -f flag as a safety barrier\n"\
                 "  net status\t\tShow server status\n"\
                "  net usersidlist\tto get a list of all users with their SIDs\n"
+               "  net usershare\t\tto add, delete and list locally user-modifiable shares\n"
                 "\n"\
                 "  net ads <command>\tto run ADS commands\n"\
                 "  net rap <command>\tto run RAP (pre-RPC) commands\n"\
@@ -270,11 +272,12 @@ int net_help(int argc, const char **argv)
                {"PASSWORD", net_rap_password_usage},
                {"TIME", net_time_usage},
                {"LOOKUP", net_lookup_usage},
+               {"USERSHARE", net_usershare_usage},
                {"USERSIDLIST", net_usersidlist_usage},
 #ifdef WITH_FAKE_KASERVER
                {"AFS", net_help_afs},
 #endif
-               {"IDMAP", net_help_idmap},
+
                {"HELP", help_usage},
                {NULL, NULL}};
 
index 8ee63515d4545aacbabcdba7b7b527ad54d99e16..dd2d666d5a0b0f9f7043a59cf8560d4ded1f919d 100644 (file)
@@ -28,6 +28,8 @@ int net_lookup_usage(int argc, const char **argv)
 "  net lookup kdc [realm]\n\tgives IP of realm's kerberos KDC\n\n"
 "  net lookup dc [domain]\n\tgives IP of domains Domain Controllers\n\n"
 "  net lookup master [domain|wg]\n\tgive IP of master browser\n\n"
+"  net lookup name [name]\n\tLookup name's sid and type\n\n"
+"  net lookup sid [sid]\n\tGive sid's name and type\n\n"
 );
        return -1;
 }
@@ -227,6 +229,54 @@ static int net_lookup_kdc(int argc, const char **argv)
        return -1;
 }
 
+static int net_lookup_name(int argc, const char **argv)
+{
+       const char *dom, *name;
+       DOM_SID sid;
+       enum SID_NAME_USE type;
+
+       if (argc != 1) {
+               d_printf("usage: net lookup name <name>\n");
+               return -1;
+       }
+
+       if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ALL,
+                        &dom, &name, &sid, &type)) {
+               d_printf("Could not lookup name %s\n", argv[0]);
+               return -1;
+       }
+
+       d_printf("%s %d (%s) %s\\%s\n", sid_string_static(&sid),
+                type, sid_type_lookup(type), dom, name);
+       return 0;
+}
+
+static int net_lookup_sid(int argc, const char **argv)
+{
+       const char *dom, *name;
+       DOM_SID sid;
+       enum SID_NAME_USE type;
+
+       if (argc != 1) {
+               d_printf("usage: net lookup sid <sid>\n");
+               return -1;
+       }
+
+       if (!string_to_sid(&sid, argv[0])) {
+               d_printf("Could not convert %s to SID\n", argv[0]);
+               return -1;
+       }
+
+       if (!lookup_sid(tmp_talloc_ctx(), &sid,
+                       &dom, &name, &type)) {
+               d_printf("Could not lookup name %s\n", argv[0]);
+               return -1;
+       }
+
+       d_printf("%s %d (%s) %s\\%s\n", sid_string_static(&sid),
+                type, sid_type_lookup(type), dom, name);
+       return 0;
+}
 
 /* lookup hosts or IP addresses using internal samba lookup fns */
 int net_lookup(int argc, const char **argv)
@@ -239,6 +289,8 @@ int net_lookup(int argc, const char **argv)
                {"DC", net_lookup_dc},
                {"MASTER", net_lookup_master},
                {"KDC", net_lookup_kdc},
+               {"NAME", net_lookup_name},
+               {"SID", net_lookup_sid},
                {NULL, NULL}
        };
 
index 0495a7b92c2a8f92ae08dde8fe84cfaaae579465..a9dc3a1fc65f13f82d83f82826849c236109c744 100644 (file)
@@ -49,46 +49,42 @@ static int net_mode_share;
  * @return The Domain SID of the remote machine.
  **/
 
-static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx, char **domain_name)
+NTSTATUS net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx,
+                                  DOM_SID **domain_sid, char **domain_name)
 {
        struct rpc_pipe_client *lsa_pipe;
-       DOM_SID *domain_sid;
        POLICY_HND pol;
        NTSTATUS result = NT_STATUS_OK;
        uint32 info_class = 5;
        
        lsa_pipe = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result);
        if (!lsa_pipe) {
-               fprintf(stderr, "could not initialise lsa pipe\n");
-               goto error;
+               d_fprintf(stderr, "Could not initialise lsa pipe\n");
+               return result;
        }
        
        result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, False, 
                                     SEC_RIGHTS_MAXIMUM_ALLOWED,
                                     &pol);
        if (!NT_STATUS_IS_OK(result)) {
-               goto error;
+               d_fprintf(stderr, "open_policy failed: %s\n",
+                         nt_errstr(result));
+               return result;
        }
 
-       result = rpccli_lsa_query_info_policy(lsa_pipe, mem_ctx, &pol, info_class, 
-                                          domain_name, &domain_sid);
+       result = rpccli_lsa_query_info_policy(lsa_pipe, mem_ctx, &pol,
+                                             info_class, domain_name,
+                                             domain_sid);
        if (!NT_STATUS_IS_OK(result)) {
- error:
-               fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain);
-
-               if (!NT_STATUS_IS_OK(result)) {
-                       fprintf(stderr, "error: %s\n", nt_errstr(result));
-               }
-
-               exit(1);
+               d_fprintf(stderr, "lsaquery failed: %s\n",
+                         nt_errstr(result));
+               return result;
        }
 
-       if (lsa_pipe) {
-               rpccli_lsa_close(lsa_pipe, mem_ctx, &pol);
-               cli_rpc_pipe_close(lsa_pipe);
-       }
+       rpccli_lsa_close(lsa_pipe, mem_ctx, &pol);
+       cli_rpc_pipe_close(lsa_pipe);
 
-       return domain_sid;
+       return NT_STATUS_OK;
 }
 
 /**
@@ -136,7 +132,12 @@ int run_rpc_command(struct cli_state *cli_arg,
                return -1;
        }
        
-       domain_sid = net_get_remote_domain_sid(cli, mem_ctx, &domain_name);
+       nt_status = net_get_remote_domain_sid(cli, mem_ctx, &domain_sid,
+                                             &domain_name);
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               cli_shutdown(cli);
+               return -1;
+       }
 
        if (!(conn_flags & NET_FLAGS_NO_PIPE)) {
                if (lp_client_schannel() && (pipe_idx == PI_NETLOGON)) {
@@ -410,7 +411,7 @@ int net_rpc_join(int argc, const char **argv)
  * @return Normal NTSTATUS return.
  **/
 
-static NTSTATUS rpc_info_internals(const DOM_SID *domain_sid,
+NTSTATUS rpc_info_internals(const DOM_SID *domain_sid,
                        const char *domain_name, 
                        struct cli_state *cli,
                        struct rpc_pipe_client *pipe_hnd,
@@ -1219,6 +1220,380 @@ int net_rpc_user(int argc, const char **argv)
        return net_run_function(argc, argv, func, rpc_user_usage);
 }
 
+static NTSTATUS rpc_sh_user_list(TALLOC_CTX *mem_ctx,
+                                struct rpc_sh_ctx *ctx,
+                                struct rpc_pipe_client *pipe_hnd,
+                                int argc, const char **argv)
+{
+       return rpc_user_list_internals(ctx->domain_sid, ctx->domain_name,
+                                      ctx->cli, pipe_hnd, mem_ctx,
+                                      argc, argv);
+}
+
+static NTSTATUS rpc_sh_user_info(TALLOC_CTX *mem_ctx,
+                                struct rpc_sh_ctx *ctx,
+                                struct rpc_pipe_client *pipe_hnd,
+                                int argc, const char **argv)
+{
+       return rpc_user_info_internals(ctx->domain_sid, ctx->domain_name,
+                                      ctx->cli, pipe_hnd, mem_ctx,
+                                      argc, argv);
+}
+
+static NTSTATUS rpc_sh_handle_user(TALLOC_CTX *mem_ctx,
+                                  struct rpc_sh_ctx *ctx,
+                                  struct rpc_pipe_client *pipe_hnd,
+                                  int argc, const char **argv,
+                                  NTSTATUS (*fn)(
+                                          TALLOC_CTX *mem_ctx,
+                                          struct rpc_sh_ctx *ctx,
+                                          struct rpc_pipe_client *pipe_hnd,
+                                          const POLICY_HND *user_hnd,
+                                          int argc, const char **argv))
+                                          
+{
+       POLICY_HND connect_pol, domain_pol, user_pol;
+       NTSTATUS result = NT_STATUS_UNSUCCESSFUL;
+       DOM_SID sid;
+       uint32 rid;
+       enum SID_NAME_USE type;
+
+       if (argc == 0) {
+               d_fprintf(stderr, "usage: %s <username>\n", ctx->whoami);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       ZERO_STRUCT(connect_pol);
+       ZERO_STRUCT(domain_pol);
+       ZERO_STRUCT(user_pol);
+
+       result = net_rpc_lookup_name(mem_ctx, pipe_hnd->cli, argv[0],
+                                    NULL, NULL, &sid, &type);
+       if (!NT_STATUS_IS_OK(result)) {
+               d_fprintf(stderr, "Could not lookup %s: %s\n", argv[0],
+                         nt_errstr(result));
+               goto done;
+       }
+
+       if (type != SID_NAME_USER) {
+               d_fprintf(stderr, "%s is a %s, not a user\n", argv[0],
+                         sid_type_lookup(type));
+               result = NT_STATUS_NO_SUCH_USER;
+               goto done;
+       }
+
+       if (!sid_peek_check_rid(ctx->domain_sid, &sid, &rid)) {
+               d_fprintf(stderr, "%s is not in our domain\n", argv[0]);
+               result = NT_STATUS_NO_SUCH_USER;
+               goto done;
+       }
+
+       result = rpccli_samr_connect(pipe_hnd, mem_ctx,
+                                    MAXIMUM_ALLOWED_ACCESS, &connect_pol);
+       if (!NT_STATUS_IS_OK(result)) {
+               goto done;
+       }
+
+       result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol,
+                                        MAXIMUM_ALLOWED_ACCESS,
+                                        ctx->domain_sid, &domain_pol);
+       if (!NT_STATUS_IS_OK(result)) {
+               goto done;
+       }
+
+       result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol,
+                                      MAXIMUM_ALLOWED_ACCESS,
+                                      rid, &user_pol);
+       if (!NT_STATUS_IS_OK(result)) {
+               goto done;
+       }
+
+       result = fn(mem_ctx, ctx, pipe_hnd, &user_pol, argc-1, argv+1);
+
+ done:
+       if (is_valid_policy_hnd(&user_pol)) {
+               rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol);
+       }
+       if (is_valid_policy_hnd(&domain_pol)) {
+               rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol);
+       }
+       if (is_valid_policy_hnd(&connect_pol)) {
+               rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol);
+       }
+       return result;
+}
+
+static NTSTATUS rpc_sh_user_show_internals(TALLOC_CTX *mem_ctx,
+                                          struct rpc_sh_ctx *ctx,
+                                          struct rpc_pipe_client *pipe_hnd,
+                                          const POLICY_HND *user_hnd,
+                                          int argc, const char **argv)
+{
+       NTSTATUS result;
+       SAM_USERINFO_CTR *ctr;
+       SAM_USER_INFO_21 *info;
+
+       if (argc != 0) {
+               d_fprintf(stderr, "usage: %s show <username>\n", ctx->whoami);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, user_hnd,
+                                           21, &ctr);
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
+       }
+
+       info = ctr->info.id21;
+
+       d_printf("user rid: %d, group rid: %d\n", info->user_rid,
+                info->group_rid);
+
+       return result;
+}
+
+static NTSTATUS rpc_sh_user_show(TALLOC_CTX *mem_ctx,
+                                struct rpc_sh_ctx *ctx,
+                                struct rpc_pipe_client *pipe_hnd,
+                                int argc, const char **argv)
+{
+       return rpc_sh_handle_user(mem_ctx, ctx, pipe_hnd, argc, argv,
+                                 rpc_sh_user_show_internals);
+}
+
+#define FETCHSTR(name, rec) \
+do { if (strequal(ctx->thiscmd, name)) { \
+       oldval = rpcstr_pull_unistr2_talloc(mem_ctx, &usr->uni_##rec); } \
+} while (0);
+
+#define SETSTR(name, rec, flag) \
+do { if (strequal(ctx->thiscmd, name)) { \
+       init_unistr2(&usr->uni_##rec, argv[0], STR_TERMINATE); \
+       init_uni_hdr(&usr->hdr_##rec, &usr->uni_##rec); \
+       usr->fields_present |= ACCT_##flag; } \
+} while (0);
+
+static NTSTATUS rpc_sh_user_str_edit_internals(TALLOC_CTX *mem_ctx,
+                                              struct rpc_sh_ctx *ctx,
+                                              struct rpc_pipe_client *pipe_hnd,
+                                              const POLICY_HND *user_hnd,
+                                              int argc, const char **argv)
+{
+       NTSTATUS result;
+       SAM_USERINFO_CTR *ctr;
+       SAM_USER_INFO_21 *usr;
+       const char *username;
+       const char *oldval = "";
+
+       if (argc > 1) {
+               d_fprintf(stderr, "usage: %s <username> [new value|NULL]\n",
+                         ctx->whoami);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, user_hnd,
+                                           21, &ctr);
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
+       }
+
+       usr = ctr->info.id21;
+
+       username = rpcstr_pull_unistr2_talloc(mem_ctx, &usr->uni_user_name);
+
+       FETCHSTR("fullname", full_name);
+       FETCHSTR("homedir", home_dir);
+       FETCHSTR("homedrive", dir_drive);
+       FETCHSTR("logonscript", logon_script);
+       FETCHSTR("profilepath", profile_path);
+       FETCHSTR("description", acct_desc);
+
+       if (argc == 0) {
+               d_printf("%s's %s: [%s]\n", username, ctx->thiscmd, oldval);
+               goto done;
+       }
+
+       ZERO_STRUCTP(usr);
+
+       if (strcmp(argv[0], "NULL") == 0) {
+               argv[0] = "";
+       }
+
+       SETSTR("fullname", full_name, FULL_NAME);
+       SETSTR("homedir", home_dir, HOME_DIR);
+       SETSTR("homedrive", dir_drive, HOME_DRIVE);
+       SETSTR("logonscript", logon_script, LOGON_SCRIPT);
+       SETSTR("profilepath", profile_path, PROFILE);
+       SETSTR("description", acct_desc, DESCRIPTION);
+
+       result = rpccli_samr_set_userinfo2(
+               pipe_hnd, mem_ctx, user_hnd, 21,
+               &pipe_hnd->cli->user_session_key, ctr);
+
+       d_printf("Set %s's %s from [%s] to [%s]\n", username,
+                ctx->thiscmd, oldval, argv[0]);
+
+ done:
+
+       return result;
+}
+
+#define HANDLEFLG(name, rec) \
+do { if (strequal(ctx->thiscmd, name)) { \
+       oldval = (oldflags & ACB_##rec) ? "yes" : "no"; \
+       if (newval) { \
+               newflags = oldflags | ACB_##rec; \
+       } else { \
+               newflags = oldflags & ~ACB_##rec; \
+       } } } while (0);
+
+static NTSTATUS rpc_sh_user_str_edit(TALLOC_CTX *mem_ctx,
+                                    struct rpc_sh_ctx *ctx,
+                                    struct rpc_pipe_client *pipe_hnd,
+                                    int argc, const char **argv)
+{
+       return rpc_sh_handle_user(mem_ctx, ctx, pipe_hnd, argc, argv,
+                                 rpc_sh_user_str_edit_internals);
+}
+
+static NTSTATUS rpc_sh_user_flag_edit_internals(TALLOC_CTX *mem_ctx,
+                                               struct rpc_sh_ctx *ctx,
+                                               struct rpc_pipe_client *pipe_hnd,
+                                               const POLICY_HND *user_hnd,
+                                               int argc, const char **argv)
+{
+       NTSTATUS result;
+       SAM_USERINFO_CTR *ctr;
+       SAM_USER_INFO_21 *usr;
+       const char *username;
+       const char *oldval = "unknown";
+       uint32 oldflags, newflags;
+       BOOL newval;
+
+       if ((argc > 1) ||
+           ((argc == 1) && !strequal(argv[0], "yes") &&
+            !strequal(argv[0], "no"))) {
+               d_fprintf(stderr, "usage: %s <username> [yes|no]\n",
+                         ctx->whoami);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       newval = strequal(argv[0], "yes");
+
+       result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, user_hnd,
+                                           21, &ctr);
+       if (!NT_STATUS_IS_OK(result)) {
+               return result;
+       }
+
+       usr = ctr->info.id21;
+
+       username = rpcstr_pull_unistr2_talloc(mem_ctx, &usr->uni_user_name);
+       oldflags = usr->acb_info;
+       newflags = usr->acb_info;
+
+       HANDLEFLG("disabled", DISABLED);
+       HANDLEFLG("pwnotreq", PWNOTREQ);
+       HANDLEFLG("autolock", AUTOLOCK);
+       HANDLEFLG("pwnoexp", PWNOEXP);
+
+       if (argc == 0) {
+               d_printf("%s's %s flag: %s\n", username, ctx->thiscmd, oldval);
+               goto done;
+       }
+
+       ZERO_STRUCTP(usr);
+
+       usr->acb_info = newflags;
+       usr->fields_present = ACCT_FLAGS;
+
+       result = rpccli_samr_set_userinfo2(
+               pipe_hnd, mem_ctx, user_hnd, 21,
+               &pipe_hnd->cli->user_session_key, ctr);
+
+       if (NT_STATUS_IS_OK(result)) {
+               d_printf("Set %s's %s flag from [%s] to [%s]\n", username,
+                        ctx->thiscmd, oldval, argv[0]);
+       }
+
+ done:
+
+       return result;
+}
+
+static NTSTATUS rpc_sh_user_flag_edit(TALLOC_CTX *mem_ctx,
+                                     struct rpc_sh_ctx *ctx,
+                                     struct rpc_pipe_client *pipe_hnd,
+                                     int argc, const char **argv)
+{
+       return rpc_sh_handle_user(mem_ctx, ctx, pipe_hnd, argc, argv,
+                                 rpc_sh_user_flag_edit_internals);
+}
+
+struct rpc_sh_cmd *net_rpc_user_edit_cmds(TALLOC_CTX *mem_ctx,
+                                         struct rpc_sh_ctx *ctx)
+{
+       static struct rpc_sh_cmd cmds[] = {
+
+               { "fullname", NULL, PI_SAMR, rpc_sh_user_str_edit,
+                 "Show/Set a user's full name" },
+
+               { "homedir", NULL, PI_SAMR, rpc_sh_user_str_edit,
+                 "Show/Set a user's home directory" },
+
+               { "homedrive", NULL, PI_SAMR, rpc_sh_user_str_edit,
+                 "Show/Set a user's home drive" },
+
+               { "logonscript", NULL, PI_SAMR, rpc_sh_user_str_edit,
+                 "Show/Set a user's logon script" },
+
+               { "profilepath", NULL, PI_SAMR, rpc_sh_user_str_edit,
+                 "Show/Set a user's profile path" },
+
+               { "description", NULL, PI_SAMR, rpc_sh_user_str_edit,
+                 "Show/Set a user's description" },
+
+               { "disabled", NULL, PI_SAMR, rpc_sh_user_flag_edit,
+                 "Show/Set whether a user is disabled" },
+
+               { "autolock", NULL, PI_SAMR, rpc_sh_user_flag_edit,
+                 "Show/Set whether a user locked out" },
+
+               { "pwnotreq", NULL, PI_SAMR, rpc_sh_user_flag_edit,
+                 "Show/Set whether a user does not need a password" },
+
+               { "pwnoexp", NULL, PI_SAMR, rpc_sh_user_flag_edit,
+                 "Show/Set whether a user's password does not expire" },
+
+               { NULL, NULL, 0, NULL, NULL }
+       };
+
+       return cmds;
+}
+
+struct rpc_sh_cmd *net_rpc_user_cmds(TALLOC_CTX *mem_ctx,
+                                    struct rpc_sh_ctx *ctx)
+{
+       static struct rpc_sh_cmd cmds[] = {
+
+               { "list", NULL, PI_SAMR, rpc_sh_user_list,
+                 "List available users" },
+
+               { "info", NULL, PI_SAMR, rpc_sh_user_info,
+                 "List the domain groups a user is member of" },
+
+               { "show", NULL, PI_SAMR, rpc_sh_user_show,
+                 "Show info about a user" },
+
+               { "edit", net_rpc_user_edit_cmds, 0, NULL, 
+                 "Show/Modify a user's fields" },
+
+               { NULL, NULL, 0, NULL, NULL }
+       };
+
+       return cmds;
+};
+
 /****************************************************************************/
 
 /**
@@ -1580,7 +1955,7 @@ static NTSTATUS get_sid_from_name(struct cli_state *cli,
        }
 
        result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1,
-                                     &name, &sids, &types);
+                                     &name, NULL, &sids, &types);
 
        if (NT_STATUS_IS_OK(result)) {
                sid_copy(sid, &sids[0]);
@@ -2581,7 +2956,7 @@ static NTSTATUS rpc_share_add_internals(const DOM_SID *domain_sid,
                                          opt_comment, perms, opt_maxusers,
                                          num_users, path, password, 
                                          level, NULL);
-       return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL;
+       return werror_to_ntstatus(result);
 }
 
 static int rpc_share_add(int argc, const char **argv)
@@ -4291,6 +4666,114 @@ int net_rpc_share(int argc, const char **argv)
        return net_run_function(argc, argv, func, rpc_share_usage);
 }
 
+static NTSTATUS rpc_sh_share_list(TALLOC_CTX *mem_ctx,
+                                 struct rpc_sh_ctx *ctx,
+                                 struct rpc_pipe_client *pipe_hnd,
+                                 int argc, const char **argv)
+{
+       return rpc_share_list_internals(ctx->domain_sid, ctx->domain_name,
+                                       ctx->cli, pipe_hnd, mem_ctx,
+                                       argc, argv);
+}
+
+static NTSTATUS rpc_sh_share_add(TALLOC_CTX *mem_ctx,
+                                struct rpc_sh_ctx *ctx,
+                                struct rpc_pipe_client *pipe_hnd,
+                                int argc, const char **argv)
+{
+       WERROR result;
+
+       if ((argc < 2) || (argc > 3)) {
+               d_fprintf(stderr, "usage: %s <share> <path> [comment]\n",
+                         ctx->whoami);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       result = rpccli_srvsvc_net_share_add(
+               pipe_hnd, mem_ctx, argv[0], STYPE_DISKTREE,
+               (argc == 3) ? argv[2] : "",
+               0, 0, 0, argv[1], NULL, 2, NULL);
+                                            
+       return werror_to_ntstatus(result);
+}
+
+static NTSTATUS rpc_sh_share_delete(TALLOC_CTX *mem_ctx,
+                                   struct rpc_sh_ctx *ctx,
+                                   struct rpc_pipe_client *pipe_hnd,
+                                   int argc, const char **argv)
+{
+       WERROR result;
+
+       if (argc != 1) {
+               d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       result = rpccli_srvsvc_net_share_del(pipe_hnd, mem_ctx, argv[0]);
+       return werror_to_ntstatus(result);
+}
+
+static NTSTATUS rpc_sh_share_info(TALLOC_CTX *mem_ctx,
+                                 struct rpc_sh_ctx *ctx,
+                                 struct rpc_pipe_client *pipe_hnd,
+                                 int argc, const char **argv)
+{
+       SRV_SHARE_INFO info;
+       SRV_SHARE_INFO_2 *info2 = &info.share.info2;
+       WERROR result;
+
+       if (argc != 1) {
+               d_fprintf(stderr, "usage: %s <share>\n", ctx->whoami);
+               return NT_STATUS_INVALID_PARAMETER;
+       }
+
+       result = rpccli_srvsvc_net_share_get_info(
+               pipe_hnd, mem_ctx, argv[0], 2, &info);
+       if (!W_ERROR_IS_OK(result)) {
+               goto done;
+       }
+
+       d_printf("Name:     %s\n",
+                rpcstr_pull_unistr2_talloc(mem_ctx,
+                                           &info2->info_2_str.uni_netname));
+       d_printf("Comment:  %s\n",
+                rpcstr_pull_unistr2_talloc(mem_ctx,
+                                           &info2->info_2_str.uni_remark));
+       
+       d_printf("Path:     %s\n",
+                rpcstr_pull_unistr2_talloc(mem_ctx,
+                                           &info2->info_2_str.uni_path));
+       d_printf("Password: %s\n",
+                rpcstr_pull_unistr2_talloc(mem_ctx,
+                                           &info2->info_2_str.uni_passwd));
+
+ done:
+       return werror_to_ntstatus(result);
+}
+
+struct rpc_sh_cmd *net_rpc_share_cmds(TALLOC_CTX *mem_ctx,
+                                     struct rpc_sh_ctx *ctx)
+{
+       static struct rpc_sh_cmd cmds[] = {
+
+       { "list", NULL, PI_SRVSVC, rpc_sh_share_list,
+         "List available shares" },
+
+       { "add", NULL, PI_SRVSVC, rpc_sh_share_add,
+         "Add a share" },
+
+       { "delete", NULL, PI_SRVSVC, rpc_sh_share_delete,
+         "Delete a share" },
+
+       { "info", NULL, PI_SRVSVC, rpc_sh_share_info,
+         "Get information about a share" },
+
+       { NULL, NULL, 0, NULL, NULL }
+       };
+
+       return cmds;
+};
+
 /****************************************************************************/
 
 static int rpc_file_usage(int argc, const char **argv)
@@ -5011,7 +5494,6 @@ static int rpc_trustdom_establish(int argc, const char **argv)
        TALLOC_CTX *mem_ctx;
        NTSTATUS nt_status;
        DOM_SID *domain_sid;
-       smb_ucs2_t *uni_domain_name;
        
        char* domain_name;
        char* domain_name_pol;
@@ -5119,13 +5601,6 @@ static int rpc_trustdom_establish(int argc, const char **argv)
                return -1;
        }
 
-       if (push_ucs2_talloc(mem_ctx, &uni_domain_name, domain_name_pol) == (size_t)-1) {
-               DEBUG(0, ("Could not convert domain name %s to unicode\n",
-                         domain_name_pol));
-               cli_shutdown(cli);
-               return -1;
-       }
-
        /* There should be actually query info level 3 (following nt serv behaviour),
           but I still don't know if it's _really_ necessary */
                        
@@ -5134,10 +5609,8 @@ static int rpc_trustdom_establish(int argc, const char **argv)
         */
 
        if (!secrets_store_trusted_domain_password(domain_name,
-                                                  uni_domain_name,
-                                                  strlen_w(uni_domain_name)+1,
                                                   opt_password,
-                                                  *domain_sid)) {
+                                                  domain_sid)) {
                DEBUG(0, ("Storing password for trusted domain failed.\n"));
                cli_shutdown(cli);
                return -1;
@@ -5253,7 +5726,6 @@ static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
        LSA_TRUSTED_DOMAIN_INFO *info;
        char *cleartextpwd = NULL;
        DATA_BLOB data;
-       smb_ucs2_t *uni_dom_name;
 
        nt_status = rpccli_lsa_query_trusted_domain_info_by_sid(pipe_hnd, mem_ctx, pol, 4, &dom_sid, &info);
        
@@ -5276,18 +5748,9 @@ static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd,
                goto done;
        }
        
-       if (push_ucs2_talloc(mem_ctx, &uni_dom_name, trusted_dom_name) == (size_t)-1) {
-               DEBUG(0, ("Could not convert domain name %s to unicode\n",
-                         trusted_dom_name));
-               nt_status = NT_STATUS_UNSUCCESSFUL;
-               goto done;
-       }
-
        if (!secrets_store_trusted_domain_password(trusted_dom_name,
-                                                  uni_dom_name,
-                                                  strlen_w(uni_dom_name)+1,
                                                   cleartextpwd,
-                                                  dom_sid)) {
+                                                  &dom_sid)) {
                DEBUG(0, ("Storing password for trusted domain failed.\n"));
                nt_status = NT_STATUS_UNSUCCESSFUL;
                goto done;
@@ -6163,7 +6626,6 @@ int net_rpc_help(int argc, const char **argv)
        return (net_run_function(argc, argv, func, rpc_user_usage));
 }
 
-
 /** 
  * 'net rpc' entrypoint.
  * @param argc  Standard main() style argc
@@ -6194,6 +6656,7 @@ int net_rpc(int argc, const char **argv)
                {"rights", net_rpc_rights},
                {"service", net_rpc_service},
                {"registry", net_rpc_registry},
+               {"shell", net_rpc_shell},
                {"help", net_rpc_help},
                {NULL, NULL}
        };
index 2c15fef5a09e912301f41cc3768e74add072cc78..2f02b40948366b6a106a1a2e99488e7be73efaaf 100644 (file)
@@ -75,7 +75,8 @@ static NTSTATUS name_to_sid(struct rpc_pipe_client *pipe_hnd,
        if ( !NT_STATUS_IS_OK(result) )
                return result;
 
-       result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &pol, 1, &name, &sids, &sid_types);
+       result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &pol, 1, &name,
+                                        NULL, &sids, &sid_types);
        
        if ( NT_STATUS_IS_OK(result) )
                sid_copy( sid, &sids[0] );
@@ -488,7 +489,7 @@ static NTSTATUS rpc_rights_revoke_internal(const DOM_SID *domain_sid,
 
 done:
        if ( !NT_STATUS_IS_OK(result) ) {
-               d_fprintf(stderr, "Failed to revoke privileges for %s (%s)", 
+               d_fprintf(stderr, "Failed to revoke privileges for %s (%s)\n", 
                        argv[0], nt_errstr(result));
        }
        
@@ -560,3 +561,53 @@ int net_rpc_rights(int argc, const char **argv)
                
        return net_help_rights( argc, argv );
 }
+
+static NTSTATUS rpc_sh_rights_list(TALLOC_CTX *mem_ctx, struct rpc_sh_ctx *ctx,
+                                  struct rpc_pipe_client *pipe_hnd,
+                                  int argc, const char **argv)
+{
+       return rpc_rights_list_internal(ctx->domain_sid, ctx->domain_name,
+                                       ctx->cli, pipe_hnd, mem_ctx,
+                                       argc, argv);
+}
+
+static NTSTATUS rpc_sh_rights_grant(TALLOC_CTX *mem_ctx,
+                                   struct rpc_sh_ctx *ctx,
+                                   struct rpc_pipe_client *pipe_hnd,
+                                   int argc, const char **argv)
+{
+       return rpc_rights_grant_internal(ctx->domain_sid, ctx->domain_name,
+                                        ctx->cli, pipe_hnd, mem_ctx,
+                                        argc, argv);
+}
+
+static NTSTATUS rpc_sh_rights_revoke(TALLOC_CTX *mem_ctx,
+                                    struct rpc_sh_ctx *ctx,
+                                    struct rpc_pipe_client *pipe_hnd,
+                                    int argc, const char **argv)
+{
+       return rpc_rights_revoke_internal(ctx->domain_sid, ctx->domain_name,
+                                         ctx->cli, pipe_hnd, mem_ctx,
+                                         argc, argv);
+}
+
+struct rpc_sh_cmd *net_rpc_rights_cmds(TALLOC_CTX *mem_ctx,
+                                      struct rpc_sh_ctx *ctx)
+{
+       static struct rpc_sh_cmd cmds[] = {
+
+       { "list", NULL, PI_LSARPC, rpc_sh_rights_list,
+         "View available or assigned privileges" },
+
+       { "grant", NULL, PI_LSARPC, rpc_sh_rights_grant,
+         "Assign privilege[s]" },
+
+       { "revoke", NULL, PI_LSARPC, rpc_sh_rights_revoke,
+         "Revoke privilege[s]" },
+
+       { NULL, NULL, 0, NULL, NULL }
+       };
+
+       return cmds;
+};
+
index 09e62d9defa3a88fb778052be9268cc595496c49..45fdfbfad3ef2ed06dc7ba60fce3e1a4a05573b5 100644 (file)
@@ -559,7 +559,7 @@ static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta)
                sam_account_from_delta(sam_account, delta);
                DEBUG(3, ("Attempting to update user SID %s for user %s in the passdb\n", 
                          sid_to_string(sid_string, &user_sid), pdb_get_username(sam_account)));
-               if (!pdb_update_sam_account(sam_account)) {
+               if (!NT_STATUS_IS_OK(pdb_update_sam_account(sam_account))) {
                        DEBUG(1, ("SAM Account for %s failed to be updated in the passdb!\n",
                                  account));
                        pdb_free_sam(&sam_account);
@@ -835,145 +835,6 @@ static NTSTATUS fetch_alias_info(uint32 rid, SAM_ALIAS_INFO *delta,
 
 static NTSTATUS fetch_alias_mem(uint32 rid, SAM_ALIAS_MEM_INFO *delta, DOM_SID dom_sid)
 {
-#if 0  /* 
-        * commented out right now after talking to Volker.  Can't
-        * do much with the membership but seemed a shame to waste
-        * somewhat working code.  Needs testing because the membership
-        * that shows up surprises me.  Also can't do much with groups
-        * in groups (e.g. Domain Admins being a member of Adminsitrators).
-        * --jerry
-        */
-       
-       int i;
-       TALLOC_CTX *t = NULL;
-       char **nt_members = NULL;
-       char **unix_members;
-       DOM_SID group_sid;
-       GROUP_MAP map;
-       struct group *grp;
-       enum SID_NAME_USE sid_type;
-
-       if (delta->num_members == 0) {
-               return NT_STATUS_OK;
-       }
-
-       sid_copy(&group_sid, &dom_sid);
-       sid_append_rid(&group_sid, rid);
-
-       if (sid_equal(&dom_sid, &global_sid_Builtin)) {
-               sid_type = SID_NAME_WKN_GRP;
-               if (!get_builtin_group_from_sid(&group_sid, &map, False)) {
-                       DEBUG(0, ("Could not find builtin group %s\n", sid_string_static(&group_sid)));
-                       return NT_STATUS_NO_SUCH_GROUP;
-               }
-       } else {
-               sid_type = SID_NAME_ALIAS;
-               if (!get_local_group_from_sid(&group_sid, &map, False)) {
-                       DEBUG(0, ("Could not find local group %s\n", sid_string_static(&group_sid)));
-                       return NT_STATUS_NO_SUCH_GROUP;
-               }
-       }       
-
-       if (!(grp = getgrgid(map.gid))) {
-               DEBUG(0, ("Could not find unix group %d\n", map.gid));
-               return NT_STATUS_NO_SUCH_GROUP;
-       }
-
-       d_printf("Group members of %s: ", grp->gr_name);
-
-       if (!(t = talloc_init("fetch_group_mem_info"))) {
-               DEBUG(0, ("could not talloc_init\n"));
-               return NT_STATUS_NO_MEMORY;
-       }
-
-       nt_members = TALLOC_ZERO_ARRAY(t, char *, delta->num_members);
-
-       for (i=0; i<delta->num_members; i++) {
-               NTSTATUS nt_status;
-               SAM_ACCOUNT *member = NULL;
-               DOM_SID member_sid;
-
-               if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_talloc(t, &member))) {
-                       talloc_destroy(t);
-                       return nt_status;
-               }
-
-               sid_copy(&member_sid, &delta->sids[i].sid);
-
-               if (!pdb_getsampwsid(member, &member_sid)) {
-                       DEBUG(1, ("Found bogus group member: (member_sid=%s group=%s)\n",
-                                 sid_string_static(&member_sid), grp->gr_name));
-                       pdb_free_sam(&member);
-                       continue;
-               }
-
-               if (pdb_get_group_rid(member) == rid) {
-                       d_printf("%s(primary),", pdb_get_username(member));
-                       pdb_free_sam(&member);
-                       continue;
-               }
-               
-               d_printf("%s,", pdb_get_username(member));
-               nt_members[i] = talloc_strdup(t, pdb_get_username(member));
-               pdb_free_sam(&member);
-       }
-
-       d_printf("\n");
-
-       unix_members = grp->gr_mem;
-
-       while (*unix_members) {
-               BOOL is_nt_member = False;
-               for (i=0; i<delta->num_members; i++) {
-                       if (nt_members[i] == NULL) {
-                               /* This was a primary group */
-                               continue;
-                       }
-
-                       if (strcmp(*unix_members, nt_members[i]) == 0) {
-                               is_nt_member = True;
-                               break;
-                       }
-               }
-               if (!is_nt_member) {
-                       /* We look at a unix group member that is not
-                          an nt group member. So, remove it. NT is
-                          boss here. */
-                       smb_delete_user_group(grp->gr_name, *unix_members);
-               }
-               unix_members += 1;
-       }
-
-       for (i=0; i<delta->num_members; i++) {
-               BOOL is_unix_member = False;
-
-               if (nt_members[i] == NULL) {
-                       /* This was the primary group */
-                       continue;
-               }
-
-               unix_members = grp->gr_mem;
-
-               while (*unix_members) {
-                       if (strcmp(*unix_members, nt_members[i]) == 0) {
-                               is_unix_member = True;
-                               break;
-                       }
-                       unix_members += 1;
-               }
-
-               if (!is_unix_member) {
-                       /* We look at a nt group member that is not a
-                           unix group member currently. So, add the nt
-                           group member. */
-                       smb_add_user_group(grp->gr_name, nt_members[i]);
-               }
-       }
-       
-       talloc_destroy(t);
-
-#endif /* end of fetch_alias_mem() */
-
        return NT_STATUS_OK;
 }
 
diff --git a/source3/utils/net_rpc_shell.c b/source3/utils/net_rpc_shell.c
new file mode 100644 (file)
index 0000000..f9675e4
--- /dev/null
@@ -0,0 +1,270 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *  Shell around net rpc subcommands
+ *  Copyright (C) Volker Lendecke 2006
+ *
+ *  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"
+#include "utils/net.h"
+
+static struct rpc_sh_cmd sh_cmds[];
+
+static NTSTATUS rpc_sh_info(TALLOC_CTX *mem_ctx, struct rpc_sh_ctx *ctx,
+                           struct rpc_pipe_client *pipe_hnd,
+                           int argc, const char **argv)
+{
+       return rpc_info_internals(ctx->domain_sid, ctx->domain_name,
+                                 ctx->cli, pipe_hnd, mem_ctx,
+                                 argc, argv);
+}
+
+static struct rpc_sh_ctx *this_ctx;
+
+static char **completion_fn(const char *text, int start, int end)
+{
+       char **cmds = NULL;
+       int n_cmds = 0;
+       struct rpc_sh_cmd *c;
+
+       if (start != 0) {
+               return NULL;
+       }
+
+       ADD_TO_ARRAY(NULL, char *, SMB_STRDUP(text), &cmds, &n_cmds);
+
+       for (c = this_ctx->cmds; c->name != NULL; c++) {
+               BOOL match = (strncmp(text, c->name, strlen(text)) == 0);
+
+               if (match) {
+                       ADD_TO_ARRAY(NULL, char *, SMB_STRDUP(c->name),
+                                    &cmds, &n_cmds);
+               }
+       }
+
+       if (n_cmds == 2) {
+               SAFE_FREE(cmds[0]);
+               cmds[0] = cmds[1];
+               n_cmds -= 1;
+       }
+
+       ADD_TO_ARRAY(NULL, char *, NULL, &cmds, &n_cmds);
+       return cmds;
+}
+
+static NTSTATUS net_sh_run(struct rpc_sh_ctx *ctx, struct rpc_sh_cmd *cmd,
+                          int argc, const char **argv)
+{
+       TALLOC_CTX *mem_ctx;
+       struct rpc_pipe_client *pipe_hnd;
+       NTSTATUS status;
+
+       mem_ctx = talloc_new(ctx);
+       if (mem_ctx == NULL) {
+               d_fprintf(stderr, "talloc_new failed\n");
+               return NT_STATUS_NO_MEMORY;
+       }
+
+       pipe_hnd = cli_rpc_pipe_open_noauth(ctx->cli, cmd->pipe_idx, &status);
+       if (pipe_hnd == NULL) {
+               d_fprintf(stderr, "Could not open pipe: %s\n",
+                         nt_errstr(status));
+               return status;
+       }
+
+       status = cmd->fn(mem_ctx, ctx, pipe_hnd, argc, argv);
+
+       cli_rpc_pipe_close(pipe_hnd);
+
+       talloc_destroy(mem_ctx);
+
+       return status;
+}
+
+static BOOL net_sh_process(struct rpc_sh_ctx *ctx,
+                          int argc, const char **argv)
+{
+       struct rpc_sh_cmd *c;
+       struct rpc_sh_ctx *new_ctx;
+       NTSTATUS status;
+
+       if (argc == 0) {
+               return True;
+       }
+
+       if (ctx == this_ctx) {
+
+               /* We've been called from the cmd line */
+               if (strequal(argv[0], "..") &&
+                   (this_ctx->parent != NULL)) {
+                       new_ctx = this_ctx->parent;
+                       talloc_free(this_ctx);
+                       this_ctx = new_ctx;
+                       return True;
+               }
+       }
+
+       if (strequal(argv[0], "help") || strequal(argv[0], "?")) {
+               for (c = ctx->cmds; c->name != NULL; c++) {
+                       if (ctx != this_ctx) {
+                               d_printf("%s ", ctx->whoami);
+                       }
+                       d_printf("%-15s %s\n", c->name, c->help);
+               }
+               return True;
+       }
+
+       for (c = ctx->cmds; c->name != NULL; c++) {
+               if (strequal(c->name, argv[0])) {
+                       break;
+               }
+       }
+
+       if (c->name == NULL) {
+               /* None found */
+               d_fprintf(stderr, "%s: unknown cmd\n", argv[0]);
+               return True;
+       }
+
+       new_ctx = TALLOC_P(ctx, struct rpc_sh_ctx);
+       if (new_ctx == NULL) {
+               d_fprintf(stderr, "talloc failed\n");
+               return False;
+       }
+       new_ctx->cli = ctx->cli;
+       new_ctx->whoami = talloc_asprintf(new_ctx, "%s %s",
+                                         ctx->whoami, c->name);
+       new_ctx->thiscmd = talloc_strdup(new_ctx, c->name);
+
+       if (c->sub != NULL) {
+               new_ctx->cmds = c->sub(new_ctx, ctx);
+       } else {
+               new_ctx->cmds = NULL;
+       }
+
+       new_ctx->parent = ctx;
+       new_ctx->domain_name = ctx->domain_name;
+       new_ctx->domain_sid = ctx->domain_sid;
+
+       argc -= 1;
+       argv += 1;
+
+       if (c->sub != NULL) {
+               if (argc == 0) {
+                       this_ctx = new_ctx;
+                       return True;
+               }
+               return net_sh_process(new_ctx, argc, argv);
+       }
+
+       status = net_sh_run(new_ctx, c, argc, argv);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "%s failed: %s\n", new_ctx->whoami,
+                         nt_errstr(status));
+       }
+
+       return True;
+}
+
+int net_rpc_shell(int argc, const char **argv)
+{
+       NTSTATUS status;
+       struct rpc_sh_ctx *ctx;
+
+       if (argc != 0) {
+               d_fprintf(stderr, "usage: net rpc shell\n");
+               return -1;
+       }
+
+       ctx = TALLOC_P(NULL, struct rpc_sh_ctx);
+       if (ctx == NULL) {
+               d_fprintf(stderr, "talloc failed\n");
+               return -1;
+       }
+
+       ctx->cli = net_make_ipc_connection(0);
+       if (ctx->cli == NULL) {
+               d_fprintf(stderr, "Could not open connection\n");
+               return -1;
+       }
+
+       ctx->cmds = sh_cmds;
+       ctx->whoami = "net rpc";
+       ctx->parent = NULL;
+
+       status = net_get_remote_domain_sid(ctx->cli, ctx, &ctx->domain_sid,
+                                          &ctx->domain_name);
+       if (!NT_STATUS_IS_OK(status)) {
+               return -1;
+       }
+
+       d_printf("Talking to domain %s (%s)\n", ctx->domain_name,
+                sid_string_static(ctx->domain_sid));
+       
+       this_ctx = ctx;
+
+       while(1) {
+               char *prompt;
+               char *line;
+               int ret;
+
+               asprintf(&prompt, "%s> ", this_ctx->whoami);
+
+               line = smb_readline(prompt, NULL, completion_fn);
+               SAFE_FREE(prompt);
+
+               if (line == NULL) {
+                       break;
+               }
+
+               ret = poptParseArgvString(line, &argc, &argv);
+               if (ret != 0) {
+                       d_fprintf(stderr, "cmdline invalid: %s\n",
+                                 poptStrerror(ret));
+                       return False;
+               }
+
+               if ((line[0] != '\n') &&
+                   (!net_sh_process(this_ctx, argc, argv))) {
+                       break;
+               }
+       }
+
+       cli_shutdown(ctx->cli);
+
+       talloc_free(ctx);
+
+       return 0;
+}
+
+static struct rpc_sh_cmd sh_cmds[] = {
+
+       { "info", NULL, PI_SAMR, rpc_sh_info,
+         "Print information about the domain connected to" },
+
+       { "rights", net_rpc_rights_cmds, 0, NULL,
+         "List/Grant/Revoke user rights" },
+
+       { "share", net_rpc_share_cmds, 0, NULL,
+         "List/Add/Remove etc shares" },
+
+       { "user", net_rpc_user_cmds, 0, NULL,
+         "List/Add/Remove user info" },
+
+       { NULL, NULL, 0, NULL, NULL }
+};
diff --git a/source3/utils/net_sam.c b/source3/utils/net_sam.c
new file mode 100644 (file)
index 0000000..ba3ec5c
--- /dev/null
@@ -0,0 +1,784 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *  Local SAM access routines
+ *  Copyright (C) Volker Lendecke 2006
+ *
+ *  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"
+#include "utils/net.h"
+
+/*
+ * Set a user's data
+ */
+
+static int net_sam_userset(int argc, const char **argv, const char *field,
+                          BOOL (*fn)(SAM_ACCOUNT *, const char *,
+                                     enum pdb_value_state))
+{
+       SAM_ACCOUNT *sam_acct = NULL;
+       DOM_SID sid;
+       enum SID_NAME_USE type;
+       const char *dom, *name;
+       NTSTATUS status;
+
+       if (argc != 2) {
+               d_fprintf(stderr, "usage: net sam set %s <user> <value>\n",
+                         field);
+               return -1;
+       }
+
+       if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED,
+                        &dom, &name, &sid, &type)) {
+               d_fprintf(stderr, "Could not find name %s\n", argv[0]);
+               return -1;
+       }
+
+       if (type != SID_NAME_USER) {
+               d_fprintf(stderr, "%s is a %s, not a user\n", argv[0],
+                         sid_type_lookup(type));
+               return -1;
+       }
+
+       if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_acct))) {
+               d_fprintf(stderr, "Internal error\n");
+               return -1;
+       }
+
+       if (!pdb_getsampwsid(sam_acct, &sid)) {
+               d_fprintf(stderr, "Loading user %s failed\n", argv[0]);
+               return -1;
+       }
+
+       if (!fn(sam_acct, argv[1], PDB_CHANGED)) {
+               d_fprintf(stderr, "Internal error\n");
+               return -1;
+       }
+
+       status = pdb_update_sam_account(sam_acct);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "Updating sam account %s failed with %s\n",
+                         argv[0], nt_errstr(status));
+               return -1;
+       }
+
+       pdb_free_sam(&sam_acct);
+
+       d_printf("Updated %s for %s\\%s to %s\n", field, dom, name, argv[1]);
+       return 0;
+}
+
+static int net_sam_set_fullname(int argc, const char **argv)
+{
+       return net_sam_userset(argc, argv, "fullname",
+                              pdb_set_fullname);
+}
+
+static int net_sam_set_logonscript(int argc, const char **argv)
+{
+       return net_sam_userset(argc, argv, "logonscript",
+                              pdb_set_logon_script);
+}
+
+static int net_sam_set_profilepath(int argc, const char **argv)
+{
+       return net_sam_userset(argc, argv, "profilepath",
+                              pdb_set_profile_path);
+}
+
+static int net_sam_set_homedrive(int argc, const char **argv)
+{
+       return net_sam_userset(argc, argv, "homedrive",
+                              pdb_set_dir_drive);
+}
+
+static int net_sam_set_homedir(int argc, const char **argv)
+{
+       return net_sam_userset(argc, argv, "homedir",
+                              pdb_set_homedir);
+}
+
+static int net_sam_set_workstations(int argc, const char **argv)
+{
+       return net_sam_userset(argc, argv, "workstations",
+                              pdb_set_workstations);
+}
+
+/*
+ * Set account flags
+ */
+
+static int net_sam_set_userflag(int argc, const char **argv, const char *field,
+                               uint16 flag)
+{
+       SAM_ACCOUNT *sam_acct = NULL;
+       DOM_SID sid;
+       enum SID_NAME_USE type;
+       const char *dom, *name;
+       NTSTATUS status;
+       uint16 acct_flags;
+
+       if ((argc != 2) || (!strequal(argv[1], "yes") &&
+                           !strequal(argv[1], "no"))) {
+               d_fprintf(stderr, "usage: net sam set %s <user> [yes|no]\n",
+                         field);
+               return -1;
+       }
+
+       if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED,
+                        &dom, &name, &sid, &type)) {
+               d_fprintf(stderr, "Could not find name %s\n", argv[0]);
+               return -1;
+       }
+
+       if (type != SID_NAME_USER) {
+               d_fprintf(stderr, "%s is a %s, not a user\n", argv[0],
+                         sid_type_lookup(type));
+               return -1;
+       }
+
+       if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_acct))) {
+               d_fprintf(stderr, "Internal error\n");
+               return -1;
+       }
+
+       if (!pdb_getsampwsid(sam_acct, &sid)) {
+               d_fprintf(stderr, "Loading user %s failed\n", argv[0]);
+               return -1;
+       }
+
+       acct_flags = pdb_get_acct_ctrl(sam_acct);
+
+       if (strequal(argv[1], "yes")) {
+               acct_flags |= flag;
+       } else {
+               acct_flags &= ~flag;
+       }
+
+       pdb_set_acct_ctrl(sam_acct, acct_flags, PDB_CHANGED);
+
+       status = pdb_update_sam_account(sam_acct);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "Updating sam account %s failed with %s\n",
+                         argv[0], nt_errstr(status));
+               return -1;
+       }
+
+       pdb_free_sam(&sam_acct);
+
+       d_fprintf(stderr, "Updated flag %s for %s\\%s to %s\n", field, dom,
+                 name, argv[1]);
+       return 0;
+}
+
+static int net_sam_set_disabled(int argc, const char **argv)
+{
+       return net_sam_set_userflag(argc, argv, "disabled", ACB_DISABLED);
+}
+
+static int net_sam_set_pwnotreq(int argc, const char **argv)
+{
+       return net_sam_set_userflag(argc, argv, "pwnotreq", ACB_PWNOTREQ);
+}
+
+static int net_sam_set_autolock(int argc, const char **argv)
+{
+       return net_sam_set_userflag(argc, argv, "autolock", ACB_AUTOLOCK);
+}
+
+static int net_sam_set_pwnoexp(int argc, const char **argv)
+{
+       return net_sam_set_userflag(argc, argv, "pwnoexp", ACB_PWNOEXP);
+}
+
+/*
+ * Set a user's time field
+ */
+
+static int net_sam_set_time(int argc, const char **argv, const char *field,
+                           BOOL (*fn)(SAM_ACCOUNT *, time_t,
+                                      enum pdb_value_state))
+{
+       SAM_ACCOUNT *sam_acct = NULL;
+       DOM_SID sid;
+       enum SID_NAME_USE type;
+       const char *dom, *name;
+       NTSTATUS status;
+       time_t new_time;
+
+       if (argc != 2) {
+               d_fprintf(stderr, "usage: net sam set %s <user> "
+                         "[now|YYYY-MM-DD HH:MM]\n", field);
+               return -1;
+       }
+
+       if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED,
+                        &dom, &name, &sid, &type)) {
+               d_fprintf(stderr, "Could not find name %s\n", argv[0]);
+               return -1;
+       }
+
+       if (type != SID_NAME_USER) {
+               d_fprintf(stderr, "%s is a %s, not a user\n", argv[0],
+                         sid_type_lookup(type));
+               return -1;
+       }
+
+       if (strequal(argv[1], "now")) {
+               new_time = time(NULL);
+       } else {
+               struct tm tm;
+               char *end;
+               ZERO_STRUCT(tm);
+               end = strptime(argv[1], "%Y-%m-%d %H:%M", &tm);
+               new_time = mktime(&tm);
+               if ((end == NULL) || (*end != '\0') || (new_time == -1)) {
+                       d_fprintf(stderr, "Could not parse time string %s\n",
+                                 argv[1]);
+                       return -1;
+               }
+       }
+
+
+       if (!NT_STATUS_IS_OK(pdb_init_sam(&sam_acct))) {
+               d_fprintf(stderr, "Internal error\n");
+               return -1;
+       }
+
+       if (!pdb_getsampwsid(sam_acct, &sid)) {
+               d_fprintf(stderr, "Loading user %s failed\n", argv[0]);
+               return -1;
+       }
+
+       if (!fn(sam_acct, new_time, PDB_CHANGED)) {
+               d_fprintf(stderr, "Internal error\n");
+               return -1;
+       }
+
+       status = pdb_update_sam_account(sam_acct);
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "Updating sam account %s failed with %s\n",
+                         argv[0], nt_errstr(status));
+               return -1;
+       }
+
+       pdb_free_sam(&sam_acct);
+
+       d_printf("Updated %s for %s\\%s to %s\n", field, dom, name, argv[1]);
+       return 0;
+}
+
+static int net_sam_set_pwdmustchange(int argc, const char **argv)
+{
+       return net_sam_set_time(argc, argv, "pwdmustchange",
+                               pdb_set_pass_must_change_time);
+}
+
+static int net_sam_set_pwdcanchange(int argc, const char **argv)
+{
+       return net_sam_set_time(argc, argv, "pwdcanchange",
+                               pdb_set_pass_can_change_time);
+}
+
+/*
+ * Set a user's or a group's comment
+ */
+
+static int net_sam_set_comment(int argc, const char **argv)
+{
+       GROUP_MAP map;
+       DOM_SID sid;
+       enum SID_NAME_USE type;
+       const char *dom, *name;
+       NTSTATUS status;
+
+       if (argc != 2) {
+               d_fprintf(stderr, "usage: net sam set comment <name> "
+                         "<comment>\n");
+               return -1;
+       }
+
+       if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED,
+                        &dom, &name, &sid, &type)) {
+               d_fprintf(stderr, "Could not find name %s\n", argv[0]);
+               return -1;
+       }
+
+       if (type == SID_NAME_USER) {
+               return net_sam_userset(argc, argv, "comment",
+                                      pdb_set_acct_desc);
+       }
+
+       if ((type != SID_NAME_DOM_GRP) && (type != SID_NAME_ALIAS) &&
+           (type != SID_NAME_WKN_GRP)) {
+               d_fprintf(stderr, "%s is a %s, not a group\n", argv[0],
+                         sid_type_lookup(type));
+               return -1;
+       }
+
+       if (!pdb_getgrsid(&map, sid)) {
+               d_fprintf(stderr, "Could not load group %s\n", argv[0]);
+               return -1;
+       }
+
+       fstrcpy(map.comment, argv[1]);
+
+       status = pdb_update_group_mapping_entry(&map);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "Updating group mapping entry failed with "
+                         "%s\n", nt_errstr(status));
+               return -1;
+       }
+
+       d_printf("Updated comment of group %s\\%s to %s\n", dom, name,
+                argv[1]);
+
+       return 0;
+}
+
+static int net_sam_set(int argc, const char **argv)
+{
+       struct functable2 func[] = {
+               { "homedir", net_sam_set_homedir,
+                 "Change a user's home directory" },
+               { "profilepath", net_sam_set_profilepath,
+                 "Change a user's profile path" },
+               { "comment", net_sam_set_comment,
+                 "Change a users or groups description" },
+               { "fullname", net_sam_set_fullname,
+                 "Change a user's full name" },
+               { "logonscript", net_sam_set_logonscript,
+                 "Change a user's logon script" },
+               { "homedrive", net_sam_set_homedrive,
+                 "Change a user's home drive" },
+               { "workstations", net_sam_set_workstations,
+                 "Change a user's allowed workstations" },
+               { "disabled", net_sam_set_disabled,
+                 "Disable/Enable a user" },
+               { "pwnotreq", net_sam_set_pwnotreq,
+                 "Disable/Enable the password not required flag" },
+               { "autolock", net_sam_set_autolock,
+                 "Disable/Enable a user's lockout flag" },
+               { "pwnoexp", net_sam_set_pwnoexp,
+                 "Disable/Enable whether a user's pw does not expire" },
+               { "pwdmustchange", net_sam_set_pwdmustchange,
+                 "Set a users password must change time" },
+               { "pwdcanchange", net_sam_set_pwdcanchange,
+                 "Set a users password can change time" },
+               {NULL, NULL}
+       };
+
+       return net_run_function2(argc, argv, "net sam set", func);
+}
+
+/*
+ * Map a unix group to a domain group
+ */
+
+static int net_sam_mapunixgroup(int argc, const char **argv)
+{
+       NTSTATUS status;
+       GROUP_MAP map;
+       struct group *grp;
+
+       if (argc != 1) {
+               d_fprintf(stderr, "usage: net sam mapunixgroup <name>\n");
+               return -1;
+       }
+
+       grp = getgrnam(argv[0]);
+       if (grp == NULL) {
+               d_fprintf(stderr, "Could not find group %s\n", argv[0]);
+               return -1;
+       }
+
+       status = map_unix_group(grp, &map);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "Mapping group %s failed with %s\n",
+                         argv[0], nt_errstr(status));
+               return -1;
+       }
+
+       d_printf("Mapped unix group %s to SID %s\n", argv[0],
+                sid_string_static(&map.sid));
+
+       return 0;
+}
+
+/*
+ * Create a local group
+ */
+
+static int net_sam_createlocalgroup(int argc, const char **argv)
+{
+       NTSTATUS status;
+       uint32 rid;
+
+       if (argc != 1) {
+               d_fprintf(stderr, "usage: net sam createlocalgroup <name>\n");
+               return -1;
+       }
+
+       if (!winbind_ping()) {
+               d_fprintf(stderr, "winbind seems not to run. createlocalgroup "
+                         "only works when winbind runs.\n");
+               return -1;
+       }
+
+       status = pdb_create_alias(argv[0], &rid);
+
+       if (!NT_STATUS_IS_OK(status)) {
+               d_fprintf(stderr, "Creating %s failed with %s\n",
+                         argv[0], nt_errstr(status));
+               return -1;
+       }
+
+       d_printf("Created local group %s with RID %d\n", argv[0], rid);
+
+       return 0;
+}
+
+/*
+ * Add a group member
+ */
+
+static int net_sam_addmem(int argc, const char **argv)
+{
+       const char *groupdomain, *groupname, *memberdomain, *membername;
+       DOM_SID group, member;
+       enum SID_NAME_USE grouptype, membertype;
+       NTSTATUS status;
+
+       if (argc != 2) {
+               d_fprintf(stderr, "usage: net sam addmem <group> <member>\n");
+               return -1;
+       }
+
+       if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED,
+                        &groupdomain, &groupname, &group, &grouptype)) {
+               d_fprintf(stderr, "Could not find group %s\n", argv[0]);
+               return -1;
+       }
+
+       if (!lookup_name(tmp_talloc_ctx(), argv[1], LOOKUP_NAME_ISOLATED,
+                        &memberdomain, &membername, &member, &membertype)) {
+               d_fprintf(stderr, "Could not find member %s\n", argv[1]);
+               return -1;
+       }
+
+       if ((grouptype == SID_NAME_ALIAS) || (grouptype == SID_NAME_WKN_GRP)) {
+               if ((membertype != SID_NAME_USER) &&
+                   (membertype != SID_NAME_DOM_GRP)) {
+                       d_fprintf(stderr, "%s is a local group, only users "
+                                 "and domain groups can be added.\n"
+                                 "%s is a %s\n", argv[0], argv[1],
+                                 sid_type_lookup(membertype));
+                       return -1;
+               }
+               status = pdb_add_aliasmem(&group, &member);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_fprintf(stderr, "Adding local group member failed "
+                                 "with %s\n", nt_errstr(status));
+                       return -1;
+               }
+       } else {
+               d_fprintf(stderr, "Can only add members to local groups so "
+                         "far, %s is a %s\n", argv[0],
+                         sid_type_lookup(grouptype));
+               return -1;
+       }
+
+       d_printf("Added %s\\%s to %s\\%s\n",
+                memberdomain, membername, groupdomain, groupname);
+
+       return 0;
+}
+
+/*
+ * Delete a group member
+ */
+
+static int net_sam_delmem(int argc, const char **argv)
+{
+       const char *groupdomain, *groupname;
+       const char *memberdomain = NULL;
+       const char *membername = NULL;
+       DOM_SID group, member;
+       enum SID_NAME_USE grouptype;
+       NTSTATUS status;
+
+       if (argc != 2) {
+               d_fprintf(stderr, "usage: net sam delmem <group> <member>\n");
+               return -1;
+       }
+
+       if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED,
+                        &groupdomain, &groupname, &group, &grouptype)) {
+               d_fprintf(stderr, "Could not find group %s\n", argv[0]);
+               return -1;
+       }
+
+       if (!lookup_name(tmp_talloc_ctx(), argv[1], LOOKUP_NAME_ISOLATED,
+                        &memberdomain, &membername, &member, NULL)) {
+               if (!string_to_sid(&member, argv[1])) {
+                       d_fprintf(stderr, "Could not find member %s\n",
+                                 argv[1]);
+                       return -1;
+               }
+       }
+
+       if ((grouptype == SID_NAME_ALIAS) ||
+           (grouptype == SID_NAME_WKN_GRP)) {
+               status = pdb_del_aliasmem(&group, &member);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_fprintf(stderr, "Deleting local group member failed "
+                                 "with %s\n", nt_errstr(status));
+                       return -1;
+               }
+       } else {
+               d_fprintf(stderr, "Can only delete members from local groups "
+                         "so far, %s is a %s\n", argv[0],
+                         sid_type_lookup(grouptype));
+               return -1;
+       }
+
+       if (membername != NULL) {
+               d_printf("Deleted %s\\%s from %s\\%s\n",
+                        memberdomain, membername, groupdomain, groupname);
+       } else {
+               d_printf("Deleted %s from %s\\%s\n",
+                        sid_string_static(&member), groupdomain, groupname);
+       }
+
+       return 0;
+}
+
+/*
+ * List group members
+ */
+
+static int net_sam_listmem(int argc, const char **argv)
+{
+       const char *groupdomain, *groupname;
+       DOM_SID group;
+       enum SID_NAME_USE grouptype;
+       NTSTATUS status;
+
+       if (argc != 1) {
+               d_fprintf(stderr, "usage: net sam listmem <group>\n");
+               return -1;
+       }
+
+       if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED,
+                        &groupdomain, &groupname, &group, &grouptype)) {
+               d_fprintf(stderr, "Could not find group %s\n", argv[0]);
+               return -1;
+       }
+
+       if ((grouptype == SID_NAME_ALIAS) ||
+           (grouptype == SID_NAME_WKN_GRP)) {
+               DOM_SID *members = NULL;
+               size_t i, num_members = 0;
+               
+               status = pdb_enum_aliasmem(&group, &members, &num_members);
+
+               if (!NT_STATUS_IS_OK(status)) {
+                       d_fprintf(stderr, "Listing group members failed with "
+                                 "%s\n", nt_errstr(status));
+                       return -1;
+               }
+
+               d_printf("%s\\%s has %d members\n", groupdomain, groupname,
+                        num_members);
+               for (i=0; i<num_members; i++) {
+                       const char *dom, *name;
+                       if (lookup_sid(tmp_talloc_ctx(), &members[i],
+                                      &dom, &name, NULL)) {
+                               d_printf(" %s\\%s\n", dom, name);
+                       } else {
+                               d_printf(" %s\n",
+                                        sid_string_static(&members[i]));
+                       }
+               }
+       } else {
+               d_fprintf(stderr, "Can only list local group members so far.\n"
+                         "%s is a %s\n", argv[0], sid_type_lookup(grouptype));
+               return -1;
+       }
+
+       return 0;
+}
+
+/*
+ * Do the listing
+ */
+static int net_sam_do_list(int argc, const char **argv,
+                          struct pdb_search *search, const char *what)
+{
+       BOOL verbose = (argc == 1);
+
+       if ((argc > 1) ||
+           ((argc == 1) && !strequal(argv[0], "verbose"))) {
+               d_fprintf(stderr, "usage: net sam list %s [verbose]\n", what);
+               return -1;
+       }
+
+       if (search == NULL) {
+               d_fprintf(stderr, "Could not start search\n");
+               return -1;
+       }
+
+       while (True) {
+               struct samr_displayentry entry;
+               if (!search->next_entry(search, &entry)) {
+                       break;
+               }
+               if (verbose) {
+                       d_printf("%s:%d:%s\n",
+                                entry.account_name,
+                                entry.rid,
+                                entry.description);
+               } else {
+                       d_printf("%s\n", entry.account_name);
+               }
+       }
+
+       search->search_end(search);
+       return 0;
+}
+
+static int net_sam_list_users(int argc, const char **argv)
+{
+       return net_sam_do_list(argc, argv, pdb_search_users(ACB_NORMAL),
+                              "users");
+}
+
+static int net_sam_list_groups(int argc, const char **argv)
+{
+       return net_sam_do_list(argc, argv, pdb_search_groups(), "groups");
+}
+
+static int net_sam_list_localgroups(int argc, const char **argv)
+{
+       return net_sam_do_list(argc, argv,
+                              pdb_search_aliases(get_global_sam_sid()),
+                              "localgroups");
+}
+
+static int net_sam_list_builtin(int argc, const char **argv)
+{
+       return net_sam_do_list(argc, argv,
+                              pdb_search_aliases(&global_sid_Builtin),
+                              "builtin");
+}
+
+static int net_sam_list_workstations(int argc, const char **argv)
+{
+       return net_sam_do_list(argc, argv,
+                              pdb_search_users(ACB_WSTRUST),
+                              "workstations");
+}
+
+/*
+ * List stuff
+ */
+
+static int net_sam_list(int argc, const char **argv)
+{
+       struct functable2 func[] = {
+               { "users", net_sam_list_users,
+                 "List SAM users" },
+               { "groups", net_sam_list_groups,
+                 "List SAM groups" },
+               { "localgroups", net_sam_list_localgroups,
+                 "List SAM local groups" },
+               { "builtin", net_sam_list_builtin,
+                 "List builtin groups" },
+               { "workstations", net_sam_list_workstations,
+                 "List domain member workstations" },
+               {NULL, NULL}
+       };
+
+       return net_run_function2(argc, argv, "net sam list", func);
+}
+
+/*
+ * Show details of SAM entries
+ */
+
+static int net_sam_show(int argc, const char **argv)
+{
+       DOM_SID sid;
+       enum SID_NAME_USE type;
+       const char *dom, *name;
+
+       if (argc != 1) {
+               d_fprintf(stderr, "usage: net sam show <name>\n");
+               return -1;
+       }
+
+       if (!lookup_name(tmp_talloc_ctx(), argv[0], LOOKUP_NAME_ISOLATED,
+                        &dom, &name, &sid, &type)) {
+               d_fprintf(stderr, "Could not find name %s\n", argv[0]);
+               return -1;
+       }
+
+       d_printf("%s\\%s is a %s with SID %s\n", dom, name,
+                sid_type_lookup(type), sid_string_static(&sid));
+
+       return 0;
+}
+
+/***********************************************************
+ migrated functionality from smbgroupedit
+ **********************************************************/
+int net_sam(int argc, const char **argv)
+{
+       struct functable2 func[] = {
+               { "createlocalgroup", net_sam_createlocalgroup,
+                 "Create a new local group" },
+               { "mapunixgroup", net_sam_mapunixgroup,
+                 "Map a unix group to a domain group" },
+               { "addmem", net_sam_addmem,
+                 "Add a member to a group" },
+               { "delmem", net_sam_delmem,
+                 "Delete a member from a group" },
+               { "listmem", net_sam_listmem,
+                 "List group members" },
+               { "list", net_sam_list,
+                 "List users, groups and local groups" },
+               { "show", net_sam_show,
+                 "Show details of a SAM entry" },
+               { "set", net_sam_set,
+                 "Set details of a SAM account" },
+               { NULL, NULL, NULL }
+       };
+
+       /* we shouldn't have silly checks like this */
+       if (getuid() != 0) {
+               d_fprintf(stderr, "You must be root to edit the SAM "
+                         "directly.\n");
+               return -1;
+       }
+       
+       return net_run_function2(argc, argv, "net sam", func);
+}
+
diff --git a/source3/utils/net_usershare.c b/source3/utils/net_usershare.c
new file mode 100644 (file)
index 0000000..c00f239
--- /dev/null
@@ -0,0 +1,829 @@
+/* 
+   Samba Unix/Linux SMB client library 
+   Distributed SMB/CIFS Server Management Utility 
+
+   Copyright (C) Jeremy Allison (jra@samba.org) 2005
+
+   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"
+#include "utils/net.h"
+
+struct {
+       const char *us_errstr;
+       enum usershare_err us_err;
+} us_errs [] = {
+       {"",USERSHARE_OK},
+       {"Malformed usershare file", USERSHARE_MALFORMED_FILE},
+       {"Bad version number", USERSHARE_BAD_VERSION},
+       {"Malformed path entry", USERSHARE_MALFORMED_PATH},
+       {"Malformed comment entryfile", USERSHARE_MALFORMED_COMMENT_DEF},
+       {"Malformed acl definition", USERSHARE_MALFORMED_ACL_DEF},
+       {"Acl parse error", USERSHARE_ACL_ERR},
+       {"Path not absolute", USERSHARE_PATH_NOT_ABSOLUTE},
+       {"Path is denied", USERSHARE_PATH_IS_DENIED},
+       {"Path not allowed", USERSHARE_PATH_NOT_ALLOWED},
+       {"Path is not a directory", USERSHARE_PATH_NOT_DIRECTORY},
+       {"System error", USERSHARE_POSIX_ERR},
+       {NULL,(enum usershare_err)-1}
+};
+
+static const char *get_us_error_code(enum usershare_err us_err)
+{
+       static pstring out;
+       int idx = 0;
+
+       while (us_errs[idx].us_errstr != NULL) {
+               if (us_errs[idx].us_err == us_err) {
+                       return us_errs[idx].us_errstr;
+               }
+               idx++;
+       }
+
+       slprintf(out, sizeof(out), "Usershare error code (0x%x)", (unsigned int)us_err);
+       return out;
+}
+
+/* The help subsystem for the USERSHARE subcommand */
+
+static int net_usershare_add_usage(int argc, const char **argv)
+{
+       char c = *lp_winbind_separator();
+       d_printf(
+               "net usershare add [-l|--long] <sharename> <path> [<comment>] [<acl>]\n"
+               "\tAdds the specified share name for this user.\n"
+               "\t<sharename> is the new share name.\n"
+               "\t<path> is the path on the filesystem to export.\n"
+               "\t<comment> is the optional comment for the new share.\n"
+               "\t<acl> is an optional share acl in the format \"DOMAIN%cname:X,DOMAIN%cname:X,....\"\n"
+               "\t\t\"X\" represents a permission and can be any one of the characters f, r or d\n"
+               "\t\twhere \"f\" means full control, \"r\" means read-only, \"d\" means deny access.\n"
+               "\t\tname may be a domain user or group. For local users use the local server name "
+               "instead of \"DOMAIN\"\n"
+               "\t\tThe default acl is \"Everyone:r\" which allows everyone read-only access.\n"
+               "\tAdd -l or --long to print the info on the newly added share.\n",
+               c, c );
+       return -1;
+}
+
+static int net_usershare_delete_usage(int argc, const char **argv)
+{
+       d_printf(
+               "net usershare delete <sharename>\n"\
+               "\tdeletes the specified share name for this user.\n");
+       return -1;
+}
+
+static int net_usershare_info_usage(int argc, const char **argv)
+{
+       d_printf(
+               "net usershare info [-l|--long] [wildcard sharename]\n"\
+               "\tPrints out the path, comment and acl elements of shares that match the wildcard.\n"
+               "\tBy default only gives info on shares owned by the current user\n"
+               "\tAdd -l or --long to apply this to all shares\n"
+               "\tOmit the sharename or use a wildcard of '*' to see all shares\n");
+       return -1;
+}
+
+static int net_usershare_list_usage(int argc, const char **argv)
+{
+       d_printf(
+               "net usershare list [-l|--long] [wildcard sharename]\n"\
+               "\tLists the names of all shares that match the wildcard.\n"
+               "\tBy default only lists shares owned by the current user\n"
+               "\tAdd -l or --long to apply this to all shares\n"
+               "\tOmit the sharename or use a wildcard of '*' to see all shares\n");
+       return -1;
+}
+
+int net_usershare_usage(int argc, const char **argv)
+{
+       d_printf("net usershare add <sharename> <path> [<comment>] [<acl>] to add or change a user defined share.\n"
+               "net usershare delete <sharename> to delete a user defined share.\n"
+               "net usershare info [-l|--long] [wildcard sharename] to print info about a user defined share.\n"
+               "net usershare list [-l|--long] [wildcard sharename] to list user defined shares.\n"
+               "net usershare help\n"\
+               "\nType \"net usershare help <option>\" to get more information on that option\n\n");
+
+       net_common_flags_usage(argc, argv);
+       return -1;
+}
+
+/***************************************************************************
+***************************************************************************/
+
+static void get_basepath(pstring basepath)
+{
+       pstrcpy(basepath, lp_usershare_path());
+       if (basepath[strlen(basepath)-1] == '/') {
+               basepath[strlen(basepath)-1] = '\0';
+       }
+}
+
+/***************************************************************************
+ Delete a single userlevel share.
+***************************************************************************/
+
+static int net_usershare_delete(int argc, const char **argv)
+{
+       pstring us_path;
+       char *sharename;
+
+       if (argc != 1) {
+               return net_usershare_delete_usage(argc, argv);
+       }
+
+       sharename = strdup_lower(argv[0]);
+
+       if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS, strlen(sharename))) {
+               d_fprintf(stderr, "net usershare delete: share name %s contains "
+                        "invalid characters (any of %s)\n",
+                        sharename, INVALID_SHARENAME_CHARS);
+               SAFE_FREE(sharename);
+               return -1;
+       }
+
+       pstrcpy(us_path, lp_usershare_path());
+       pstrcat(us_path, "/");
+       pstrcat(us_path, sharename);
+
+       if (unlink(us_path) != 0) {
+               d_fprintf(stderr, "net usershare delete: unable to remove usershare %s. "
+                       "Error was %s\n",
+                        us_path, strerror(errno));
+               SAFE_FREE(sharename);
+               return -1;
+       }
+       SAFE_FREE(sharename);
+       return 0;
+}
+
+/***************************************************************************
+ Data structures to handle a list of usershare files.
+***************************************************************************/
+
+struct file_list {
+       struct file_list *next, *prev;
+       const char *pathname;
+};
+
+static struct file_list *flist;
+
+/***************************************************************************
+***************************************************************************/
+
+static int get_share_list(TALLOC_CTX *ctx, const char *wcard, BOOL only_ours)
+{
+       SMB_STRUCT_DIR *dp;
+       SMB_STRUCT_DIRENT *de;
+       uid_t myuid = geteuid();
+       struct file_list *fl = NULL;
+       pstring basepath;
+
+       get_basepath(basepath);
+       dp = sys_opendir(basepath);
+       if (!dp) {
+               d_fprintf(stderr, "get_share_list: cannot open usershare directory %s. Error %s\n",
+                       basepath, strerror(errno) );
+               return -1;
+       }
+
+       while((de = sys_readdir(dp)) != 0) {
+               SMB_STRUCT_STAT sbuf;
+               pstring path;
+               const char *n = de->d_name;
+
+               /* Ignore . and .. */
+               if (*n == '.') {
+                       if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
+                               continue;
+                       }
+               }
+
+               if (!validate_net_name(n, INVALID_SHARENAME_CHARS, strlen(n))) {
+                       d_fprintf(stderr, "get_share_list: ignoring bad share name %s\n",n);
+                       continue;
+               }
+               pstrcpy(path, basepath);
+               pstrcat(path, "/");
+               pstrcat(path, n);
+
+               if (sys_lstat(path, &sbuf) != 0) {
+                       d_fprintf(stderr, "get_share_list: can't lstat file %s. Error was %s\n",
+                               path, strerror(errno) );
+                       continue;
+               }
+
+               if (!S_ISREG(sbuf.st_mode)) {
+                       d_fprintf(stderr, "get_share_list: file %s is not a regular file. Ignoring.\n",
+                               path );
+                       continue;
+               }
+
+               if (only_ours && sbuf.st_uid != myuid) {
+                       continue;
+               }
+
+               if (!unix_wild_match(wcard, n)) {
+                       continue;
+               }
+
+               /* (Finally) - add to list. */ 
+               fl = TALLOC_P(ctx, struct file_list);
+               if (!fl) {
+                       return -1;
+               }
+               fl->pathname = talloc_strdup(ctx, n);
+               if (!fl->pathname) {
+                       return -1;
+               }
+
+               DLIST_ADD(flist, fl);
+       }
+
+       sys_closedir(dp);
+       return 0;
+}
+
+enum priv_op { US_LIST_OP, US_INFO_OP};
+
+struct priv_info {
+       TALLOC_CTX *ctx;
+       enum priv_op op;
+};
+
+/***************************************************************************
+ Call a function for every share on the list.
+***************************************************************************/
+
+static int process_share_list(int (*fn)(struct file_list *, void *), void *private)
+{
+       struct file_list *fl;
+       int ret = 0;
+
+       for (fl = flist; fl; fl = fl->next) {
+               ret = (*fn)(fl, private);
+       }
+
+       return ret;
+}
+
+/***************************************************************************
+ Info function.
+***************************************************************************/
+
+static int info_fn(struct file_list *fl, void *private)
+{
+       SMB_STRUCT_STAT sbuf;
+       char **lines = NULL;
+       struct priv_info *pi = (struct priv_info *)private;
+       TALLOC_CTX *ctx = pi->ctx;
+       int fd = -1;
+       int numlines = 0;
+       SEC_DESC *psd = NULL;
+       pstring basepath;
+       pstring sharepath;
+       pstring comment;
+       pstring acl_str;
+       int num_aces;
+       char sep_str[2];
+       enum usershare_err us_err;
+
+       sep_str[0] = *lp_winbind_separator();
+       sep_str[1] = '\0';
+
+       get_basepath(basepath);
+       pstrcat(basepath, "/");
+       pstrcat(basepath, fl->pathname);
+
+#ifdef O_NOFOLLOW
+       fd = sys_open(basepath, O_RDONLY|O_NOFOLLOW, 0);
+#else
+       fd = sys_open(basepath, O_RDONLY, 0);
+#endif
+
+       if (fd == -1) {
+               d_fprintf(stderr, "info_fn: unable to open %s. %s\n",
+                        basepath, strerror(errno) );
+                return -1;
+        }
+
+       /* Paranoia... */
+       if (sys_fstat(fd, &sbuf) != 0) {
+               d_fprintf(stderr, "info_fn: can't fstat file %s. Error was %s\n",
+                       basepath, strerror(errno) );
+               close(fd);
+               return -1;
+       }
+
+       if (!S_ISREG(sbuf.st_mode)) {
+               d_fprintf(stderr, "info_fn: file %s is not a regular file. Ignoring.\n",
+                       basepath );
+               close(fd);
+               return -1;
+       }
+
+       lines = fd_lines_load(fd, &numlines, 10240);
+       close(fd);
+
+       if (lines == NULL) {
+               return -1;
+       }
+
+       /* Ensure it's well formed. */
+       us_err = parse_usershare_file(ctx, &sbuf, fl->pathname, -1, lines, numlines,
+                               sharepath,
+                               comment,
+                               &psd);
+
+       if (us_err != USERSHARE_OK) {
+               d_fprintf(stderr, "info_fn: file %s is not a well formed usershare file.\n",
+                       basepath );
+               d_fprintf(stderr, "info_fn: Error was %s.\n",
+                       get_us_error_code(us_err) );
+               return -1;
+       }
+
+       pstrcpy(acl_str, "usershare_acl=");
+
+       for (num_aces = 0; num_aces < psd->dacl->num_aces; num_aces++) {
+               char access_str[2];
+               const char *domain;
+               const char *name;
+
+               access_str[1] = '\0';
+
+               if (net_lookup_name_from_sid(ctx, &psd->dacl->ace[num_aces].trustee, &domain, &name)) {
+                       if (*domain) {
+                               pstrcat(acl_str, domain);
+                               pstrcat(acl_str, sep_str);
+                       }
+                       pstrcat(acl_str,name);
+               } else {
+                       fstring sidstr;
+                       sid_to_string(sidstr, &psd->dacl->ace[num_aces].trustee);
+                       pstrcat(acl_str,sidstr);
+               }
+               pstrcat(acl_str, ":");
+
+               if (psd->dacl->ace[num_aces].type == SEC_ACE_TYPE_ACCESS_DENIED) {
+                       pstrcat(acl_str, "D,");
+               } else {
+                       if (psd->dacl->ace[num_aces].info.mask & GENERIC_ALL_ACCESS) {
+                               pstrcat(acl_str, "F,");
+                       } else {
+                               pstrcat(acl_str, "R,");
+                       }
+               }
+       }
+
+       acl_str[strlen(acl_str)-1] = '\0';
+
+       if (pi->op == US_INFO_OP) {
+               d_printf("[%s]\n", fl->pathname );
+               d_printf("path=%s\n", sharepath );
+               d_printf("comment=%s\n", comment);
+               d_printf("%s\n\n", acl_str);
+       } else if (pi->op == US_LIST_OP) {
+               d_printf("%s\n", fl->pathname);
+       }
+
+       return 0;
+}
+
+/***************************************************************************
+ Print out info (internal detail) on userlevel shares.
+***************************************************************************/
+
+static int net_usershare_info(int argc, const char **argv)
+{
+       fstring wcard;
+       BOOL only_ours = True;
+       int ret = -1;
+       struct priv_info pi;
+       TALLOC_CTX *ctx;
+
+       fstrcpy(wcard, "*");
+
+       if (opt_long_list_entries) {
+               only_ours = False;
+       }
+
+       switch (argc) {
+               case 0:
+                       break;
+               case 1:
+                       fstrcpy(wcard, argv[0]);
+                       break;
+               default:
+                       return net_usershare_info_usage(argc, argv);
+       }
+
+       strlower_m(wcard);
+
+       ctx = talloc_init("share_info");
+       ret = get_share_list(ctx, wcard, only_ours);
+       if (ret) {
+               return ret;
+       }
+
+       pi.ctx = ctx;
+       pi.op = US_INFO_OP;
+
+       ret = process_share_list(info_fn, &pi);
+       talloc_destroy(ctx);
+       return ret;
+}
+
+/***************************************************************************
+ Add a single userlevel share.
+***************************************************************************/
+
+static int net_usershare_add(int argc, const char **argv)
+{
+       TALLOC_CTX *ctx = NULL;
+       SMB_STRUCT_STAT sbuf;
+       SMB_STRUCT_STAT lsbuf;
+       char *sharename;
+       pstring full_path;
+       pstring full_path_tmp;
+       const char *us_path;
+       const char *us_comment;
+       const char *arg_acl;
+       char *us_acl;
+       char *file_img;
+       int num_aces = 0;
+       int i;
+       int tmpfd;
+       const char *pacl;
+       size_t to_write;
+       uid_t myeuid = geteuid();
+
+       us_comment = "";
+       arg_acl = "S-1-1-0:R";
+
+       switch (argc) {
+               case 0:
+               case 1:
+               default:
+                       return net_usershare_add_usage(argc, argv);
+               case 2:
+                       sharename = strdup_lower(argv[0]);
+                       us_path = argv[1];
+                       break;
+               case 3:
+                       sharename = strdup_lower(argv[0]);
+                       us_path = argv[1];
+                       us_comment = argv[2];
+                       break;
+               case 4:
+                       sharename = strdup_lower(argv[0]);
+                       us_path = argv[1];
+                       us_comment = argv[2];
+                       arg_acl = argv[3];
+                       break;
+       }
+
+       if (!validate_net_name(sharename, INVALID_SHARENAME_CHARS, strlen(sharename))) {
+               d_fprintf(stderr, "net usershare add: share name %s contains "
+                        "invalid characters (any of %s)\n",
+                        sharename, INVALID_SHARENAME_CHARS);
+               SAFE_FREE(sharename);
+               return -1;
+       }
+
+       /* Disallow shares the same as users. */
+       if (getpwnam(sharename)) {
+               d_fprintf(stderr, "net usershare add: share name %s is already a valid system user name\n",
+                       sharename );
+               SAFE_FREE(sharename);
+               return -1;
+       }
+
+       /* Construct the full path for the usershare file. */
+       get_basepath(full_path);
+       pstrcat(full_path, "/");
+       pstrcpy(full_path_tmp, full_path);
+       pstrcat(full_path, sharename);
+       pstrcat(full_path_tmp, ":tmpXXXXXX");
+
+       /* The path *must* be absolute. */
+       if (us_path[0] != '/') {
+               d_fprintf(stderr,"net usershare add: path %s is not an absolute path.\n",
+                       us_path);
+               SAFE_FREE(sharename);
+               return -1;
+       }
+
+       /* Check the directory to be shared exists. */
+       if (sys_stat(us_path, &sbuf) != 0) {
+               d_fprintf(stderr, "net usershare add: cannot stat path %s to ensure "
+                       "this is a directory. Error was %s\n",
+                       us_path, strerror(errno) );
+               SAFE_FREE(sharename);
+               return -1;
+       }
+
+       if (!S_ISDIR(sbuf.st_mode)) {
+               d_fprintf(stderr, "net usershare add: path %s is not a directory.\n",
+                       us_path );
+               SAFE_FREE(sharename);
+               return -1;
+       }
+
+       /* If we're not root, check if we're restricted to sharing out directories
+          that we own only. */
+
+       if ((myeuid != 0) && lp_usershare_owner_only() && (myeuid != sbuf.st_uid)) {
+               d_fprintf(stderr, "net usershare add: cannot share path %s as "
+                       "we are restricted to only sharing directories we own.\n",
+                       us_path );
+               SAFE_FREE(sharename);
+               return -1;
+       }
+
+       /* No validation needed on comment. Now go through and validate the
+          acl string. Convert names to SID's as needed. Then run it through
+          parse_usershare_acl to ensure it's valid. */
+
+       ctx = talloc_init("share_info");
+
+       /* Start off the string we'll append to. */
+       us_acl = talloc_strdup(ctx, "");
+
+       pacl = arg_acl;
+       num_aces = 1;
+
+       /* Add the number of ',' characters to get the number of aces. */
+       num_aces += count_chars(pacl,',');
+
+       for (i = 0; i < num_aces; i++) {
+               DOM_SID sid;
+               const char *pcolon = strchr_m(pacl, ':');
+               const char *name;
+
+               if (pcolon == NULL) {
+                       d_fprintf(stderr, "net usershare add: malformed acl %s (missing ':').\n",
+                               pacl );
+                       talloc_destroy(ctx);
+                       SAFE_FREE(sharename);
+                       return -1;
+               }
+
+               switch(pcolon[1]) {
+                       case 'f':
+                       case 'F':
+                       case 'd':
+                       case 'r':
+                       case 'R':
+                               break;
+                       default:
+                               d_fprintf(stderr, "net usershare add: malformed acl %s "
+                                       "(access control must be 'r', 'f', or 'd')\n",
+                                       pacl );
+                               talloc_destroy(ctx);
+                               SAFE_FREE(sharename);
+                               return -1;
+               }
+
+               if (pcolon[2] != ',' && pcolon[2] != '\0') {
+                       d_fprintf(stderr, "net usershare add: malformed terminating character for acl %s\n",
+                               pacl );
+                       talloc_destroy(ctx);
+                       SAFE_FREE(sharename);
+                       return -1;
+               }
+
+               /* Get the name */
+               name = talloc_strndup(ctx, pacl, pcolon - pacl);
+               if (!string_to_sid(&sid, name)) {
+                       /* Convert to a SID */
+                       if (!net_lookup_sid_from_name(ctx, name, &sid)) {
+                               d_fprintf(stderr, "net usershare add: cannot convert name %s to a SID.\n",
+                                       name );
+                               talloc_destroy(ctx);
+                               SAFE_FREE(sharename);
+                               return -1;
+                       }
+               }
+               us_acl = talloc_asprintf_append(us_acl, "%s:%c,", sid_string_static(&sid), pcolon[1]);
+
+               /* Move to the next ACL entry. */
+               if (pcolon[2] == ',') {
+                       pacl = &pcolon[3];
+               }
+       }
+
+       /* Remove the last ',' */
+       us_acl[strlen(us_acl)-1] = '\0';
+
+       /* Create a temporary filename for this share. */
+       tmpfd = smb_mkstemp(full_path_tmp);
+
+       if (tmpfd == -1) {
+               d_fprintf(stderr, "net usershare add: cannot create tmp file %s\n",
+                               full_path_tmp );
+               talloc_destroy(ctx);
+               SAFE_FREE(sharename);
+               return -1;
+       }
+
+       /* Ensure we opened the file we thought we did. */
+       if (sys_lstat(full_path_tmp, &lsbuf) != 0) {
+               d_fprintf(stderr, "net usershare add: cannot lstat tmp file %s\n",
+                               full_path_tmp );
+               talloc_destroy(ctx);
+               SAFE_FREE(sharename);
+               return -1;
+       }
+
+       /* Check this is the same as the file we opened. */
+       if (sys_fstat(tmpfd, &sbuf) != 0) {
+               d_fprintf(stderr, "net usershare add: cannot fstat tmp file %s\n",
+                               full_path_tmp );
+               talloc_destroy(ctx);
+               SAFE_FREE(sharename);
+               return -1;
+       }
+
+       if (!S_ISREG(sbuf.st_mode) || sbuf.st_dev != lsbuf.st_dev || sbuf.st_ino != lsbuf.st_ino) {
+               d_fprintf(stderr, "net usershare add: tmp file %s is not a regular file ?\n",
+                               full_path_tmp );
+               talloc_destroy(ctx);
+               SAFE_FREE(sharename);
+               return -1;
+       }
+       
+       if (fchmod(tmpfd, 0644) == -1) {
+               d_fprintf(stderr, "net usershare add: failed to fchmod tmp file %s to 0644n",
+                               full_path_tmp );
+               talloc_destroy(ctx);
+               SAFE_FREE(sharename);
+               return -1;
+       }
+
+       /* Create the in-memory image of the file. */
+       file_img = talloc_strdup(ctx, "#VERSION 1\npath=");
+       file_img = talloc_asprintf_append(file_img, "%s\ncomment=%s\nusershare_acl=%s\n",
+                       us_path, us_comment, us_acl );
+
+       to_write = strlen(file_img);
+
+       if (write(tmpfd, file_img, to_write) != to_write) {
+               d_fprintf(stderr, "net usershare add: failed to write %u bytes to file %s. Error was %s\n",
+                       (unsigned int)to_write, full_path_tmp, strerror(errno));
+               unlink(full_path_tmp);
+               talloc_destroy(ctx);
+               SAFE_FREE(sharename);
+               return -1;
+       }
+
+       /* Attempt to replace any existing share by this name. */
+       if (rename(full_path_tmp, full_path) != 0) {
+               unlink(full_path_tmp);
+               d_fprintf(stderr, "net usershare add: failed to add share %s. Error was %s\n",
+                       sharename, strerror(errno));
+               talloc_destroy(ctx);
+               close(tmpfd);
+               SAFE_FREE(sharename);
+               return -1;
+       }
+
+       close(tmpfd);
+       talloc_destroy(ctx);
+
+       if (opt_long_list_entries) {
+               const char *my_argv[2];
+               my_argv[0] = sharename;
+               my_argv[1] = NULL;
+               net_usershare_info(1, argv);
+       }
+
+       SAFE_FREE(sharename);
+       return 0;
+}
+
+#if 0
+/***************************************************************************
+ List function.
+***************************************************************************/
+
+static int list_fn(struct file_list *fl, void *private)
+{
+       d_printf("%s\n", fl->pathname);
+       return 0;
+}
+#endif
+
+/***************************************************************************
+ List userlevel shares.
+***************************************************************************/
+
+static int net_usershare_list(int argc, const char **argv)
+{
+       fstring wcard;
+       BOOL only_ours = True;
+       int ret = -1;
+       struct priv_info pi;
+       TALLOC_CTX *ctx;
+
+       fstrcpy(wcard, "*");
+
+       if (opt_long_list_entries) {
+               only_ours = False;
+       }
+
+       switch (argc) {
+               case 0:
+                       break;
+               case 1:
+                       fstrcpy(wcard, argv[0]);
+                       break;
+               default:
+                       return net_usershare_list_usage(argc, argv);
+       }
+
+       strlower_m(wcard);
+
+       ctx = talloc_init("share_list");
+       ret = get_share_list(ctx, wcard, only_ours);
+       if (ret) {
+               return ret;
+       }
+
+       pi.ctx = ctx;
+       pi.op = US_LIST_OP;
+
+       ret = process_share_list(info_fn, &pi);
+       talloc_destroy(ctx);
+       return ret;
+}
+
+/***************************************************************************
+ Handle "net usershare help *" subcommands.
+***************************************************************************/
+
+int net_usershare_help(int argc, const char **argv)
+{
+       struct functable func[] = {
+               {"ADD", net_usershare_add_usage},
+               {"DELETE", net_usershare_delete_usage},
+               {"INFO", net_usershare_info_usage},
+               {"LIST", net_usershare_list_usage},
+               {NULL, NULL}};
+
+       return net_run_function(argc, argv, func, net_usershare_usage);
+}
+
+/***************************************************************************
+ Entry-point for all the USERSHARE functions.
+***************************************************************************/
+
+int net_usershare(int argc, const char **argv)
+{
+       SMB_STRUCT_DIR *dp;
+
+       struct functable func[] = {
+               {"ADD", net_usershare_add},
+               {"DELETE", net_usershare_delete},
+               {"INFO", net_usershare_info},
+               {"LIST", net_usershare_list},
+               {"HELP", net_usershare_help},
+               {NULL, NULL}
+       };
+       
+       if (lp_usershare_max_shares() == 0) {
+               d_fprintf(stderr, "net usershare: usershares are currently disabled\n");
+               return -1;
+       }
+
+       dp = sys_opendir(lp_usershare_path());
+       if (!dp) {
+               int err = errno;
+               d_fprintf(stderr, "net usershare: cannot open usershare directory %s. Error %s\n",
+                       lp_usershare_path(), strerror(err) );
+               if (err == EACCES) {
+                       d_fprintf(stderr, "You do not have permission to create a usershare. Ask your "
+                               "administrator to grant you permissions to create a share.\n");
+               } else if (err == ENOENT) {
+                       d_fprintf(stderr, "Please ask your system administrator to "
+                               "enable user sharing.\n");
+               }
+               return -1;
+       }
+       sys_closedir(dp);
+
+       return net_run_function(argc, argv, func, net_usershare_usage);
+}
diff --git a/source3/utils/net_util.c b/source3/utils/net_util.c
new file mode 100644 (file)
index 0000000..805104c
--- /dev/null
@@ -0,0 +1,89 @@
+/*
+ *  Unix SMB/CIFS implementation.
+ *  Helper routines for net
+ *  Copyright (C) Volker Lendecke 2006
+ *
+ *  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"
+#include "utils/net.h"
+
+BOOL is_valid_policy_hnd(const POLICY_HND *hnd)
+{
+       POLICY_HND tmp;
+       ZERO_STRUCT(tmp);
+       return (memcmp(&tmp, hnd, sizeof(tmp)) != 0);
+}
+
+NTSTATUS net_rpc_lookup_name(TALLOC_CTX *mem_ctx, struct cli_state *cli,
+                            const char *name, const char **ret_domain,
+                            const char **ret_name, DOM_SID *ret_sid,
+                            enum SID_NAME_USE *ret_type)
+{
+       struct rpc_pipe_client *lsa_pipe;
+       POLICY_HND pol;
+       NTSTATUS result = NT_STATUS_OK;
+       const char **dom_names;
+       DOM_SID *sids;
+       uint32_t *types;
+
+       ZERO_STRUCT(pol);
+
+       lsa_pipe = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result);
+       if (lsa_pipe == NULL) {
+               d_fprintf(stderr, "Could not initialise lsa pipe\n");
+               return result;
+       }
+
+       result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, False, 
+                                       SEC_RIGHTS_MAXIMUM_ALLOWED,
+                                       &pol);
+       if (!NT_STATUS_IS_OK(result)) {
+               d_fprintf(stderr, "open_policy failed: %s\n",
+                         nt_errstr(result));
+               return result;
+       }
+
+       result = rpccli_lsa_lookup_names(lsa_pipe, mem_ctx, &pol, 1,
+                                        &name, &dom_names, &sids, &types);
+
+       if (!NT_STATUS_IS_OK(result)) {
+               /* This can happen easily, don't log an error */
+               goto done;
+       }
+
+       if (ret_domain != NULL) {
+               *ret_domain = dom_names[0];
+       }
+       if (ret_name != NULL) {
+               *ret_name = talloc_strdup(mem_ctx, name);
+       }
+       if (ret_sid != NULL) {
+               sid_copy(ret_sid, &sids[0]);
+       }
+       if (ret_type != NULL) {
+               *ret_type = types[0];
+       }
+
+ done:
+       if (is_valid_policy_hnd(&pol)) {
+               rpccli_lsa_close(lsa_pipe, mem_ctx, &pol);
+       }
+       cli_rpc_pipe_close(lsa_pipe);
+
+       return result;
+}
diff --git a/source3/utils/netlookup.c b/source3/utils/netlookup.c
new file mode 100644 (file)
index 0000000..edb2f7d
--- /dev/null
@@ -0,0 +1,209 @@
+/*
+   Unix SMB/CIFS implementation.
+
+   Name lookup.
+
+   Copyright (C) Jeremy Allison 2005
+
+   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"
+#include "utils/net.h"
+
+/********************************************************
+ Connection cachine struct. Goes away when ctx destroyed.
+********************************************************/
+
+struct con_struct {
+       BOOL failed_connect;
+       struct cli_state *cli;
+       struct rpc_pipe_client *lsapipe;
+       POLICY_HND pol;
+};
+
+static struct con_struct *cs;
+
+/********************************************************
+ Close connection on context destruction.
+********************************************************/
+
+static int cs_destructor(void *p)
+{
+       if (cs->cli) {
+               cli_shutdown(cs->cli);
+       }
+       cs = NULL;
+       return 0;
+}
+
+/********************************************************
+ Create the connection to localhost.
+********************************************************/
+
+static struct con_struct *create_cs(TALLOC_CTX *ctx)
+{
+       NTSTATUS nt_status;
+       struct in_addr loopback_ip = *interpret_addr2("127.0.0.1");;
+
+       if (cs) {
+               if (cs->failed_connect) {
+                       return NULL;
+               }
+               return cs;
+       }
+
+       cs = TALLOC_P(ctx, struct con_struct);
+       if (!cs) {
+               return NULL;
+       }
+
+       ZERO_STRUCTP(cs);
+       talloc_set_destructor(cs, cs_destructor);
+
+       /* Connect to localhost with given username/password. */
+       /* JRA. Pretty sure we can just do this anonymously.... */
+#if 0
+       if (!opt_password && !opt_machine_pass) {
+               char *pass = getpass("Password:");
+               if (pass) {
+                       opt_password = SMB_STRDUP(pass);
+               }
+       }
+#endif
+
+       nt_status = cli_full_connection(&cs->cli, global_myname(), global_myname(),
+                                       &loopback_ip, 0,
+                                       "IPC$", "IPC",
+#if 0
+                                       opt_user_name,
+                                       opt_workgroup,
+                                       opt_password,
+#else
+                                       "",
+                                       opt_workgroup,
+                                       "",
+#endif
+                                       0,
+                                       Undefined,
+                                       NULL);
+
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               DEBUG(2,("create_cs: Connect failed. Error was %s\n", nt_errstr(nt_status)));
+               cs->failed_connect = True;
+               return NULL;
+       }
+
+       cs->lsapipe = cli_rpc_pipe_open_noauth(cs->cli,
+                                       PI_LSARPC,
+                                       &nt_status);
+
+       if (cs->lsapipe == NULL) {
+               DEBUG(2,("create_cs: open LSA pipe failed. Error was %s\n", nt_errstr(nt_status)));
+               cs->failed_connect = True;
+               return NULL;
+       }
+
+       nt_status = rpccli_lsa_open_policy(cs->lsapipe, ctx, True,
+                               SEC_RIGHTS_MAXIMUM_ALLOWED,
+                               &cs->pol);
+
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               DEBUG(2,("create_cs: rpccli_lsa_open_policy failed. Error was %s\n", nt_errstr(nt_status)));
+               cs->failed_connect = True;
+               return NULL;
+       }
+       
+       return cs;
+}
+
+/********************************************************
+ Do a lookup_sids call to localhost.
+ Check if the local machine is authoritative for this sid. We can't
+ check if this is our SID as that's stored in the root-read-only
+ secrets.tdb.
+ The local smbd will also ask winbindd for us, so we don't have to.
+********************************************************/
+
+BOOL net_lookup_name_from_sid(TALLOC_CTX *ctx,
+                               DOM_SID *psid,
+                               const char **ppdomain,
+                               const char **ppname)
+{
+       NTSTATUS nt_status;
+       struct con_struct *csp = NULL;
+       char **domains;
+       char **names;
+       uint32 *types;
+
+       *ppdomain = NULL;
+       *ppname = NULL;
+
+       csp = create_cs(ctx);
+       if (csp == NULL) {
+               return False;
+       }
+
+       nt_status = rpccli_lsa_lookup_sids(csp->lsapipe, ctx,
+                                               &csp->pol,
+                                               1, psid,
+                                               &domains,
+                                               &names,
+                                               &types);
+
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               return False;
+       }
+
+       *ppdomain = domains[0];
+       *ppname = names[0];
+       /* Don't care about type here. */
+
+        /* Converted OK */
+        return True;
+}
+
+/********************************************************
+ Do a lookup_names call to localhost.
+********************************************************/
+
+BOOL net_lookup_sid_from_name(TALLOC_CTX *ctx, const char *full_name, DOM_SID *pret_sid)
+{
+       NTSTATUS nt_status;
+       struct con_struct *csp = NULL;
+       DOM_SID *sids = NULL;
+       uint32 *types = NULL;
+
+       csp = create_cs(ctx);
+       if (csp == NULL) {
+               return False;
+       }
+
+       nt_status = rpccli_lsa_lookup_names(csp->lsapipe, ctx,
+                                               &csp->pol,
+                                               1,
+                                               &full_name,
+                                               NULL, &sids,
+                                               &types);
+
+       if (!NT_STATUS_IS_OK(nt_status)) {
+               return False;
+       }
+
+       *pret_sid = sids[0];
+
+        /* Converted OK */
+        return True;
+}
index 4759aec0ccff5932985ae1fc0fa95b4ae7078c93..c22f4b5e0982ba9fd49a5153ee95573e3a4e8c40 100644 (file)
@@ -1173,7 +1173,7 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
               spnego.negTokenInit.mechListMIC.length);
        principal[spnego.negTokenInit.mechListMIC.length] = '\0';
 
-       retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0);
+       retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0, NULL);
 
        if (retval) {
 
@@ -1191,12 +1191,12 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego)
                pstr_sprintf(user, "%s@%s", opt_username, opt_domain);
 
                if ((retval = kerberos_kinit_password(user, opt_password, 
-                                                     0, NULL, NULL))) {
+                                                     0, NULL, NULL, NULL, False, 0))) {
                        DEBUG(10, ("Requesting TGT failed: %s\n", error_message(retval)));
                        return False;
                }
 
-               retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0);
+               retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0, NULL);
 
                if (retval) {
                        DEBUG(10, ("Kinit suceeded, but getting a ticket failed: %s\n", error_message(retval)));
index f41bbb8caaf90953ae5fbc2b677f40d1bb706772..0b17d50ad310ea9eae2c6e2b4cc931f907800d69 100644 (file)
@@ -337,7 +337,7 @@ static int fix_users_list (struct pdb_context *in)
        while (check && NT_STATUS_IS_OK(in->pdb_getsampwent (in, sam_pwent))) {
                printf("Updating record for user %s\n", pdb_get_username(sam_pwent));
        
-               if (!pdb_update_sam_account(sam_pwent)) {
+               if (!NT_STATUS_IS_OK(pdb_update_sam_account(sam_pwent))) {
                        printf("Update of user %s failed!\n", pdb_get_username(sam_pwent));
                }
                pdb_free_sam(&sam_pwent);
@@ -498,7 +498,7 @@ static int new_user (struct pdb_context *in, const char *username,
        
        get_global_sam_sid();
 
-       if (!NT_STATUS_IS_OK(pdb_init_sam_new(&sam_pwent, username, 0))) {
+       if (!NT_STATUS_IS_OK(pdb_init_sam_new(&sam_pwent, username))) {
                DEBUG(0, ("could not create account to add new user %s\n", username));
                return -1;
        }
@@ -603,13 +603,13 @@ static int new_machine (struct pdb_context *in, const char *machine_in)
        fstrcpy(machineaccount, machinename);
        fstrcat(machineaccount, "$");
 
-       if ((pwd = getpwnam_alloc(machineaccount))) {
+       if ((pwd = getpwnam_alloc(NULL, machineaccount))) {
                if (!NT_STATUS_IS_OK(pdb_init_sam_pw( &sam_pwent, pwd))) {
                        fprintf(stderr, "Could not init sam from pw\n");
-                       passwd_free(&pwd);
+                       talloc_free(pwd);
                        return -1;
                }
-               passwd_free(&pwd);
+               talloc_free(&pwd);
        } else {
                if (!NT_STATUS_IS_OK(pdb_init_sam (&sam_pwent))) {
                        fprintf(stderr, "Could not init sam from pw\n");
index 26362c6270a03bc816b50924e08cd997b1f30bb8..cff3bc5dde44cf3fe2b5c4a989969b9854800601 100644 (file)
@@ -145,7 +145,7 @@ static BOOL StringToSid(DOM_SID *sid, const char *str)
 
        if (!cacls_open_policy_hnd() ||
            !NT_STATUS_IS_OK(rpccli_lsa_lookup_names(global_pipe_hnd, global_hack_cli->mem_ctx, 
-                                                 &pol, 1, &str, &sids, 
+                                                 &pol, 1, &str, NULL, &sids, 
                                                  &types))) {
                result = False;
                goto done;
index a4d2766b13281ea93c80750cfd812d18dabc6e0d..405e51cd256bed247bf478cb8c8a52f6d4db790a 100644 (file)
@@ -584,6 +584,107 @@ static BOOL do_drvupgrade(const struct process_id pid,
                pid, MSG_DEBUG, argv[1], strlen(argv[1]) + 1, False);
 }
 
+static BOOL do_winbind_online(const struct process_id pid,
+                            const int argc, const char **argv)
+{
+       TDB_CONTEXT *tdb;
+
+       if (argc != 1) {
+               fprintf(stderr, "Usage: smbcontrol winbindd online\n");
+               return False;
+       }
+
+       if (!lp_winbind_offline_logon()) {
+               fprintf(stderr, "The parameter \"winbind offline logon\" must "
+                       "be set in the [global] section of smb.conf for this "
+                       "command to be allowed.\n");
+               return False;
+       }
+
+       /* Remove the entry in the winbindd_cache tdb to tell a later
+          starting winbindd that we're online. */
+
+       tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600);
+       if (!tdb) {
+               fprintf(stderr, "Cannot open the tdb %s for writing.\n",
+                       lock_path("winbindd_cache.tdb"));
+               return False;
+       }
+
+       tdb_delete_bystring(tdb, "WINBINDD_OFFLINE");
+       tdb_close(tdb);
+
+       return send_message(pid, MSG_WINBIND_ONLINE, NULL, 0, False);
+}
+
+static BOOL do_winbind_offline(const struct process_id pid,
+                            const int argc, const char **argv)
+{
+       TDB_CONTEXT *tdb;
+       BOOL ret = False;
+       int retry = 0;
+
+       if (argc != 1) {
+               fprintf(stderr, "Usage: smbcontrol winbindd offline\n");
+               return False;
+       }
+
+       if (!lp_winbind_offline_logon()) {
+               fprintf(stderr, "The parameter \"winbind offline logon\" must "
+                       "be set in the [global] section of smb.conf for this "
+                       "command to be allowed.\n");
+               return False;
+       }
+
+       /* Create an entry in the winbindd_cache tdb to tell a later
+          starting winbindd that we're offline. We may actually create
+          it here... */
+
+       tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
+                               WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
+                               TDB_DEFAULT /* TDB_CLEAR_IF_FIRST */, O_RDWR|O_CREAT, 0600);
+
+       if (!tdb) {
+               fprintf(stderr, "Cannot open the tdb %s for writing.\n",
+                       lock_path("winbindd_cache.tdb"));
+               return False;
+       }
+
+       /* There's a potential race condition that if a child
+          winbindd detects a domain is online at the same time
+          we're trying to tell it to go offline that it might 
+          delete the record we add between us adding it and
+          sending the message. Minimize this by retrying up to
+          5 times. */
+
+       for (retry = 0; retry < 5; retry++) {
+               int err;
+               TDB_DATA d;
+               ZERO_STRUCT(d);
+               tdb_store_bystring(tdb, "WINBINDD_OFFLINE", d, TDB_INSERT);
+
+               ret = send_message(pid, MSG_WINBIND_OFFLINE, NULL, 0, False);
+
+               /* Check that the entry "WINBINDD_OFFLINE" still exists. */
+               tdb->ecode = 0;
+               d = tdb_fetch_bystring( tdb, "WINBINDD_OFFLINE" );
+
+               /* As this is a key with no data we don't need to free, we
+                  check for existence by looking at tdb_err. */
+
+               err = tdb_error(tdb);
+
+               if (err == TDB_ERR_NOEXIST) {
+                       DEBUG(10,("do_winbind_offline: offline state not set - retrying.\n"));
+               } else {
+                       break;
+               }
+       }
+
+       tdb_close(tdb);
+       return ret;
+}
+
 static BOOL do_reload_config(const struct process_id pid,
                             const int argc, const char **argv)
 {
@@ -668,6 +769,8 @@ static const struct {
        { "drvupgrade", do_drvupgrade, "Notify a printer driver has changed" },
        { "reload-config", do_reload_config, "Force smbd or winbindd to reload config file"},
        { "nodestatus", do_nodestatus, "Ask nmbd to do a node status request"},
+       { "online", do_winbind_online, "Ask winbind to go into online state"},
+       { "offline", do_winbind_offline, "Ask winbind to go into offline state"},
        { "noop", do_noop, "Do nothing" },
        { NULL }
 };
@@ -681,7 +784,7 @@ static void usage(poptContext *pc)
        poptPrintHelp(*pc, stderr, 0);
 
        fprintf(stderr, "\n");
-       fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\" or a "
+       fprintf(stderr, "<destination> is one of \"nmbd\", \"smbd\", \"winbindd\" or a "
                "process ID\n");
 
        fprintf(stderr, "\n");
@@ -715,10 +818,17 @@ static struct process_id parse_dest(const char *dest)
                return pid_to_procid(sys_getpid());
        }
 
+       /* Fix winbind typo. */
+       if (strequal(dest, "winbind")) {
+               dest = "winbindd";
+       }
+
        /* Check for numeric pid number */
 
        result = interpret_pid(dest);
-       if (procid_valid(&result)) {
+
+       /* Zero isn't valid if not smbd. */
+       if (result.pid && procid_valid(&result)) {
                return result;
        }
 
index b1a14685f5eccdfa7a45dc83a6650583c92809a1..7b3268e7834c7931368e52f8cb3f447286443515 100644 (file)
@@ -116,7 +116,7 @@ static BOOL StringToSid(DOM_SID *sid, const char *str)
 
        if (!cli_open_policy_hnd() ||
            !NT_STATUS_IS_OK(rpccli_lsa_lookup_names(global_pipe_hnd, cli_ipc->mem_ctx, 
-                                                 &pol, 1, &str, &sids, 
+                                                 &pol, 1, &str, NULL, &sids, 
                                                  &types))) {
                result = False;
                goto done;
index 7eb11137d707ab84d41667f029e57f223c8e8330..4323ee29e0ceed72821cf83f497a28af90c89335 100644 (file)
@@ -270,10 +270,11 @@ static char *prompt_for_new_password(BOOL stdin_get)
  Change a password either locally or remotely.
 *************************************************************/
 
-static BOOL password_change(const char *remote_mach, char *username, 
-                           char *old_passwd, char *new_pw, int local_flags)
+static NTSTATUS password_change(const char *remote_mach, char *username, 
+                               char *old_passwd, char *new_pw,
+                               int local_flags)
 {
-       BOOL ret;
+       NTSTATUS ret;
        pstring err_str;
        pstring msg_str;
 
@@ -281,7 +282,7 @@ static BOOL password_change(const char *remote_mach, char *username,
                if (local_flags & (LOCAL_ADD_USER|LOCAL_DELETE_USER|LOCAL_DISABLE_USER|LOCAL_ENABLE_USER|
                                                        LOCAL_TRUST_ACCOUNT|LOCAL_SET_NO_PASSWORD)) {
                        /* these things can't be done remotely yet */
-                       return False;
+                       return NT_STATUS_UNSUCCESSFUL;
                }
                ret = remote_password_change(remote_mach, username, 
                                             old_passwd, new_pw, err_str, sizeof(err_str));
@@ -370,9 +371,9 @@ static int process_root(int local_flags)
                load_interfaces();
        }
 
-       if (!user_name[0] && (pwd = getpwuid_alloc(geteuid()))) {
+       if (!user_name[0] && (pwd = getpwuid_alloc(NULL, geteuid()))) {
                fstrcpy(user_name, pwd->pw_name);
-               passwd_free(&pwd);
+               talloc_free(pwd);
        } 
 
        if (!user_name[0]) {
@@ -465,7 +466,9 @@ static int process_root(int local_flags)
                }
        }
 
-       if (!password_change(remote_machine, user_name, old_passwd, new_passwd, local_flags)) {
+       if (!NT_STATUS_IS_OK(password_change(remote_machine, user_name,
+                                            old_passwd, new_passwd,
+                                            local_flags))) {
                fprintf(stderr,"Failed to modify password entry for user %s\n", user_name);
                result = 1;
                goto done;
@@ -512,10 +515,10 @@ static int process_nonroot(int local_flags)
        }
 
        if (!user_name[0]) {
-               pwd = getpwuid_alloc(getuid());
+               pwd = getpwuid_alloc(NULL, getuid());
                if (pwd) {
                        fstrcpy(user_name,pwd->pw_name);
-                       passwd_free(&pwd);
+                       talloc_free(pwd);
                } else {
                        fprintf(stderr, "smbpasswd: cannot lookup user name for uid %u\n", (unsigned int)getuid());
                        exit(1);
@@ -549,7 +552,8 @@ static int process_nonroot(int local_flags)
                exit(1);
        }
 
-       if (!password_change(remote_machine, user_name, old_pw, new_pw, 0)) {
+       if (!NT_STATUS_IS_OK(password_change(remote_machine, user_name, old_pw,
+                                            new_pw, 0))) {
                fprintf(stderr,"Failed to change password for %s\n", user_name);
                result = 1;
                goto done;
index 6c9cfce13cdd66d4826784e58ca4931d6290e60d..700fb7fa0808db8176b796c17c7dbfc8352010a8 100644 (file)
@@ -293,7 +293,7 @@ static void cgi_web_auth(void)
                exit(0);
        }
 
-       pwd = getpwnam_alloc(user);
+       pwd = getpwnam_alloc(NULL, user);
        if (!pwd) {
                printf("%sCannot find user %s<br>%s\n", head, user, tail);
                exit(0);
@@ -306,7 +306,7 @@ static void cgi_web_auth(void)
                       head, user, (int)geteuid(), (int)getuid(), tail);
                exit(0);
        }
-       passwd_free(&pwd);
+       talloc_free(pwd);
 }
 
 
@@ -346,7 +346,7 @@ static BOOL cgi_handle_authorization(char *line)
         * Try and get the user from the UNIX password file.
         */
        
-       pass = getpwnam_alloc(user);
+       pass = getpwnam_alloc(NULL, user);
        
        /*
         * Validate the password they have given.
@@ -367,7 +367,7 @@ static BOOL cgi_handle_authorization(char *line)
                        
                        /* Save the users name */
                        C_user = SMB_STRDUP(user);
-                       passwd_free(&pass);
+                       talloc_free(pass);
                        return True;
                }
        }
@@ -377,7 +377,7 @@ err:
                        "WWW-Authenticate: Basic realm=\"SWAT\"\r\n",
                        "username or password incorrect");
 
-       passwd_free(&pass);
+       talloc_free(pass);
        return False;
 }
 
index 63253e41c40f69ae26344975f31142615466908d..af01d1f31bbc50a4957e1da098b5624e5bea5e46 100644 (file)
@@ -982,7 +982,7 @@ static BOOL change_password(const char *remote_machine, const char *user_name,
                            const char *old_passwd, const char *new_passwd, 
                                int local_flags)
 {
-       BOOL ret = False;
+       NTSTATUS ret;
        pstring err_str;
        pstring msg_str;
 
@@ -996,7 +996,7 @@ static BOOL change_password(const char *remote_machine, const char *user_name,
                                                                         new_passwd, err_str, sizeof(err_str));
                if(*err_str)
                        printf("%s\n<p>", err_str);
-               return ret;
+               return NT_STATUS_IS_OK(ret);
        }
 
        if(!initialize_password_db(True)) {
@@ -1012,7 +1012,7 @@ static BOOL change_password(const char *remote_machine, const char *user_name,
        if(*err_str)
                printf("%s\n<p>", err_str);
 
-       return ret;
+       return NT_STATUS_IS_OK(ret);
 }
 
 /****************************************************************************