summaryrefslogtreecommitdiff
path: root/source3
diff options
context:
space:
mode:
Diffstat (limited to 'source3')
-rw-r--r--source3/Makefile.in76
-rw-r--r--source3/auth/auth.c20
-rw-r--r--source3/auth/auth_builtin.c6
-rw-r--r--source3/auth/auth_compat.c2
-rw-r--r--source3/auth/auth_domain.c41
-rw-r--r--source3/auth/auth_ntlmssp.c10
-rw-r--r--source3/auth/auth_rhosts.c190
-rw-r--r--source3/auth/auth_sam.c43
-rw-r--r--source3/auth/auth_script.c10
-rw-r--r--source3/auth/auth_server.c16
-rw-r--r--source3/auth/auth_unix.c6
-rw-r--r--source3/auth/auth_util.c1441
-rw-r--r--source3/auth/auth_winbind.c19
-rw-r--r--source3/configure.in32
-rw-r--r--source3/groupdb/mapping.c195
-rw-r--r--source3/include/ads.h2
-rw-r--r--source3/include/auth.h29
-rw-r--r--source3/include/doserr.h1
-rw-r--r--source3/include/event.h31
-rw-r--r--source3/include/gpo.h91
-rw-r--r--source3/include/idmap.h4
-rw-r--r--source3/include/includes.h11
-rw-r--r--source3/include/local.h9
-rw-r--r--source3/include/messages.h2
-rw-r--r--source3/include/nt_status.h6
-rw-r--r--source3/include/passdb.h30
-rw-r--r--source3/include/rpc_dfs.h532
-rw-r--r--source3/include/rpc_lsa.h56
-rw-r--r--source3/include/rpc_netlogon.h13
-rw-r--r--source3/include/rpc_samr.h4
-rw-r--r--source3/include/secrets.h6
-rw-r--r--source3/include/smb.h70
-rw-r--r--source3/include/smbldap.h15
-rw-r--r--source3/intl/lang_tdb.c2
-rw-r--r--source3/lib/dummysmbd.c9
-rw-r--r--source3/lib/events.c125
-rw-r--r--source3/lib/genrand.c4
-rw-r--r--source3/lib/messages.c15
-rw-r--r--source3/lib/pam_errors.c1
-rw-r--r--source3/lib/pidfile.c6
-rw-r--r--source3/lib/readline.c4
-rw-r--r--source3/lib/secdesc.c10
-rw-r--r--source3/lib/sharesec.c308
-rw-r--r--source3/lib/smbldap.c221
-rw-r--r--source3/lib/smbldap_util.c92
-rw-r--r--source3/lib/system_smbd.c91
-rw-r--r--source3/lib/username.c124
-rw-r--r--source3/lib/util.c8
-rw-r--r--source3/lib/util_file.c33
-rw-r--r--source3/lib/util_pw.c79
-rw-r--r--source3/lib/util_sid.c5
-rw-r--r--source3/lib/util_str.c99
-rw-r--r--source3/lib/util_unistr.c14
-rw-r--r--source3/libads/gpo.c680
-rw-r--r--source3/libads/gpo_util.c496
-rw-r--r--source3/libads/kerberos.c40
-rw-r--r--source3/libads/krb5_errs.c132
-rw-r--r--source3/libads/krb5_setpw.c49
-rw-r--r--source3/libads/ldap.c223
-rw-r--r--source3/libads/sasl.c23
-rw-r--r--source3/libmsrpc/cac_lsarpc.c14
-rw-r--r--source3/libsmb/cliconnect.c2
-rw-r--r--source3/libsmb/clidfs.c22
-rw-r--r--source3/libsmb/clientgen.c8
-rw-r--r--source3/libsmb/clikrb5.c171
-rw-r--r--source3/libsmb/clilist.c6
-rw-r--r--source3/libsmb/clispnego.c2
-rw-r--r--source3/libsmb/conncache.c36
-rw-r--r--source3/libsmb/errormap.c15
-rw-r--r--source3/libsmb/gpo.c167
-rw-r--r--source3/libsmb/libsmbclient.c13
-rw-r--r--source3/libsmb/passchange.c40
-rw-r--r--source3/nsswitch/pam_winbind.c991
-rw-r--r--source3/nsswitch/pam_winbind.h56
-rw-r--r--source3/nsswitch/wb_client.c16
-rw-r--r--source3/nsswitch/wbinfo.c159
-rw-r--r--source3/nsswitch/winbindd.c14
-rw-r--r--source3/nsswitch/winbindd.h17
-rw-r--r--source3/nsswitch/winbindd_ads.c19
-rw-r--r--source3/nsswitch/winbindd_cache.c858
-rw-r--r--source3/nsswitch/winbindd_cm.c26
-rw-r--r--source3/nsswitch/winbindd_cred_cache.c270
-rw-r--r--source3/nsswitch/winbindd_creds.c162
-rw-r--r--source3/nsswitch/winbindd_dual.c217
-rw-r--r--source3/nsswitch/winbindd_group.c99
-rw-r--r--source3/nsswitch/winbindd_misc.c17
-rw-r--r--source3/nsswitch/winbindd_nss.h78
-rw-r--r--source3/nsswitch/winbindd_pam.c1026
-rw-r--r--source3/nsswitch/winbindd_passdb.c172
-rw-r--r--source3/nsswitch/winbindd_reconnect.c32
-rw-r--r--source3/nsswitch/winbindd_rpc.c69
-rw-r--r--source3/nsswitch/winbindd_sid.c50
-rw-r--r--source3/nsswitch/winbindd_user.c8
-rw-r--r--source3/nsswitch/winbindd_util.c13
-rw-r--r--source3/pam_smbpass/pam_smb_auth.c8
-rw-r--r--source3/pam_smbpass/pam_smb_passwd.c6
-rw-r--r--source3/pam_smbpass/support.c2
-rw-r--r--source3/param/loadparm.c715
-rw-r--r--source3/param/params.c2
-rw-r--r--source3/passdb/lookup_sid.c831
-rw-r--r--source3/passdb/machine_sid.c3
-rw-r--r--source3/passdb/passdb.c621
-rw-r--r--source3/passdb/pdb_get_set.c12
-rw-r--r--source3/passdb/pdb_interface.c444
-rw-r--r--source3/passdb/pdb_ldap.c1530
-rw-r--r--source3/passdb/pdb_nds.c9
-rw-r--r--source3/passdb/pdb_smbpasswd.c22
-rw-r--r--source3/passdb/pdb_tdb.c96
-rw-r--r--source3/passdb/secrets.c164
-rw-r--r--source3/passdb/util_builtin.c2
-rw-r--r--source3/passdb/util_unixsids.c94
-rw-r--r--source3/passdb/util_wellknown.c15
-rw-r--r--source3/printing/nt_printing.c14
-rw-r--r--source3/printing/print_generic.c2
-rw-r--r--source3/python/py_lsa.c4
-rw-r--r--source3/rpc_client/cli_dfs.c673
-rw-r--r--source3/rpc_client/cli_lsarpc.c111
-rw-r--r--source3/rpc_client/cli_netlogon.c28
-rw-r--r--source3/rpc_client/cli_pipe.c6
-rw-r--r--source3/rpc_client/cli_samr.c7
-rw-r--r--source3/rpc_parse/parse_dfs.c2789
-rw-r--r--source3/rpc_parse/parse_lsa.c221
-rw-r--r--source3/rpc_parse/parse_net.c49
-rw-r--r--source3/rpc_parse/parse_prs.c29
-rw-r--r--source3/rpc_parse/parse_rpc.c10
-rw-r--r--source3/rpc_parse/parse_samr.c6
-rw-r--r--source3/rpc_server/srv_dfs.c587
-rw-r--r--source3/rpc_server/srv_dfs_nt.c406
-rw-r--r--source3/rpc_server/srv_lsa_nt.c256
-rw-r--r--source3/rpc_server/srv_netlog_nt.c96
-rw-r--r--source3/rpc_server/srv_pipe.c5
-rw-r--r--source3/rpc_server/srv_pipe_hnd.c5
-rw-r--r--source3/rpc_server/srv_samr_nt.c279
-rw-r--r--source3/rpc_server/srv_spoolss_nt.c20
-rw-r--r--source3/rpc_server/srv_srvsvc_nt.c208
-rw-r--r--source3/rpcclient/cmd_dfs.c111
-rw-r--r--source3/rpcclient/cmd_lsarpc.c4
-rw-r--r--source3/rpcclient/cmd_samr.c137
-rw-r--r--source3/sam/idmap.c41
-rw-r--r--source3/sam/idmap_ad.c7
-rw-r--r--source3/sam/idmap_ldap.c271
-rw-r--r--source3/sam/idmap_rid.c6
-rw-r--r--source3/sam/idmap_smbldap.c10
-rw-r--r--source3/sam/idmap_tdb.c39
-rw-r--r--source3/sam/idmap_util.c74
-rwxr-xr-xsource3/script/installman.sh5
-rwxr-xr-xsource3/script/installswat.sh20
-rw-r--r--source3/smbd/chgpasswd.c13
-rw-r--r--source3/smbd/conn.c2
-rw-r--r--source3/smbd/lanman.c2690
-rw-r--r--source3/smbd/msdfs.c8
-rw-r--r--source3/smbd/ntquotas.c9
-rw-r--r--source3/smbd/nttrans.c2
-rw-r--r--source3/smbd/open.c10
-rw-r--r--source3/smbd/password.c143
-rw-r--r--source3/smbd/posix_acls.c10
-rw-r--r--source3/smbd/process.c115
-rw-r--r--source3/smbd/sec_ctx.c58
-rw-r--r--source3/smbd/server.c29
-rw-r--r--source3/smbd/service.c287
-rw-r--r--source3/smbd/sesssetup.c30
-rw-r--r--source3/smbd/share_access.c264
-rw-r--r--source3/smbd/uid.c131
-rw-r--r--source3/utils/net.c27
-rw-r--r--source3/utils/net.h23
-rw-r--r--source3/utils/net_ads_gpo.c436
-rw-r--r--source3/utils/net_groupmap.c38
-rw-r--r--source3/utils/net_help.c9
-rw-r--r--source3/utils/net_lookup.c52
-rw-r--r--source3/utils/net_rpc.c557
-rw-r--r--source3/utils/net_rpc_rights.c55
-rw-r--r--source3/utils/net_rpc_samsync.c141
-rw-r--r--source3/utils/net_rpc_shell.c270
-rw-r--r--source3/utils/net_sam.c784
-rw-r--r--source3/utils/net_usershare.c829
-rw-r--r--source3/utils/net_util.c89
-rw-r--r--source3/utils/netlookup.c209
-rw-r--r--source3/utils/ntlm_auth.c6
-rw-r--r--source3/utils/pdbedit.c10
-rw-r--r--source3/utils/smbcacls.c2
-rw-r--r--source3/utils/smbcontrol.c114
-rw-r--r--source3/utils/smbcquotas.c2
-rw-r--r--source3/utils/smbpasswd.c24
-rw-r--r--source3/web/cgi.c10
-rw-r--r--source3/web/swat.c6
185 files changed, 22252 insertions, 7131 deletions
diff --git a/source3/Makefile.in b/source3/Makefile.in
index 6c182a6e41..281d58f23d 100644
--- a/source3/Makefile.in
+++ b/source3/Makefile.in
@@ -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 $@"
diff --git a/source3/auth/auth.c b/source3/auth/auth.c
index df7d6fc9c6..6dc30383d5 100644
--- a/source3/auth/auth.c
+++ b/source3/auth/auth.c
@@ -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;
diff --git a/source3/auth/auth_builtin.c b/source3/auth/auth_builtin.c
index 96c2221652..d4d6d49e40 100644
--- a/source3/auth/auth_builtin.c
+++ b/source3/auth/auth_builtin.c
@@ -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);
diff --git a/source3/auth/auth_compat.c b/source3/auth/auth_compat.c
index 2ac70d7354..28b9de8d43 100644
--- a/source3/auth/auth_compat.c
+++ b/source3/auth/auth_compat.c
@@ -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;
}
diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c
index 266851b229..81ae7c1340 100644
--- a/source3/auth/auth_domain.c
+++ b/source3/auth/auth_domain.c
@@ -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,
diff --git a/source3/auth/auth_ntlmssp.c b/source3/auth/auth_ntlmssp.c
index 2fef8f1e9b..2bf86860cc 100644
--- a/source3/auth/auth_ntlmssp.c
+++ b/source3/auth/auth_ntlmssp.c
@@ -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;
diff --git a/source3/auth/auth_rhosts.c b/source3/auth/auth_rhosts.c
index b561e3d42b..e310fa80fd 100644
--- a/source3/auth/auth_rhosts.c
+++ b/source3/auth/auth_rhosts.c
@@ -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);
}
diff --git a/source3/auth/auth_sam.c b/source3/auth/auth_sam.c
index 558c181f70..fb53941b79 100644
--- a/source3/auth/auth_sam.c
+++ b/source3/auth/auth_sam.c
@@ -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 */
diff --git a/source3/auth/auth_script.c b/source3/auth/auth_script.c
index 1a715fca31..1bc33ec59e 100644
--- a/source3/auth/auth_script.c
+++ b/source3/auth/auth_script.c
@@ -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;
}
diff --git a/source3/auth/auth_server.c b/source3/auth/auth_server.c
index 7bce32ef2b..8eed8bba6a 100644
--- a/source3/auth/auth_server.c
+++ b/source3/auth/auth_server.c
@@ -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
{
diff --git a/source3/auth/auth_unix.c b/source3/auth/auth_unix.c
index f744cba0c4..df0703d348 100644
--- a/source3/auth/auth_unix.c
+++ b/source3/auth/auth_unix.c
@@ -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() ?
diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c
index eb15fff7c8..27dab9b9aa 100644
--- a/source3/auth/auth_util.c
+++ b/source3/auth/auth_util.c
@@ -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
@@ -26,6 +27,12 @@
#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);
@@ -1506,38 +1667,19 @@ void free_user_info(auth_usersupplied_info **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
***************************************************************************/
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);
@@ -1551,40 +1693,28 @@ BOOL make_auth_methods(struct auth_context *auth_context, auth_methods **auth_me
}
/****************************************************************************
- 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;
diff --git a/source3/auth/auth_winbind.c b/source3/auth/auth_winbind.c
index ad72bd9a1f..6e2f26a572 100644
--- a/source3/auth/auth_winbind.c
+++ b/source3/auth/auth_winbind.c
@@ -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);
}
diff --git a/source3/configure.in b/source3/configure.in
index 7079bf7437..e901e065d2 100644
--- a/source3/configure.in
+++ b/source3/configure.in
@@ -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)
diff --git a/source3/groupdb/mapping.c b/source3/groupdb/mapping.c
index 7dc0426c44..2790d47587 100644
--- a/source3/groupdb/mapping.c
+++ b/source3/groupdb/mapping.c
@@ -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));
}
diff --git a/source3/include/ads.h b/source3/include/ads.h
index decb823ea9..ce643666ad 100644
--- a/source3/include/ads.h
+++ b/source3/include/ads.h
@@ -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"
diff --git a/source3/include/auth.h b/source3/include/auth.h
index 03206c03c6..79fbb93895 100644
--- a/source3/include/auth.h
+++ b/source3/include/auth.h
@@ -20,12 +20,6 @@
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;
diff --git a/source3/include/doserr.h b/source3/include/doserr.h
index 62c1e4fa22..8f8ea06696 100644
--- a/source3/include/doserr.h
+++ b/source3/include/doserr.h
@@ -200,6 +200,7 @@
#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
index 0000000000..fdb990678d
--- /dev/null
+++ b/source3/include/event.h
@@ -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
index 0000000000..65c96c31e6
--- /dev/null
+++ b/source3/include/gpo.h
@@ -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;
+};
diff --git a/source3/include/idmap.h b/source3/include/idmap.h
index c81b94a718..474982f292 100644
--- a/source3/include/idmap.h
+++ b/source3/include/idmap.h
@@ -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);
diff --git a/source3/include/includes.h b/source3/include/includes.h
index a9b792d5f6..8aa1003240 100644
--- a/source3/include/includes.h
+++ b/source3/include/includes.h
@@ -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 */
diff --git a/source3/include/local.h b/source3/include/local.h
index c9b54ab1a2..916fb6e46d 100644
--- a/source3/include/local.h
+++ b/source3/include/local.h
@@ -238,4 +238,13 @@
/* 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
diff --git a/source3/include/messages.h b/source3/include/messages.h
index 4b1732d42d..dc4f4ca2c0 100644
--- a/source3/include/messages.h
+++ b/source3/include/messages.h
@@ -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. */
diff --git a/source3/include/nt_status.h b/source3/include/nt_status.h
index ab768258df..14c83eba4b 100644
--- a/source3/include/nt_status.h
+++ b/source3/include/nt_status.h
@@ -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
diff --git a/source3/include/passdb.h b/source3/include/passdb.h
index f1896710dc..0035fc5b05 100644
--- a/source3/include/passdb.h
+++ b/source3/include/passdb.h
@@ -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 **);
diff --git a/source3/include/rpc_dfs.h b/source3/include/rpc_dfs.h
index 7aee208c14..adf25c9938 100644
--- a/source3/include/rpc_dfs.h
+++ b/source3/include/rpc_dfs.h
@@ -1,164 +1,396 @@
-/*
- 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 */
diff --git a/source3/include/rpc_lsa.h b/source3/include/rpc_lsa.h
index dd255c28d5..c8d6a210b5 100644
--- a/source3/include/rpc_lsa.h
+++ b/source3/include/rpc_lsa.h
@@ -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 */
diff --git a/source3/include/rpc_netlogon.h b/source3/include/rpc_netlogon.h
index c1d8540344..91f85601e3 100644
--- a/source3/include/rpc_netlogon.h
+++ b/source3/include/rpc_netlogon.h
@@ -86,8 +86,17 @@
#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
diff --git a/source3/include/rpc_samr.h b/source3/include/rpc_samr.h
index 342db37ea5..2fae514c3d 100644
--- a/source3/include/rpc_samr.h
+++ b/source3/include/rpc_samr.h
@@ -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
{
diff --git a/source3/include/secrets.h b/source3/include/secrets.h
index f2d1afd96b..610a14b52b 100644
--- a/source3/include/secrets.h
+++ b/source3/include/secrets.h
@@ -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
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 3a6f68b9ec..b167e4ee12 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -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};
diff --git a/source3/include/smbldap.h b/source3/include/smbldap.h
index bea1a6d84a..8870205bbb 100644
--- a/source3/include/smbldap.h
+++ b/source3/include/smbldap.h
@@ -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 */
diff --git a/source3/intl/lang_tdb.c b/source3/intl/lang_tdb.c
index d3422f0d78..d20a15d90e 100644
--- a/source3/intl/lang_tdb.c
+++ b/source3/intl/lang_tdb.c
@@ -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;
diff --git a/source3/lib/dummysmbd.c b/source3/lib/dummysmbd.c
index 1b31dff499..9b587224e3 100644
--- a/source3/lib/dummysmbd.c
+++ b/source3/lib/dummysmbd.c
@@ -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
index 0000000000..314f074979
--- /dev/null
+++ b/source3/lib/events.c
@@ -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;
+}
diff --git a/source3/lib/genrand.c b/source3/lib/genrand.c
index f37bbc9c2f..5b643bf297 100644
--- a/source3/lib/genrand.c
+++ b/source3/lib/genrand.c
@@ -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);
}
/*
diff --git a/source3/lib/messages.c b/source3/lib/messages.c
index 058bbc99b0..2d6518aed6 100644
--- a/source3/lib/messages.c
+++ b/source3/lib/messages.c
@@ -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);
+}
/** @} **/
diff --git a/source3/lib/pam_errors.c b/source3/lib/pam_errors.c
index 212d3831fd..8a4c41d7df 100644
--- a/source3/lib/pam_errors.c
+++ b/source3/lib/pam_errors.c
@@ -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}
};
diff --git a/source3/lib/pidfile.c b/source3/lib/pidfile.c
index b041eb7f1b..08e41083b5 100644
--- a/source3/lib/pidfile.c
+++ b/source3/lib/pidfile.c
@@ -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;
}
diff --git a/source3/lib/readline.c b/source3/lib/readline.c
index 78b99fd7fb..c1f1dc7f40 100644
--- a/source3/lib/readline.c
+++ b/source3/lib/readline.c
@@ -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
diff --git a/source3/lib/secdesc.c b/source3/lib/secdesc.c
index ace0aee866..273bf0f0a3 100644
--- a/source3/lib/secdesc.c
+++ b/source3/lib/secdesc.c
@@ -23,6 +23,15 @@
#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
index 0000000000..b98e304582
--- /dev/null
+++ b/source3/lib/sharesec.c
@@ -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;
+}
diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c
index 609816b877..c045be51c5 100644
--- a/source3/lib/smbldap.c
+++ b/source3/lib/smbldap.c
@@ -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
********************************************************************/
diff --git a/source3/lib/smbldap_util.c b/source3/lib/smbldap_util.c
index 4679b86487..7b4cf4d079 100644
--- a/source3/lib/smbldap_util.c
+++ b/source3/lib/smbldap_util.c
@@ -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)));
diff --git a/source3/lib/system_smbd.c b/source3/lib/system_smbd.c
index 6c65f61ad7..1d4f88fbb9 100644
--- a/source3/lib/system_smbd.c
+++ b/source3/lib/system_smbd.c
@@ -28,47 +28,6 @@
#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;
diff --git a/source3/lib/username.c b/source3/lib/username.c
index 7d66b320ad..c04dfd05da 100644
--- a/source3/lib/username.c
+++ b/source3/lib/username.c
@@ -22,8 +22,12 @@
#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);
}
diff --git a/source3/lib/util.c b/source3/lib/util.c
index 38878befc7..dc57839df3 100644
--- a/source3/lib/util.c
+++ b/source3/lib/util.c
@@ -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;
}
diff --git a/source3/lib/util_file.c b/source3/lib/util_file.c
index 407a8b24fc..53a9bc9b41 100644
--- a/source3/lib/util_file.c
+++ b/source3/lib/util_file.c
@@ -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;
}
diff --git a/source3/lib/util_pw.c b/source3/lib/util_pw.c
index 13349bad34..e026affb44 100644
--- a/source3/lib/util_pw.c
+++ b/source3/lib/util_pw.c
@@ -22,69 +22,45 @@
#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);
}
diff --git a/source3/lib/util_sid.c b/source3/lib/util_sid.c
index e2b2ebf28c..c7f9dc2fdb 100644
--- a/source3/lib/util_sid.c
+++ b/source3/lib/util_sid.c
@@ -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
diff --git a/source3/lib/util_str.c b/source3/lib/util_str.c
index 0b02487f77..85b5cfc90a 100644
--- a/source3/lib/util_str.c
+++ b/source3/lib/util_str.c
@@ -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;
+}
+
diff --git a/source3/lib/util_unistr.c b/source3/lib/util_unistr.c
index 880416a549..bc90314fce 100644
--- a/source3/lib/util_unistr.c
+++ b/source3/lib/util_unistr.c
@@ -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
index 0000000000..9cf7aae977
--- /dev/null
+++ b/source3/libads/gpo.c
@@ -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
index 0000000000..8f913c1971
--- /dev/null
+++ b/source3/libads/gpo_util.c
@@ -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);
+}
diff --git a/source3/libads/kerberos.c b/source3/libads/kerberos.c
index d5b4b11fa2..67f8433775 100644
--- a/source3/libads/kerberos.c
+++ b/source3/libads/kerberos.c
@@ -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
index 0000000000..cd227d4377
--- /dev/null
+++ b/source3/libads/krb5_errs.c
@@ -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
+
diff --git a/source3/libads/krb5_setpw.c b/source3/libads/krb5_setpw.c
index 31d0a02cad..6ffd218e96 100644
--- a/source3/libads/krb5_setpw.c
+++ b/source3/libads/krb5_setpw.c
@@ -24,9 +24,17 @@
#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);
}
diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c
index e503da62a4..8444989bac 100644
--- a/source3/libads/ldap.c
+++ b/source3/libads/ldap.c
@@ -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
@@ -808,6 +809,65 @@ char *ads_get_dn(ADS_STRUCT *ads, void *msg)
}
/**
+ * 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
* @param res ** which will contain results - free res* with ads_msgfree()
@@ -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
diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c
index f6adfb5108..d8d33a924f 100644
--- a/source3/libads/sasl.c
+++ b/source3/libads/sasl.c
@@ -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;
diff --git a/source3/libmsrpc/cac_lsarpc.c b/source3/libmsrpc/cac_lsarpc.c
index d2e52f01a4..b157f33c69 100644
--- a/source3/libmsrpc/cac_lsarpc.c
+++ b/source3/libmsrpc/cac_lsarpc.c
@@ -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;
diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c
index 7c15c8d19f..6f32fb1b5d 100644
--- a/source3/libsmb/cliconnect.c
+++ b/source3/libsmb/cliconnect.c
@@ -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);
diff --git a/source3/libsmb/clidfs.c b/source3/libsmb/clidfs.c
index 51f21397f7..c5cf75783b 100644
--- a/source3/libsmb/clidfs.c
+++ b/source3/libsmb/clidfs.c
@@ -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;
}
diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c
index 2f980adcf8..55addd44a6 100644
--- a/source3/libsmb/clientgen.c
+++ b/source3/libsmb/clientgen.c
@@ -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;
}
/****************************************************************************
diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c
index e0dcefeb1d..55a705d7f0 100644
--- a/source3/libsmb/clikrb5.c
+++ b/source3/libsmb/clikrb5.c
@@ -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;
@@ -991,10 +994,154 @@ out:
#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;
diff --git a/source3/libsmb/clilist.c b/source3/libsmb/clilist.c
index 48780e28df..252dafcfa8 100644
--- a/source3/libsmb/clilist.c
+++ b/source3/libsmb/clilist.c
@@ -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;
diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c
index cc481a066a..13bf1a866c 100644
--- a/source3/libsmb/clispnego.c
+++ b/source3/libsmb/clispnego.c
@@ -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;
diff --git a/source3/libsmb/conncache.c b/source3/libsmb/conncache.c
index 2af4d57b80..49512d7a2e 100644
--- a/source3/libsmb/conncache.c
+++ b/source3/libsmb/conncache.c
@@ -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
diff --git a/source3/libsmb/errormap.c b/source3/libsmb/errormap.c
index 3c0b13ad6f..f6b5af068a 100644
--- a/source3/libsmb/errormap.c
+++ b/source3/libsmb/errormap.c
@@ -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
index 0000000000..0257138ece
--- /dev/null
+++ b/source3/libsmb/gpo.c
@@ -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
+*/
diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c
index 44cb43c285..03dbd71e93 100644
--- a/source3/libsmb/libsmbclient.c
+++ b/source3/libsmb/libsmbclient.c
@@ -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) {
diff --git a/source3/libsmb/passchange.c b/source3/libsmb/passchange.c
index 8b811b06ea..673671d28d 100644
--- a/source3/libsmb/passchange.c
+++ b/source3/libsmb/passchange.c
@@ -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;
}
}
}
diff --git a/source3/nsswitch/pam_winbind.c b/source3/nsswitch/pam_winbind.c
index 61c01daa16..57e05dc4bb 100644
--- a/source3/nsswitch/pam_winbind.c
+++ b/source3/nsswitch/pam_winbind.c
@@ -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(pamh, PAM_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.
diff --git a/source3/nsswitch/pam_winbind.h b/source3/nsswitch/pam_winbind.h
index 86ba977287..1e38269e0e 100644
--- a/source3/nsswitch/pam_winbind.h
+++ b/source3/nsswitch/pam_winbind.h
@@ -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;\
+ };\
+};
diff --git a/source3/nsswitch/wb_client.c b/source3/nsswitch/wb_client.c
index fcab76b033..ff0f15a122 100644
--- a/source3/nsswitch/wb_client.c
+++ b/source3/nsswitch/wb_client.c
@@ -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;
}
diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c
index 793a05f179..571a1b3e19 100644
--- a/source3/nsswitch/wbinfo.c
+++ b/source3/nsswitch/wbinfo.c
@@ -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" },
@@ -1016,6 +1100,11 @@ int main(int argc, char **argv)
#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
POPT_TABLEEND
@@ -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;
diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c
index bbcf2b5e88..4a269bac17 100644
--- a/source3/nsswitch/winbindd.c
+++ b/source3/nsswitch/winbindd.c
@@ -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 */
diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h
index 00a0233055..e81102571c 100644
--- a/source3/nsswitch/winbindd.h
+++ b/source3/nsswitch/winbindd.h
@@ -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 */
diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c
index 29129e823a..a866365042 100644
--- a/source3/nsswitch/winbindd_ads.c
+++ b/source3/nsswitch/winbindd_ads.c
@@ -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,
};
diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c
index 9ecfb1ff6e..28633757c0 100644
--- a/source3/nsswitch/winbindd_cache.c
+++ b/source3/nsswitch/winbindd_cache.c
@@ -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
@@ -29,6 +29,12 @@
#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;
@@ -188,6 +171,22 @@ static uint32 centry_uint32(struct cache_entry *centry)
}
/*
+ 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
*/
static uint8 centry_uint8(struct cache_entry *centry)
@@ -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",
@@ -522,6 +583,16 @@ static void centry_put_uint32(struct cache_entry *centry, uint32 v)
}
/*
+ 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
*/
static void centry_put_uint8(struct cache_entry *centry, uint8 v)
@@ -563,6 +634,28 @@ static void centry_put_sid(struct cache_entry *centry, const DOM_SID *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()
*/
struct cache_entry *centry_start(struct winbindd_domain *domain, NTSTATUS status)
@@ -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
+};
diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c
index 177ac54d3e..568078f86e 100644
--- a/source3/nsswitch/winbindd_cm.c
+++ b/source3/nsswitch/winbindd_cm.c
@@ -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
index 0000000000..a8aab04031
--- /dev/null
+++ b/source3/nsswitch/winbindd_cred_cache.c
@@ -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
index 0000000000..d37e9019db
--- /dev/null
+++ b/source3/nsswitch/winbindd_creds.c
@@ -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);
+}
+
+
diff --git a/source3/nsswitch/winbindd_dual.c b/source3/nsswitch/winbindd_dual.c
index 38030ee9ac..1988f36b51 100644
--- a/source3/nsswitch/winbindd_dual.c
+++ b/source3/nsswitch/winbindd_dual.c
@@ -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);
diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c
index ff2d19f5fc..a328cebac4 100644
--- a/source3/nsswitch/winbindd_group.c
+++ b/source3/nsswitch/winbindd_group.c
@@ -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;
}
-
diff --git a/source3/nsswitch/winbindd_misc.c b/source3/nsswitch/winbindd_misc.c
index 1fbf4b33df..b6aecae393 100644
--- a/source3/nsswitch/winbindd_misc.c
+++ b/source3/nsswitch/winbindd_misc.c
@@ -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 */
diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h
index eda68ae5c7..033e51d794 100644
--- a/source3/nsswitch/winbindd_nss.h
+++ b/source3/nsswitch/winbindd_nss.h
@@ -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
diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c
index 890007ae38..ab20102f79 100644
--- a/source3/nsswitch/winbindd_pam.c
+++ b/source3/nsswitch/winbindd_pam.c
@@ -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
@@ -27,6 +28,70 @@
#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;
+}
+
diff --git a/source3/nsswitch/winbindd_passdb.c b/source3/nsswitch/winbindd_passdb.c
index c32aa01a38..96a85a4f3a 100644
--- a/source3/nsswitch/winbindd_passdb.c
+++ b/source3/nsswitch/winbindd_passdb.c
@@ -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,
};
diff --git a/source3/nsswitch/winbindd_reconnect.c b/source3/nsswitch/winbindd_reconnect.c
index 77df9c1513..e37bfcad97 100644
--- a/source3/nsswitch/winbindd_reconnect.c
+++ b/source3/nsswitch/winbindd_reconnect.c
@@ -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,
};
diff --git a/source3/nsswitch/winbindd_rpc.c b/source3/nsswitch/winbindd_rpc.c
index 6179189e30..4aaedad4a2 100644
--- a/source3/nsswitch/winbindd_rpc.c
+++ b/source3/nsswitch/winbindd_rpc.c
@@ -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,
};
diff --git a/source3/nsswitch/winbindd_sid.c b/source3/nsswitch/winbindd_sid.c
index fc878cb5cc..a4cd8f7604 100644
--- a/source3/nsswitch/winbindd_sid.c
+++ b/source3/nsswitch/winbindd_sid.c
@@ -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;
}
+
diff --git a/source3/nsswitch/winbindd_user.c b/source3/nsswitch/winbindd_user.c
index 0b88d5eee5..9670bf534c 100644
--- a/source3/nsswitch/winbindd_user.c
+++ b/source3/nsswitch/winbindd_user.c
@@ -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;
diff --git a/source3/nsswitch/winbindd_util.c b/source3/nsswitch/winbindd_util.c
index 4c3306a8ac..b92ee0de82 100644
--- a/source3/nsswitch/winbindd_util.c
+++ b/source3/nsswitch/winbindd_util.c
@@ -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.
*****************************************************************************/
diff --git a/source3/pam_smbpass/pam_smb_auth.c b/source3/pam_smbpass/pam_smb_auth.c
index 70275abf92..cbdb6fa811 100644
--- a/source3/pam_smbpass/pam_smb_auth.c
+++ b/source3/pam_smbpass/pam_smb_auth.c
@@ -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';
diff --git a/source3/pam_smbpass/pam_smb_passwd.c b/source3/pam_smbpass/pam_smb_passwd.c
index 8149bc1200..176b278c04 100644
--- a/source3/pam_smbpass/pam_smb_passwd.c
+++ b/source3/pam_smbpass/pam_smb_passwd.c
@@ -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)",
diff --git a/source3/pam_smbpass/support.c b/source3/pam_smbpass/support.c
index 3f2c638816..add74acc5d 100644
--- a/source3/pam_smbpass/support.c
+++ b/source3/pam_smbpass/support.c
@@ -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()),
diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c
index a2aa851b09..a886728047 100644
--- a/source3/param/loadparm.c
+++ b/source3/param/loadparm.c
@@ -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) {
@@ -4190,6 +4241,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);
}
}
diff --git a/source3/param/params.c b/source3/param/params.c
index 2a6c8b3e65..f5ce6bdb64 100644
--- a/source3/param/params.c
+++ b/source3/param/params.c
@@ -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)) );
diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c
index 4640eb6ae5..6266aa9cab 100644
--- a/source3/passdb/lookup_sid.c
+++ b/source3/passdb/lookup_sid.c
@@ -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;
}
diff --git a/source3/passdb/machine_sid.c b/source3/passdb/machine_sid.c
index 074a516bcb..d7cae06749 100644
--- a/source3/passdb/machine_sid.c
+++ b/source3/passdb/machine_sid.c
@@ -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);
diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c
index f9f6021d81..90a51d1cbd 100644
--- a/source3/passdb/passdb.c
+++ b/source3/passdb/passdb.c
@@ -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.
@@ -732,129 +837,11 @@ BOOL algorithmic_pdb_rid_is_user(uint32 rid)
}
/*******************************************************************
- 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
*********************************************************************/
diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c
index 783e9e23fa..71fb36e0d5 100644
--- a/source3/passdb/pdb_get_set.c
+++ b/source3/passdb/pdb_get_set.c
@@ -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;
diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c
index 4808af3908..d8afff2111 100644
--- a/source3/passdb/pdb_interface.c
+++ b/source3/passdb/pdb_interface.c
@@ -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;
diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c
index b35ce18eee..a21e976803 100644
--- a/source3/passdb/pdb_ldap.c
+++ b/source3/passdb/pdb_ldap.c
@@ -84,13 +84,12 @@
#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;
diff --git a/source3/passdb/pdb_nds.c b/source3/passdb/pdb_nds.c
index cf2d1d7c8a..49c3c9db06 100644
--- a/source3/passdb/pdb_nds.c
+++ b/source3/passdb/pdb_nds.c
@@ -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) {
diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c
index 487df96e95..06a3f4f4a1 100644
--- a/source3/passdb/pdb_smbpasswd.c
+++ b/source3/passdb/pdb_smbpasswd.c
@@ -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);
diff --git a/source3/passdb/pdb_tdb.c b/source3/passdb/pdb_tdb.c
index 370c8adc7d..74f47e70dc 100644
--- a/source3/passdb/pdb_tdb.c
+++ b/source3/passdb/pdb_tdb.c
@@ -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) {
diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c
index 88dabbd644..69bafc7ce5 100644
--- a/source3/passdb/secrets.c
+++ b/source3/passdb/secrets.c
@@ -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;
}
/*******************************************************************************
diff --git a/source3/passdb/util_builtin.c b/source3/passdb/util_builtin.c
index 12a98d24dd..9c59df1f68 100644
--- a/source3/passdb/util_builtin.c
+++ b/source3/passdb/util_builtin.c
@@ -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
index 0000000000..ee8cf2d8f0
--- /dev/null
+++ b/source3/passdb/util_unixsids.c
@@ -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;
+}
diff --git a/source3/passdb/util_wellknown.c b/source3/passdb/util_wellknown.c
index 8caae3b2a0..be3cf37446 100644
--- a/source3/passdb/util_wellknown.c
+++ b/source3/passdb/util_wellknown.c
@@ -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.
***************************************************************************/
diff --git a/source3/printing/nt_printing.c b/source3/printing/nt_printing.c
index a91c2a5c70..e6c6f7d3dc 100644
--- a/source3/printing/nt_printing.c
+++ b/source3/printing/nt_printing.c
@@ -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);
diff --git a/source3/printing/print_generic.c b/source3/printing/print_generic.c
index b2484d5b43..18fca67860 100644
--- a/source3/printing/print_generic.c
+++ b/source3/printing/print_generic.c
@@ -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 */
diff --git a/source3/python/py_lsa.c b/source3/python/py_lsa.c
index 4f809520bc..a4e8254e0d 100644
--- a/source3/python/py_lsa.c
+++ b/source3/python/py_lsa.c
@@ -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));
diff --git a/source3/rpc_client/cli_dfs.c b/source3/rpc_client/cli_dfs.c
index 78df220ac2..8b94d6ed9d 100644
--- a/source3/rpc_client/cli_dfs.c
+++ b/source3/rpc_client/cli_dfs.c
@@ -1,183 +1,632 @@
-/*
- 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);
}
+
diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c
index aa1cb95fda..9331d09093 100644
--- a/source3/rpc_client/cli_lsarpc.c
+++ b/source3/rpc_client/cli_lsarpc.c
@@ -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;
+}
+
diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c
index b5addf3375..3dc26f61c9 100644
--- a/source3/rpc_client/cli_netlogon.c
+++ b/source3/rpc_client/cli_netlogon.c
@@ -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;
}
diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c
index 23c66acf26..9cc350bef1 100644
--- a/source3/rpc_client/cli_pipe.c
+++ b/source3/rpc_client/cli_pipe.c
@@ -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 "
diff --git a/source3/rpc_client/cli_samr.c b/source3/rpc_client/cli_samr.c
index fb95da97ae..744d8174a0 100644
--- a/source3/rpc_client/cli_samr.c
+++ b/source3/rpc_client/cli_samr.c
@@ -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;
diff --git a/source3/rpc_parse/parse_dfs.c b/source3/rpc_parse/parse_dfs.c
index f102e95004..f1d0705302 100644
--- a/source3/rpc_parse/parse_dfs.c
+++ b/source3/rpc_parse/parse_dfs.c
@@ -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"
@@ -26,519 +8,2660 @@
#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))
+ if (!prs_uint32("ptr0_path", ps, depth, &v->ptr0_path))
return False;
-
- if(!prs_align(ps))
+
+
+ if (!prs_uint32("ptr0_comment", ps, depth, &v->ptr0_comment))
return False;
-
- if(!prs_uint32("ptr_ServerName", ps, depth, &q_d->ptr_ServerName))
+
+
+ if (!prs_uint32("state", ps, depth, &v->state))
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("num_stores", ps, depth, &v->num_stores))
return False;
+
+ return True;
+}
- if(!prs_uint32("ptr_ShareName", ps, depth, &q_d->ptr_ShareName))
+BOOL netdfs_io_dfs_Info2_d(const char *desc, NETDFS_DFS_INFO2 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
- if(q_d->ptr_ShareName)
- if (!smb_io_unistr2("ShareName",&q_d->ShareName, q_d->ptr_ShareName, ps, depth))
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info2_d");
+ depth++;
+ if (v->ptr0_path) {
+ if (!prs_align_custom(ps, 4))
return False;
- if(!prs_align(ps))
- 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;
}
-/*******************************************************************
-Read/write a DFS_R_DFS_REMOVE structure
-*******************************************************************/
+BOOL init_netdfs_dfs_StorageInfo(NETDFS_DFS_STORAGEINFO *v, uint32 state, const char *server, const char *share)
+{
+ 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 {
+ 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 dfs_io_r_dfs_remove(const char *desc, DFS_R_DFS_REMOVE *r_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(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_StorageInfo_p");
depth++;
-
- if(!prs_werror("status", ps, depth, &r_d->status))
+ if (!prs_uint32("state", ps, depth, &v->state))
return False;
-
+
+ if (!prs_uint32("ptr0_server", ps, depth, &v->ptr0_server))
+ return False;
+
+
+ if (!prs_uint32("ptr0_share", ps, depth, &v->ptr0_share))
+ return False;
+
+
return True;
}
-/*******************************************************************
-Make a DFS_Q_DFS_ADD structure
-*******************************************************************/
+BOOL netdfs_io_dfs_StorageInfo_d(const char *desc, NETDFS_DFS_STORAGEINFO *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_StorageInfo_d");
+ depth++;
+
+ 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_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_Info3(NETDFS_DFS_INFO3 *v, const char *path, const char *comment, uint32 state, uint32 num_stores, NETDFS_DFS_STORAGEINFO **stores)
{
- 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_Info3\n"));
+
+ if (path) {
+ v->ptr0_path = 1;
+ init_unistr2(&v->path, path, UNI_FLAGS_NONE);
} else {
- q_d->ptr_Comment = 0;
+ v->ptr0_path = 0;
}
-
- q_d->Flags = flags;
+
+ 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_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_Info3_p(const char *desc, NETDFS_DFS_INFO3 *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_Info3_p");
depth++;
-
- if(!prs_align(ps))
+ if (!prs_uint32("ptr0_path", ps, depth, &v->ptr0_path))
return False;
-
- if(!smb_io_unistr2("DfsEntryPath",&q_d->DfsEntryPath, 1, ps, depth))
+
+
+ if (!prs_uint32("ptr0_comment", ps, depth, &v->ptr0_comment))
return False;
- if(!prs_align(ps))
+
+
+ if (!prs_uint32("state", ps, depth, &v->state))
return False;
-
- if(!smb_io_unistr2("ServerName",&q_d->ServerName, 1, ps, depth))
+
+ if (!prs_uint32("num_stores", ps, depth, &v->num_stores))
return False;
- if(!prs_align(ps))
+
+ if (!prs_uint32("ptr0_stores", ps, depth, &v->ptr0_stores))
return False;
+
+
+ return True;
+}
+
+BOOL netdfs_io_dfs_Info3_d(const char *desc, NETDFS_DFS_INFO3 *v, prs_struct *ps, int depth)
+{
+ 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;
+}
- if(!prs_uint32("ptr_ShareName", ps, depth, &q_d->ptr_ShareName))
+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)
+{
+ 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;
+}
+
+BOOL netdfs_io_dfs_Info4_p(const char *desc, NETDFS_DFS_INFO4 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
- if(!smb_io_unistr2("ShareName",&q_d->ShareName, 1, ps, depth))
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info4_p");
+ depth++;
+ if (!prs_uint32("ptr0_path", ps, depth, &v->ptr0_path))
return False;
- if(!prs_align(ps))
+
+
+ if (!prs_uint32("ptr0_comment", ps, depth, &v->ptr0_comment))
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("timeout", ps, depth, &v->timeout))
return False;
- if(!prs_align(ps))
+
+ if (!smb_io_uuid("guid", &v->guid, ps, depth))
return False;
+
+ if (!prs_uint32("num_stores", ps, depth, &v->num_stores))
+ return False;
+
+ if (!prs_uint32("ptr0_stores", ps, depth, &v->ptr0_stores))
+ return False;
+
+
+ return True;
+}
- if(!prs_uint32("Flags", ps, depth, &q_d->Flags))
- return True;
-
+BOOL netdfs_io_dfs_Info4_d(const char *desc, NETDFS_DFS_INFO4 *v, prs_struct *ps, int depth)
+{
+ 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_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;
}
-/************************************************************
- Read/write a DFS_R_DFS_ADD 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_add(const char *desc, DFS_R_DFS_ADD *r_d, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_Info100_p(const char *desc, NETDFS_DFS_INFO100 *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_Info100_p");
depth++;
-
- if(!prs_werror("status", ps, depth, &r_d->status))
+ if (!prs_uint32("ptr0_comment", ps, depth, &v->ptr0_comment))
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 netdfs_io_dfs_Info100_d(const char *desc, NETDFS_DFS_INFO100 *v, prs_struct *ps, int depth)
{
- 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;
+ 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;
}
-/************************************************************
- Read/write a DFS_Q_GET_INFO structure
- ************************************************************/
+BOOL init_netdfs_dfs_Info101(NETDFS_DFS_INFO101 *v, uint32 state)
+{
+ DEBUG(5,("init_netdfs_dfs_Info101\n"));
+
+ v->state = state;
+
+ return True;
+}
-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_Info101_p(const char *desc, NETDFS_DFS_INFO101 *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_Info101_p");
depth++;
-
- if(!smb_io_unistr2("",&q_i->uni_path, 1, ps, depth))
+ if (!prs_uint32("state", ps, depth, &v->state))
return False;
+
+ return True;
+}
- if(!prs_align(ps))
+BOOL netdfs_io_dfs_Info101_d(const char *desc, NETDFS_DFS_INFO101 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info101_d");
+ depth++;
+
+ return True;
+}
- if(!prs_uint32("ptr_server", ps, depth, &q_i->ptr_server))
+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;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info102_p");
+ depth++;
+ if (!prs_uint32("timeout", ps, depth, &v->timeout))
+ return False;
+
+ return True;
+}
- 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))
+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;
+}
- if(!prs_uint32("ptr_share", ps, depth, &q_i->ptr_share))
+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;
+}
+
+BOOL netdfs_io_dfs_Info200_p(const char *desc, NETDFS_DFS_INFO200 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
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))
+
+ 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;
+}
- if(!prs_uint32("level", ps, depth, &q_i->level))
+BOOL netdfs_io_dfs_Info200_d(const char *desc, NETDFS_DFS_INFO200 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info200_d");
+ depth++;
+ 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;
}
-/************************************************************
- Read/write a DFS_R_GET_INFO structure
- ************************************************************/
+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;
+}
-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_Info300_p(const char *desc, NETDFS_DFS_INFO300 *v, prs_struct *ps, int depth)
{
- if(r_i == NULL)
+ if (v == NULL)
return False;
-
- if(!prs_uint32("level", ps, depth, &r_i->level))
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_Info300_p");
+ depth++;
+ if (!prs_uint32("flags", ps, depth, &v->flags))
return False;
- if(!prs_uint32("ptr_ctr", ps, depth, &r_i->ptr_ctr))
+
+ if (!prs_uint32("ptr0_dom_root", ps, depth, &v->ptr0_dom_root))
return False;
+
+
+ return True;
+}
- if(!dfs_io_dfs_info_ctr("", &r_i->ctr, 1, r_i->level, ps, depth))
+BOOL netdfs_io_dfs_Info300_d(const char *desc, NETDFS_DFS_INFO300 *v, prs_struct *ps, int depth)
+{
+ if (v == NULL)
return False;
- if(!prs_werror("status", ps, depth, &r_i->status))
+
+ 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 (!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;
}
-
-/************************************************************
- 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_EnumArray1(NETDFS_DFS_ENUMARRAY1 *v, uint32 count, NETDFS_DFS_INFO1 **s)
{
- 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_EnumArray1\n"));
+
+ v->count = count;
+
+ if (s) {
+ v->ptr0_s = 1;
+ v->s = *s;
+ } else {
+ v->ptr0_s = 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_EnumArray1_p(const char *desc, NETDFS_DFS_ENUMARRAY1 *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_EnumArray1_p");
depth++;
-
- if(!prs_align(ps))
+ if (!prs_uint32("count", ps, depth, &v->count))
return False;
-
- if(!prs_uint32("level", ps, depth, &q_d->level))
+
+ if (!prs_uint32("ptr0_s", ps, depth, &v->ptr0_s))
return False;
- if(!prs_uint32("maxpreflen", ps, depth, &q_d->maxpreflen))
+
+
+ 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;
- if(!prs_uint32("ptr_buffer", ps, depth, &q_d->ptr_buffer))
+
+ 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;
- if(!prs_uint32("level2", ps, depth, &q_d->level2))
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray2_p");
+ depth++;
+ if (!prs_uint32("count", ps, depth, &v->count))
return False;
- if(!prs_uint32("level3", ps, depth, &q_d->level2))
+
+ if (!prs_uint32("ptr0_s", ps, depth, &v->ptr0_s))
return False;
-
- if(!prs_uint32("ptr_num_entries", ps, depth, &q_d->ptr_num_entries))
+
+
+ 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;
- if(!prs_uint32("num_entries", ps, depth, &q_d->num_entries))
+
+ 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;
- if(!prs_uint32("num_entries2", ps, depth, &q_d->num_entries2))
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumArray3_p");
+ depth++;
+ if (!prs_uint32("count", ps, depth, &v->count))
return False;
- if(!smb_io_enum_hnd("resume_hnd",&q_d->reshnd, ps, depth))
+
+ if (!prs_uint32("ptr0_s", ps, depth, &v->ptr0_s))
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_EnumArray3_d(const char *desc, NETDFS_DFS_ENUMARRAY3 *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;
+ 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=0;i<num_entries;i++) {
- if(!prs_uint32("ptr_entrypath",ps, depth, &ctr->dfs.info1[i].ptr_entrypath))
+ 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=0;i<num_entries;i++) {
- if(!smb_io_unistr2("", &ctr->dfs.info1[i].entrypath, ctr->dfs.info1[i].ptr_entrypath, ps, depth))
+ 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;
- if(!prs_align(ps))
+ }
+ }
+
+ 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;
}
- depth--;
- break;
- case 2:
- depth++;
- if(UNMARSHALLING(ps)) {
- ctr->dfs.info2 = PRS_ALLOC_MEM(ps, DFS_INFO_2, num_entries);
- if (!ctr->dfs.info2)
+ 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;
+}
- 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;
+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=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))
+ 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;
}
- depth--;
- break;
- case 3:
- depth++;
- if(UNMARSHALLING(ps)) {
- ctr->dfs.info3 = PRS_ALLOC_MEM(ps, DFS_INFO_3, num_entries);
- if (!ctr->dfs.info3)
+ 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;
+}
- 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))
+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;
- if(!prs_uint32("ptr_storages", ps, depth, &ctr->dfs.info3[i].ptr_storages))
+ }
+ 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;
}
- 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 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;
- if(!prs_align(ps))
+
+ depth--;
+ break;
+
+ case 2:
+ depth++;
+ if (!prs_uint32("ptr0_info2", ps, depth, &v->ptr0))
return False;
- if(!smb_io_unistr2("", &ctr->dfs.info3[i].comment, ctr->dfs.info3[i].ptr_comment, ps, depth))
+
+ depth--;
+ break;
+
+ case 3:
+ depth++;
+ if (!prs_uint32("ptr0_info3", ps, depth, &v->ptr0))
return False;
- if(!prs_align(ps))
+
+ depth--;
+ break;
+
+ case 4:
+ depth++;
+ if (!prs_uint32("ptr0_info4", ps, depth, &v->ptr0))
return False;
- if(!prs_uint32("num_storage_infos", ps, depth, &ctr->dfs.info3[i].num_storage_infos))
+
+ depth--;
+ break;
+
+ case 200:
+ depth++;
+ if (!prs_uint32("ptr0_info200", ps, depth, &v->ptr0))
return False;
-
- if(!dfs_io_dfs_storage_info("storage_info", &ctr->dfs.info3[i], ps, depth))
+
+ 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;
}
-/************************************************************
- Read/write a DFS_R_DFS_ENUM structure
- ************************************************************/
+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 dfs_io_r_dfs_enum(const char *desc, DFS_R_DFS_ENUM *q_d, prs_struct *ps, int depth)
+BOOL netdfs_io_dfs_EnumStruct_d(const char *desc, NETDFS_DFS_ENUMSTRUCT *v, prs_struct *ps, int depth)
{
- DFS_INFO_CTR *ctr;
- if(q_d == NULL)
+ if (v == NULL)
+ return False;
+
+ prs_debug(ps, depth, desc, "netdfs_io_dfs_EnumStruct_d");
+ depth++;
+
+ if (!prs_align_custom(ps, 4))
return False;
- ctr = q_d->ctr;
- if(ctr == NULL)
+
+ if (!netdfs_io_dfs_EnumInfo_d("e", &v->e, ps, depth))
return False;
+
+ return True;
+}
- prs_debug(ps, depth, desc, "dfs_io_r_dfs_enum");
+/* 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;
+}
- if(!prs_align(ps))
+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;
+}
- if(!prs_uint32("ptr_buffer", ps, depth, &q_d->ptr_buffer))
+BOOL netdfs_io_r_dfs_GetManagerVersion(const char *desc, NETDFS_R_DFS_GETMANAGERVERSION *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_r_dfs_GetManagerVersion");
+ depth++;
+ if (!prs_uint32("exist_flag", ps, depth, &v->exist_flag))
return False;
- if(!prs_uint32("level2", ps, depth, &ctr->switch_value))
+
+ 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_uint32("ptr_num_entries", ps, depth, &q_d->ptr_num_entries))
+
+ if (!prs_align_custom(ps, 4))
return False;
- if(q_d->ptr_num_entries)
- if(!prs_uint32("num_entries", ps, depth, &q_d->num_entries))
+
+ 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_uint32("ptr_num_entries2", ps, depth, &q_d->ptr_num_entries2))
+ }
+
+ if (!prs_align_custom(ps, 4))
+ return False;
+
+ if (!prs_uint32("ptr0_comment", ps, depth, &v->ptr0_comment))
return False;
- if(q_d->ptr_num_entries2)
- if(!prs_uint32("num_entries2", ps, depth, &ctr->num_entries))
+
+ 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;
+}
- if(!dfs_io_dfs_info_ctr("", ctr, q_d->num_entries, q_d->level, ps, depth))
+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;
+}
- if(!smb_io_enum_hnd("resume_hnd", &q_d->reshnd, ps, depth))
+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(!prs_werror("status", ps, depth, &q_d->status))
+
+ 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 dfs_io_dfs_storage_info(const char *desc, DFS_INFO_3* info3, prs_struct *ps, int depth)
+BOOL init_netdfs_r_dfs_Remove(NETDFS_R_DFS_REMOVE *v, const char *path, const char *server, const char *share, WERROR status)
{
- int i=0;
- if(info3 == NULL)
+ 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, "smb_io_dfs_storage_info");
+
+ prs_debug(ps, depth, desc, "netdfs_io_r_dfs_Remove");
depth++;
+ if (!prs_werror("status", ps, depth, &v->status))
+ return False;
+
+ return True;
+}
- if(UNMARSHALLING(ps)) {
- info3->storages = PRS_ALLOC_MEM(ps, DFS_STORAGE_INFO, info3->num_storage_infos);
- if (!info3->storages)
- return False;
+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;
+}
- for(i=0;i<info3->num_storage_infos;i++) {
- if(!prs_uint32("storage_state", ps, depth, &info3->storages[i].state))
+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(!prs_uint32("ptr_servername", ps, depth, &info3->storages[i].ptr_servername))
+
+ if (!smb_io_unistr2("server", &v->server, 1, ps, depth))
return False;
- if(!prs_uint32("ptr_sharename", ps, depth, &info3->storages[i].ptr_sharename))
+ }
+
+ 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;
+}
- 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))
+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(!prs_align(ps))
+ if (!netdfs_io_dfs_EnumStruct_d("info", &v->info, ps, depth))
return False;
- if(!smb_io_unistr2("sharename", &info3->storages[i].sharename, info3->storages[i].ptr_sharename, ps, depth))
+ }
+
+ 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(ps))
+ }
+
+ 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;
+}
+
diff --git a/source3/rpc_parse/parse_lsa.c b/source3/rpc_parse/parse_lsa.c
index 3d28b657f3..1edc017510 100644
--- a/source3/rpc_parse/parse_lsa.c
+++ b/source3/rpc_parse/parse_lsa.c
@@ -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;
+}
+
+
diff --git a/source3/rpc_parse/parse_net.c b/source3/rpc_parse/parse_net.c
index 3bd6977dbb..e7b1cdc767 100644
--- a/source3/rpc_parse/parse_net.c
+++ b/source3/rpc_parse/parse_net.c
@@ -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;
@@ -1490,6 +1490,47 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr,
/* "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"));
+ }
+
+
+}
+
/*******************************************************************
This code has been modified to cope with a NET_USER_INFO_2 - which is
exactly the same as a NET_USER_INFO_3, minus the other sids parameters.
@@ -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 */
diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c
index 7c84ee800b..c4f9f512ab 100644
--- a/source3/rpc_parse/parse_prs.c
+++ b/source3/rpc_parse/parse_prs.c
@@ -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.
diff --git a/source3/rpc_parse/parse_rpc.c b/source3/rpc_parse/parse_rpc.c
index ea4ec2c863..544d139acb 100644
--- a/source3/rpc_parse/parse_rpc.c
+++ b/source3/rpc_parse/parse_rpc.c
@@ -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 \
{ \
{ \
diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c
index 6c2b4f4ea7..7cbaa4e3c9 100644
--- a/source3/rpc_parse/parse_samr.c
+++ b/source3/rpc_parse/parse_samr.c
@@ -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"));
diff --git a/source3/rpc_server/srv_dfs.c b/source3/rpc_server/srv_dfs.c
index 42be7c5a35..44a9c06a3c 100644
--- a/source3/rpc_server/srv_dfs.c
+++ b/source3/rpc_server/srv_dfs.c
@@ -1,177 +1,602 @@
-/*
- * 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));
}
diff --git a/source3/rpc_server/srv_dfs_nt.c b/source3/rpc_server/srv_dfs_nt.c
index 63e4d4e9b7..f04d8c37c3 100644
--- a/source3/rpc_server/srv_dfs_nt.c
+++ b/source3/rpc_server/srv_dfs_nt.c
@@ -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;
+}
+
diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c
index f48f3e863a..c93107cec4 100644
--- a/source3/rpc_server/srv_lsa_nt.c
+++ b/source3/rpc_server/srv_lsa_nt.c
@@ -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;
}
@@ -227,87 +226,6 @@ static void init_reply_lookup_names(LSA_R_LOOKUP_NAMES *r_l,
}
/***************************************************************************
- 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);
}
/***************************************************************************
diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c
index 643921f596..fd78f954cc 100644
--- a/source3/rpc_server/srv_netlog_nt.c
+++ b/source3/rpc_server/srv_netlog_nt.c
@@ -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;
}
diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c
index 381adbe635..68b3a2d434 100644
--- a/source3/rpc_server/srv_pipe.c
+++ b/source3/rpc_server/srv_pipe.c
@@ -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;
diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c
index 37d3ef64c0..86a04e7ccb 100644
--- a/source3/rpc_server/srv_pipe_hnd.c
+++ b/source3/rpc_server/srv_pipe_hnd.c
@@ -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);
diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c
index 2f9d494a26..81344cdc1e 100644
--- a/source3/rpc_server/srv_samr_nt.c
+++ b/source3/rpc_server/srv_samr_nt.c
@@ -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;
}
/*********************************************************************
diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c
index a22d6db266..e6d45f76ec 100644
--- a/source3/rpc_server/srv_spoolss_nt.c
+++ b/source3/rpc_server/srv_spoolss_nt.c
@@ -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);
}
diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c
index 8150a8bf69..f279c98c31 100644
--- a/source3/rpc_server/srv_srvsvc_nt.c
+++ b/source3/rpc_server/srv_srvsvc_nt.c
@@ -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.
********************************************************************/
@@ -132,189 +112,10 @@ static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int sn
}
/*******************************************************************
- 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)) )
diff --git a/source3/rpcclient/cmd_dfs.c b/source3/rpcclient/cmd_dfs.c
index 956dbfa402..b4d43bda5e 100644
--- a/source3/rpcclient/cmd_dfs.c
+++ b/source3/rpcclient/cmd_dfs.c
@@ -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;
}
diff --git a/source3/rpcclient/cmd_lsarpc.c b/source3/rpcclient/cmd_lsarpc.c
index 5adaf46981..1b7ebac45f 100644
--- a/source3/rpcclient/cmd_lsarpc.c
+++ b/source3/rpcclient/cmd_lsarpc.c
@@ -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))
diff --git a/source3/rpcclient/cmd_samr.c b/source3/rpcclient/cmd_samr.c
index 991b55a13c..93a3e39036 100644
--- a/source3/rpcclient/cmd_samr.c
+++ b/source3/rpcclient/cmd_samr.c
@@ -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", "" },
diff --git a/source3/sam/idmap.c b/source3/sam/idmap.c
index 9fc1a573a9..aac8b70013 100644
--- a/source3/sam/idmap.c
+++ b/source3/sam/idmap.c
@@ -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) {
@@ -338,23 +362,6 @@ NTSTATUS idmap_allocate_id(unid_t *id, int 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.
**************************************************************************/
diff --git a/source3/sam/idmap_ad.c b/source3/sam/idmap_ad.c
index 47e349483d..f9a959e7ec 100644
--- a/source3/sam/idmap_ad.c
+++ b/source3/sam/idmap_ad.c
@@ -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,
diff --git a/source3/sam/idmap_ldap.c b/source3/sam/idmap_ldap.c
index b4a8c8a752..17482a5146 100644
--- a/source3/sam/idmap_ldap.c
+++ b/source3/sam/idmap_ldap.c
@@ -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,
diff --git a/source3/sam/idmap_rid.c b/source3/sam/idmap_rid.c
index eced549a55..0922000fa1 100644
--- a/source3/sam/idmap_rid.c
+++ b/source3/sam/idmap_rid.c
@@ -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,
diff --git a/source3/sam/idmap_smbldap.c b/source3/sam/idmap_smbldap.c
index b1aae2b86f..4d80364437 100644
--- a/source3/sam/idmap_smbldap.c
+++ b/source3/sam/idmap_smbldap.c
@@ -87,15 +87,6 @@ static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type)
}
/*****************************************************************************
- 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,
diff --git a/source3/sam/idmap_tdb.c b/source3/sam/idmap_tdb.c
index e89a6cf547..665c56d2f6 100644
--- a/source3/sam/idmap_tdb.c
+++ b/source3/sam/idmap_tdb.c
@@ -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;
@@ -46,41 +43,6 @@ static struct idmap_state {
} 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,
diff --git a/source3/sam/idmap_util.c b/source3/sam/idmap_util.c
index cac8934f7b..7233cb48cd 100644
--- a/source3/sam/idmap_util.c
+++ b/source3/sam/idmap_util.c
@@ -22,80 +22,6 @@
#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.
*****************************************************************/
diff --git a/source3/script/installman.sh b/source3/script/installman.sh
index 9235217ff0..3bbca1a8aa 100755
--- a/source3/script/installman.sh
+++ b/source3/script/installman.sh
@@ -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
diff --git a/source3/script/installswat.sh b/source3/script/installswat.sh
index c66fd29485..c5c285894e 100755
--- a/source3/script/installswat.sh
+++ b/source3/script/installswat.sh
@@ -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)
diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c
index bb30519319..0798541cb5 100644
--- a/source3/smbd/chgpasswd.c
+++ b/source3/smbd/chgpasswd.c
@@ -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);
}
diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c
index bb000bac30..bf4db99ea6 100644
--- a/source3/smbd/conn.c
+++ b/source3/smbd/conn.c
@@ -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);
diff --git a/source3/smbd/lanman.c b/source3/smbd/lanman.c
index 4778702e7a..83dfdf0d8b 100644
--- a/source3/smbd/lanman.c
+++ b/source3/smbd/lanman.c
@@ -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;
-
- switch (uLevel) {
- case 0: struct_len = 16; break;
- case 1: struct_len = 26; break;
- default: return -1;
- }
+ int struct_len;
+ char* p;
+ char* p2;
+ int l2;
+ int len;
- 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,87 +1709,104 @@ 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;
+ 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;
+ /* 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;
+ 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;
}
/****************************************************************************
@@ -1744,18 +1830,21 @@ static BOOL api_RNetGroupEnum(connection_struct *conn,uint16 vuid, char *param,c
int num_entries;
- if (strcmp(str1,"WrLeh") != 0)
+ 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)
+ /* 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,77 +3172,86 @@ 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;
+
+ 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,
@@ -3116,114 +3259,137 @@ static BOOL api_WPrintJobEnumerate(connection_struct *conn,uint16 vuid, char *pa
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;
+ 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 (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);
+ 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;
}
diff --git a/source3/smbd/msdfs.c b/source3/smbd/msdfs.c
index 1279fe185d..4f7858d985 100644
--- a/source3/smbd/msdfs.c
+++ b/source3/smbd/msdfs.c
@@ -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);
}
diff --git a/source3/smbd/ntquotas.c b/source3/smbd/ntquotas.c
index 9bc444d253..a824978ece 100644
--- a/source3/smbd/ntquotas.c
+++ b/source3/smbd/ntquotas.c
@@ -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",
diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c
index e12a24968b..417e3421cb 100644
--- a/source3/smbd/nttrans.c
+++ b/source3/smbd/nttrans.c
@@ -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);
diff --git a/source3/smbd/open.c b/source3/smbd/open.c
index 4b13e28f8e..4f28e291cd 100644
--- a/source3/smbd/open.c
+++ b/source3/smbd/open.c
@@ -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.
****************************************************************************/
diff --git a/source3/smbd/password.c b/source3/smbd/password.c
index 764fbe8a2e..e644550400 100644
--- a/source3/smbd/password.c
+++ b/source3/smbd/password.c
@@ -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;
}
diff --git a/source3/smbd/posix_acls.c b/source3/smbd/posix_acls.c
index 5db245ac0c..d4dd926089 100644
--- a/source3/smbd/posix_acls.c
+++ b/source3/smbd/posix_acls.c
@@ -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 {
diff --git a/source3/smbd/process.c b/source3/smbd/process.c
index 0b7b94cce2..d646ebe02d 100644
--- a/source3/smbd/process.c
+++ b/source3/smbd/process.c
@@ -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;
}
diff --git a/source3/smbd/sec_ctx.c b/source3/smbd/sec_ctx.c
index fc6a858974..ebc47c51d9 100644
--- a/source3/smbd/sec_ctx.c
+++ b/source3/smbd/sec_ctx.c
@@ -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;
@@ -180,51 +180,6 @@ fail:
}
/****************************************************************************
- 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 */
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 3e970ec16c..6c2034988a 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -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 */
diff --git a/source3/smbd/service.c b/source3/smbd/service.c
index 7640559d53..cf0116cc09 100644
--- a/source3/smbd/service.c
+++ b/source3/smbd/service.c
@@ -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
diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c
index a22a575c76..38e16126e2 100644
--- a/source3/smbd/sesssetup.c
+++ b/source3/smbd/sesssetup.c
@@ -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
index 0000000000..11e52b03ab
--- /dev/null
+++ b/source3/smbd/share_access.c
@@ -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;
+}
diff --git a/source3/smbd/uid.c b/source3/smbd/uid.c
index d419720c33..6e516d3562 100644
--- a/source3/smbd/uid.c
+++ b/source3/smbd/uid.c
@@ -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;
}
diff --git a/source3/utils/net.c b/source3/utils/net.c
index 25e10c6a31..069047c9ec 100644
--- a/source3/utils/net.c
+++ b/source3/utils/net.c
@@ -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},
diff --git a/source3/utils/net.h b/source3/utils/net.h
index 2df13cfb8f..fc3167012d 100644
--- a/source3/utils/net.h
+++ b/source3/utils/net.h
@@ -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
index 0000000000..fec6fb88fa
--- /dev/null
+++ b/source3/utils/net_ads_gpo.c
@@ -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
diff --git a/source3/utils/net_groupmap.c b/source3/utils/net_groupmap.c
index 1cff120c39..96a6aa531a 100644
--- a/source3/utils/net_groupmap.c
+++ b/source3/utils/net_groupmap.c
@@ -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;
diff --git a/source3/utils/net_help.c b/source3/utils/net_help.c
index c5188c3608..79062345ab 100644
--- a/source3/utils/net_help.c
+++ b/source3/utils/net_help.c
@@ -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}};
diff --git a/source3/utils/net_lookup.c b/source3/utils/net_lookup.c
index 8ee63515d4..dd2d666d5a 100644
--- a/source3/utils/net_lookup.c
+++ b/source3/utils/net_lookup.c
@@ -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}
};
diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c
index 0495a7b92c..a9dc3a1fc6 100644
--- a/source3/utils/net_rpc.c
+++ b/source3/utils/net_rpc.c
@@ -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}
};
diff --git a/source3/utils/net_rpc_rights.c b/source3/utils/net_rpc_rights.c
index 2c15fef5a0..2f02b40948 100644
--- a/source3/utils/net_rpc_rights.c
+++ b/source3/utils/net_rpc_rights.c
@@ -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;
+};
+
diff --git a/source3/utils/net_rpc_samsync.c b/source3/utils/net_rpc_samsync.c
index 09e62d9def..45fdfbfad3 100644
--- a/source3/utils/net_rpc_samsync.c
+++ b/source3/utils/net_rpc_samsync.c
@@ -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
index 0000000000..f9675e430b
--- /dev/null
+++ b/source3/utils/net_rpc_shell.c
@@ -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
index 0000000000..ba3ec5c57f
--- /dev/null
+++ b/source3/utils/net_sam.c
@@ -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
index 0000000000..c00f239b99
--- /dev/null
+++ b/source3/utils/net_usershare.c
@@ -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
index 0000000000..805104cefa
--- /dev/null
+++ b/source3/utils/net_util.c
@@ -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
index 0000000000..edb2f7d5ba
--- /dev/null
+++ b/source3/utils/netlookup.c
@@ -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;
+}
diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c
index 4759aec0cc..c22f4b5e09 100644
--- a/source3/utils/ntlm_auth.c
+++ b/source3/utils/ntlm_auth.c
@@ -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)));
diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c
index f41bbb8caa..0b17d50ad3 100644
--- a/source3/utils/pdbedit.c
+++ b/source3/utils/pdbedit.c
@@ -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");
diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c
index 26362c6270..cff3bc5dde 100644
--- a/source3/utils/smbcacls.c
+++ b/source3/utils/smbcacls.c
@@ -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;
diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c
index a4d2766b13..405e51cd25 100644
--- a/source3/utils/smbcontrol.c
+++ b/source3/utils/smbcontrol.c
@@ -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;
}
diff --git a/source3/utils/smbcquotas.c b/source3/utils/smbcquotas.c
index b1a14685f5..7b3268e783 100644
--- a/source3/utils/smbcquotas.c
+++ b/source3/utils/smbcquotas.c
@@ -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;
diff --git a/source3/utils/smbpasswd.c b/source3/utils/smbpasswd.c
index 7eb11137d7..4323ee29e0 100644
--- a/source3/utils/smbpasswd.c
+++ b/source3/utils/smbpasswd.c
@@ -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;
diff --git a/source3/web/cgi.c b/source3/web/cgi.c
index 6c9cfce13c..700fb7fa08 100644
--- a/source3/web/cgi.c
+++ b/source3/web/cgi.c
@@ -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;
}
diff --git a/source3/web/swat.c b/source3/web/swat.c
index 63253e41c4..af01d1f31b 100644
--- a/source3/web/swat.c
+++ b/source3/web/swat.c
@@ -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);
}
/****************************************************************************