mirror of
https://github.com/samba-team/samba.git
synced 2025-03-10 12:58:35 +03:00
r13316: Let the carnage begin....
Sync with trunk as off r13315
This commit is contained in:
parent
50c894a6e9
commit
17e63ac4ed
@ -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 $@"
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
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;
|
||||
for (i=0; lines[i]; i++) {
|
||||
char *buf = lines[i];
|
||||
trim_char(buf,' ',' ');
|
||||
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++;
|
||||
}
|
||||
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 (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;
|
||||
/* 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)
|
||||
continue;
|
||||
if (!host_ok && !is_group && strequal(remote, file_host)) {
|
||||
host_ok = True;
|
||||
}
|
||||
|
||||
/* 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);
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
@ -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 */
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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() ?
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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)
|
||||
|
@ -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));
|
||||
}
|
||||
|
||||
|
||||
|
@ -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"
|
||||
|
@ -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;
|
||||
|
@ -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)
|
||||
|
31
source/include/event.h
Normal file
31
source/include/event.h
Normal file
@ -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;
|
||||
};
|
||||
|
91
source/include/gpo.h
Normal file
91
source/include/gpo.h
Normal file
@ -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;
|
||||
};
|
@ -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);
|
||||
|
@ -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 */
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
@ -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. */
|
||||
|
@ -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
|
||||
|
@ -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 **);
|
||||
|
@ -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
|
||||
/*
|
||||
* Unix SMB/CIFS implementation.
|
||||
* header auto-generated by pidl. DO NOT MODIFY!
|
||||
*/
|
||||
|
||||
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
|
||||
#ifndef _RPC_NETDFS_H
|
||||
#define _RPC_NETDFS_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
|
||||
#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
|
||||
|
||||
/* dfsadd flags */
|
||||
#define DFSFLAG_ADD_VOLUME 0x00000001
|
||||
#define DFSFLAG_RESTORE_VOLUME 0x00000002
|
||||
|
||||
typedef struct dfs_q_dfs_exist {
|
||||
typedef struct netdfs_dfs_Info0 {
|
||||
uint32 dummy;
|
||||
} DFS_Q_DFS_EXIST;
|
||||
} NETDFS_DFS_INFO0;
|
||||
|
||||
/* 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 netdfs_dfs_Info1 {
|
||||
uint32 ptr0_path;
|
||||
UNISTR2 path;
|
||||
} NETDFS_DFS_INFO1;
|
||||
|
||||
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;
|
||||
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;
|
||||
uint32 ptr0_server;
|
||||
UNISTR2 server;
|
||||
uint32 ptr0_share;
|
||||
UNISTR2 share;
|
||||
} NETDFS_DFS_STORAGEINFO;
|
||||
|
||||
typedef struct dfs_info_3 {
|
||||
uint32 ptr_entrypath;
|
||||
UNISTR2 entrypath;
|
||||
uint32 ptr_comment;
|
||||
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 dfs_info_ctr {
|
||||
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 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;
|
||||
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 dfs_q_dfs_get_info {
|
||||
UNISTR2 uni_path;
|
||||
|
||||
uint32 ptr_server;
|
||||
UNISTR2 uni_server;
|
||||
typedef struct netdfs_dfs_EnumArray1 {
|
||||
uint32 count;
|
||||
uint32 ptr0_s;
|
||||
uint32 size_s;
|
||||
NETDFS_DFS_INFO1 *s;
|
||||
} NETDFS_DFS_ENUMARRAY1;
|
||||
|
||||
uint32 ptr_share;
|
||||
UNISTR2 uni_share;
|
||||
|
||||
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 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;
|
||||
} DFS_Q_DFS_GET_INFO;
|
||||
NETDFS_DFS_ENUMINFO_CTR e;
|
||||
} NETDFS_DFS_ENUMSTRUCT;
|
||||
|
||||
typedef struct dfs_r_dfs_get_info {
|
||||
uint32 level;
|
||||
uint32 ptr_ctr;
|
||||
DFS_INFO_CTR ctr;
|
||||
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;
|
||||
} DFS_R_DFS_GET_INFO;
|
||||
} NETDFS_R_DFS_ADD;
|
||||
|
||||
typedef struct dfs_q_dfs_enum {
|
||||
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 netdfs_q_dfs_Remove {
|
||||
UNISTR2 path;
|
||||
uint32 ptr0_server;
|
||||
UNISTR2 server;
|
||||
uint32 ptr0_share;
|
||||
UNISTR2 share;
|
||||
} NETDFS_Q_DFS_REMOVE;
|
||||
|
||||
typedef struct dfs_r_dfs_enum {
|
||||
DFS_INFO_CTR *ctr;
|
||||
uint32 ptr_buffer;
|
||||
uint32 level;
|
||||
uint32 level2;
|
||||
uint32 ptr_num_entries;
|
||||
uint32 num_entries;
|
||||
uint32 ptr_num_entries2;
|
||||
uint32 num_entries2;
|
||||
ENUM_HND reshnd;
|
||||
typedef struct netdfs_r_dfs_Remove {
|
||||
WERROR status;
|
||||
} DFS_R_DFS_ENUM;
|
||||
#endif
|
||||
} NETDFS_R_DFS_REMOVE;
|
||||
|
||||
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;
|
||||
} 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 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 */
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
{
|
||||
|
@ -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
|
||||
|
@ -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};
|
||||
|
||||
|
@ -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 */
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
}
|
||||
|
125
source/lib/events.c
Normal file
125
source/lib/events.c
Normal file
@ -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;
|
||||
}
|
@ -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);
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -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);
|
||||
}
|
||||
/** @} **/
|
||||
|
@ -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}
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
||||
|
308
source/lib/sharesec.c
Normal file
308
source/lib/sharesec.c
Normal file
@ -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;
|
||||
}
|
@ -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
|
||||
********************************************************************/
|
||||
|
@ -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);
|
||||
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),
|
||||
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),
|
||||
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),
|
||||
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)));
|
||||
|
@ -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 (!getgroups_user(username, primary_gid, pp_gids, p_num_groups)) {
|
||||
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_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;
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
return alloc_copy_passwd(temp);
|
||||
if (mem_ctx != NULL) {
|
||||
return talloc_reference(mem_ctx, pwnam_cache[i]);
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
if (result == (size_t)-1) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
*dest = talloc_strdup(mem_ctx, tmp);
|
||||
if (*dest == NULL) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
return result;
|
||||
return talloc_strdup(mem_ctx, tmp);
|
||||
}
|
||||
|
||||
/* Converts a string from internal samba format to unicode
|
||||
|
680
source/libads/gpo.c
Normal file
680
source/libads/gpo.c
Normal file
@ -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);
|
||||
}
|
496
source/libads/gpo_util.c
Normal file
496
source/libads/gpo_util.c
Normal file
@ -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);
|
||||
}
|
@ -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(),
|
||||
|
132
source/libads/krb5_errs.c
Normal file
132
source/libads/krb5_errs.c
Normal file
@ -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
|
||||
|
@ -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));
|
||||
DEBUG(1, ("Error changing password: %s (%d)\n", errstr, 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:
|
||||
return KRB5KDC_ERR_POLICY;
|
||||
default:
|
||||
return KRB5KRB_ERR_GENERIC;
|
||||
}
|
||||
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);
|
||||
}
|
||||
|
@ -4,6 +4,7 @@
|
||||
Copyright (C) Andrew Tridgell 2001
|
||||
Copyright (C) Remus Koos 2001
|
||||
Copyright (C) Jim McDonough <jmcd@us.ibm.com> 2002
|
||||
Copyright (C) Guenther Deschner 2005
|
||||
|
||||
This program is free software; you can redistribute it and/or modify
|
||||
it under the terms of the GNU General Public License as published by
|
||||
@ -807,6 +808,65 @@ char *ads_get_dn(ADS_STRUCT *ads, void *msg)
|
||||
return unix_dn;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get a canonical dn from search results
|
||||
* @param ads connection to ads server
|
||||
* @param msg Search result
|
||||
* @return dn string
|
||||
**/
|
||||
char *ads_get_dn_canonical(ADS_STRUCT *ads, void *msg)
|
||||
{
|
||||
#ifdef HAVE_LDAP_DN2AD_CANONICAL
|
||||
return ldap_dn2ad_canonical(ads_get_dn(ads, msg));
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Get the parent dn from a search result
|
||||
* @param ads connection to ads server
|
||||
* @param msg Search result
|
||||
* @return parent dn string
|
||||
**/
|
||||
char *ads_get_parent_dn(ADS_STRUCT *ads, void *msg)
|
||||
{
|
||||
char *mydn, *p, *dn;
|
||||
|
||||
dn = ads_get_dn(ads, msg);
|
||||
if (dn == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
mydn = dn;
|
||||
ads_memfree(ads, dn);
|
||||
|
||||
p = strchr(mydn, ',');
|
||||
|
||||
if (p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return p+1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the parent from a dn
|
||||
* @param dn the dn to return the parent from
|
||||
* @return parent dn string
|
||||
**/
|
||||
char *ads_parent_dn(const char *dn)
|
||||
{
|
||||
char *p = strchr(dn, ',');
|
||||
|
||||
if (p == NULL) {
|
||||
return NULL;
|
||||
}
|
||||
|
||||
return p+1;
|
||||
}
|
||||
|
||||
/**
|
||||
* Find a machine account given a hostname
|
||||
* @param ads connection to ads server
|
||||
@ -2700,4 +2760,167 @@ ADS_STATUS ads_workgroup_name(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char *
|
||||
return ADS_SUCCESS;
|
||||
}
|
||||
|
||||
/**
|
||||
* find our site name
|
||||
* @param ads connection to ads server
|
||||
* @param mem_ctx Pointer to talloc context
|
||||
* @param site_name Pointer to the sitename
|
||||
* @return status of search
|
||||
**/
|
||||
ADS_STATUS ads_site_dn(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char **site_name)
|
||||
{
|
||||
ADS_STATUS status;
|
||||
void *res;
|
||||
const char *dn, *service_name;
|
||||
const char *attrs[] = { "dsServiceName", NULL };
|
||||
|
||||
status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
|
||||
if (!ADS_ERR_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
service_name = ads_pull_string(ads, mem_ctx, res, "dsServiceName");
|
||||
if (service_name == NULL) {
|
||||
return ADS_ERROR(LDAP_NO_RESULTS_RETURNED);
|
||||
}
|
||||
|
||||
/* go up three levels */
|
||||
dn = ads_parent_dn(ads_parent_dn(ads_parent_dn(service_name)));
|
||||
if (dn == NULL) {
|
||||
return ADS_ERROR(LDAP_NO_MEMORY);
|
||||
}
|
||||
|
||||
*site_name = talloc_strdup(mem_ctx, dn);
|
||||
if (*site_name == NULL) {
|
||||
return ADS_ERROR(LDAP_NO_MEMORY);
|
||||
}
|
||||
|
||||
ads_msgfree(ads, res);
|
||||
|
||||
return status;
|
||||
/*
|
||||
dsServiceName: CN=NTDS Settings,CN=W2K3DC,CN=Servers,CN=Default-First-Site-Name,CN=Sites,CN=Configuration,DC=ber,DC=suse,DC=de
|
||||
*/
|
||||
}
|
||||
|
||||
/**
|
||||
* find the site dn where a machine resides
|
||||
* @param ads connection to ads server
|
||||
* @param mem_ctx Pointer to talloc context
|
||||
* @param computer_name name of the machine
|
||||
* @param site_name Pointer to the sitename
|
||||
* @return status of search
|
||||
**/
|
||||
ADS_STATUS ads_site_dn_for_machine(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, const char *computer_name, const char **site_dn)
|
||||
{
|
||||
ADS_STATUS status;
|
||||
void *res;
|
||||
const char *parent, *config_context, *filter;
|
||||
const char *attrs[] = { "configurationNamingContext", NULL };
|
||||
char *dn;
|
||||
|
||||
/* shortcut a query */
|
||||
if (strequal(computer_name, ads->config.ldap_server_name)) {
|
||||
return ads_site_dn(ads, mem_ctx, site_dn);
|
||||
}
|
||||
|
||||
status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
|
||||
if (!ADS_ERR_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
config_context = ads_pull_string(ads, mem_ctx, res, "configurationNamingContext");
|
||||
if (config_context == NULL) {
|
||||
return ADS_ERROR(LDAP_NO_MEMORY);
|
||||
}
|
||||
|
||||
filter = talloc_asprintf(mem_ctx, "(cn=%s)", computer_name);
|
||||
if (filter == NULL) {
|
||||
return ADS_ERROR(LDAP_NO_MEMORY);
|
||||
}
|
||||
|
||||
status = ads_do_search(ads, config_context, LDAP_SCOPE_SUBTREE, filter, NULL, &res);
|
||||
if (!ADS_ERR_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (ads_count_replies(ads, res) != 1) {
|
||||
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
|
||||
}
|
||||
|
||||
dn = ads_get_dn(ads, res);
|
||||
if (dn == NULL) {
|
||||
return ADS_ERROR(LDAP_NO_MEMORY);
|
||||
}
|
||||
|
||||
/* go up three levels */
|
||||
parent = ads_parent_dn(ads_parent_dn(ads_parent_dn(dn)));
|
||||
if (parent == NULL) {
|
||||
ads_memfree(ads, dn);
|
||||
return ADS_ERROR(LDAP_NO_MEMORY);
|
||||
}
|
||||
|
||||
*site_dn = talloc_strdup(mem_ctx, parent);
|
||||
if (*site_dn == NULL) {
|
||||
ads_memfree(ads, dn);
|
||||
ADS_ERROR(LDAP_NO_MEMORY);
|
||||
}
|
||||
|
||||
ads_memfree(ads, dn);
|
||||
ads_msgfree(ads, res);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/**
|
||||
* get the upn suffixes for a domain
|
||||
* @param ads connection to ads server
|
||||
* @param mem_ctx Pointer to talloc context
|
||||
* @param suffixes Pointer to an array of suffixes
|
||||
* @param site_name Pointer to the number of suffixes
|
||||
* @return status of search
|
||||
**/
|
||||
ADS_STATUS ads_upn_suffixes(ADS_STRUCT *ads, TALLOC_CTX *mem_ctx, char **suffixes, size_t *num_suffixes)
|
||||
{
|
||||
ADS_STATUS status;
|
||||
void *res;
|
||||
const char *config_context, *base;
|
||||
const char *attrs[] = { "configurationNamingContext", NULL };
|
||||
const char *attrs2[] = { "uPNSuffixes", NULL };
|
||||
|
||||
status = ads_do_search(ads, "", LDAP_SCOPE_BASE, "(objectclass=*)", attrs, &res);
|
||||
if (!ADS_ERR_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
config_context = ads_pull_string(ads, mem_ctx, res, "configurationNamingContext");
|
||||
if (config_context == NULL) {
|
||||
return ADS_ERROR(LDAP_NO_MEMORY);
|
||||
}
|
||||
|
||||
base = talloc_asprintf(mem_ctx, "cn=Partitions,%s", config_context);
|
||||
if (base == NULL) {
|
||||
return ADS_ERROR(LDAP_NO_MEMORY);
|
||||
}
|
||||
|
||||
status = ads_search_dn(ads, &res, base, attrs2);
|
||||
if (!ADS_ERR_OK(status)) {
|
||||
return status;
|
||||
}
|
||||
|
||||
if (ads_count_replies(ads, res) != 1) {
|
||||
return ADS_ERROR(LDAP_NO_SUCH_OBJECT);
|
||||
}
|
||||
|
||||
suffixes = ads_pull_strings(ads, mem_ctx, &res, "uPNSuffixes", num_suffixes);
|
||||
if (suffixes == NULL) {
|
||||
ads_msgfree(ads, res);
|
||||
return ADS_ERROR(LDAP_NO_MEMORY);
|
||||
}
|
||||
|
||||
ads_msgfree(ads, res);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
#endif
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
/****************************************************************************
|
||||
|
@ -409,9 +409,10 @@ static BOOL ads_cleanup_expired_creds(krb5_context context,
|
||||
krb5_creds *credsp)
|
||||
{
|
||||
krb5_error_code retval;
|
||||
const char *cc_type = krb5_cc_get_type(context, ccache);
|
||||
|
||||
DEBUG(3, ("Ticket in ccache[%s] expiration %s\n",
|
||||
krb5_cc_default_name(context),
|
||||
DEBUG(3, ("ads_cleanup_expired_creds: Ticket in ccache[%s:%s] expiration %s\n",
|
||||
cc_type, krb5_cc_get_name(context, ccache),
|
||||
http_timestring(credsp->times.endtime)));
|
||||
|
||||
/* we will probably need new tickets if the current ones
|
||||
@ -425,11 +426,11 @@ static BOOL ads_cleanup_expired_creds(krb5_context context,
|
||||
use memory ccaches, and a FILE one probably means that
|
||||
we're using creds obtained outside of our exectuable
|
||||
*/
|
||||
if (StrCaseCmp(krb5_cc_get_type(context, ccache), "FILE") == 0) {
|
||||
DEBUG(5, ("ads_cleanup_expired_creds: We do not remove creds from a FILE ccache\n"));
|
||||
if (strequal(cc_type, "KCM") || strequal(cc_type, "FILE")) {
|
||||
DEBUG(5, ("ads_cleanup_expired_creds: We do not remove creds from a %s ccache\n", cc_type));
|
||||
return False;
|
||||
}
|
||||
|
||||
|
||||
retval = krb5_cc_remove_cred(context, ccache, 0, credsp);
|
||||
if (retval) {
|
||||
DEBUG(1, ("ads_cleanup_expired_creds: krb5_cc_remove_cred failed, err %s\n",
|
||||
@ -467,7 +468,7 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context,
|
||||
/* obtain ticket & session key */
|
||||
ZERO_STRUCT(creds);
|
||||
if ((retval = krb5_copy_principal(context, server, &creds.server))) {
|
||||
DEBUG(1,("krb5_copy_principal failed (%s)\n",
|
||||
DEBUG(1,("ads_krb5_mk_req: krb5_copy_principal failed (%s)\n",
|
||||
error_message(retval)));
|
||||
goto cleanup_princ;
|
||||
}
|
||||
@ -502,8 +503,8 @@ static krb5_error_code ads_krb5_mk_req(krb5_context context,
|
||||
i++;
|
||||
}
|
||||
|
||||
DEBUG(10,("ads_krb5_mk_req: Ticket (%s) in ccache (%s) is valid until: (%s - %u)\n",
|
||||
principal, krb5_cc_default_name(context),
|
||||
DEBUG(10,("ads_krb5_mk_req: Ticket (%s) in ccache (%s:%s) is valid until: (%s - %u)\n",
|
||||
principal, krb5_cc_get_type(context, ccache), krb5_cc_get_name(context, ccache),
|
||||
http_timestring((unsigned)credsp->times.endtime),
|
||||
(unsigned)credsp->times.endtime));
|
||||
|
||||
@ -530,7 +531,8 @@ cleanup_princ:
|
||||
get a kerberos5 ticket for the given service
|
||||
*/
|
||||
int cli_krb5_get_ticket(const char *principal, time_t time_offset,
|
||||
DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts)
|
||||
DATA_BLOB *ticket, DATA_BLOB *session_key_krb5,
|
||||
uint32 extra_ap_opts, const char *ccname)
|
||||
{
|
||||
krb5_error_code retval;
|
||||
krb5_data packet;
|
||||
@ -544,7 +546,7 @@ int cli_krb5_get_ticket(const char *principal, time_t time_offset,
|
||||
ENCTYPE_DES_CBC_MD5,
|
||||
ENCTYPE_DES_CBC_CRC,
|
||||
ENCTYPE_NULL};
|
||||
|
||||
|
||||
initialize_krb5_error_table();
|
||||
retval = krb5_init_context(&context);
|
||||
if (retval) {
|
||||
@ -557,7 +559,8 @@ int cli_krb5_get_ticket(const char *principal, time_t time_offset,
|
||||
krb5_set_real_time(context, time(NULL) + time_offset, 0);
|
||||
}
|
||||
|
||||
if ((retval = krb5_cc_default(context, &ccdef))) {
|
||||
if ((retval = krb5_cc_resolve(context, ccname ?
|
||||
ccname : krb5_cc_default_name(context), &ccdef))) {
|
||||
DEBUG(1,("cli_krb5_get_ticket: krb5_cc_default failed (%s)\n",
|
||||
error_message(retval)));
|
||||
goto failed;
|
||||
@ -989,12 +992,156 @@ out:
|
||||
#else
|
||||
#error NO_SUITABLE_PRINCIPAL_COMPARE_FUNCTION
|
||||
#endif
|
||||
}
|
||||
|
||||
krb5_error_code smb_krb5_renew_ticket(const char *ccache_string, /* FILE:/tmp/krb5cc_0 */
|
||||
const char *client_string, /* gd@BER.SUSE.DE */
|
||||
const char *service_string, /* krbtgt/BER.SUSE.DE@BER.SUSE.DE */
|
||||
time_t *new_start_time)
|
||||
{
|
||||
krb5_error_code ret;
|
||||
krb5_context context = NULL;
|
||||
krb5_ccache ccache = NULL;
|
||||
krb5_principal client = NULL;
|
||||
|
||||
initialize_krb5_error_table();
|
||||
ret = krb5_init_context(&context);
|
||||
if (ret) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
if (!ccache_string) {
|
||||
ccache_string = krb5_cc_default_name(context);
|
||||
}
|
||||
|
||||
DEBUG(10,("smb_krb5_renew_ticket: using %s as ccache\n", ccache_string));
|
||||
|
||||
/* FIXME: we should not fall back to defaults */
|
||||
ret = krb5_cc_resolve(context, CONST_DISCARD(char *, ccache_string), &ccache);
|
||||
if (ret) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
#ifdef HAVE_KRB5_GET_RENEWED_CREDS /* MIT */
|
||||
{
|
||||
krb5_creds creds;
|
||||
|
||||
if (client_string) {
|
||||
ret = krb5_parse_name(context, client_string, &client);
|
||||
if (ret) {
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
ret = krb5_cc_get_principal(context, ccache, &client);
|
||||
if (ret) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
ret = krb5_get_renewed_creds(context, &creds, client, ccache, CONST_DISCARD(char *, service_string));
|
||||
if (ret) {
|
||||
DEBUG(10,("smb_krb5_renew_ticket: krb5_get_kdc_cred failed: %s\n", error_message(ret)));
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* hm, doesn't that create a new one if the old one wasn't there? - Guenther */
|
||||
ret = krb5_cc_initialize(context, ccache, client);
|
||||
if (ret) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = krb5_cc_store_cred(context, ccache, &creds);
|
||||
|
||||
if (new_start_time) {
|
||||
*new_start_time = (time_t) creds.times.renew_till;
|
||||
}
|
||||
|
||||
krb5_free_cred_contents(context, &creds);
|
||||
}
|
||||
#elif defined(HAVE_KRB5_GET_KDC_CRED) /* Heimdal */
|
||||
{
|
||||
krb5_kdc_flags flags;
|
||||
krb5_creds creds_in;
|
||||
krb5_realm *client_realm;
|
||||
krb5_creds *creds;
|
||||
|
||||
memset(&creds_in, 0, sizeof(creds_in));
|
||||
|
||||
if (client_string) {
|
||||
ret = krb5_parse_name(context, client_string, &creds_in.client);
|
||||
if (ret) {
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
ret = krb5_cc_get_principal(context, ccache, &creds_in.client);
|
||||
if (ret) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
if (service_string) {
|
||||
ret = krb5_parse_name(context, service_string, &creds_in.server);
|
||||
if (ret) {
|
||||
goto done;
|
||||
}
|
||||
} else {
|
||||
/* build tgt service by default */
|
||||
client_realm = krb5_princ_realm(context, client);
|
||||
ret = krb5_make_principal(context, &creds_in.server, *client_realm, KRB5_TGS_NAME, *client_realm, NULL);
|
||||
if (ret) {
|
||||
goto done;
|
||||
}
|
||||
}
|
||||
|
||||
flags.i = 0;
|
||||
flags.b.renewable = flags.b.renew = True;
|
||||
|
||||
ret = krb5_get_kdc_cred(context, ccache, flags, NULL, NULL, &creds_in, &creds);
|
||||
if (ret) {
|
||||
DEBUG(10,("smb_krb5_renew_ticket: krb5_get_kdc_cred failed: %s\n", error_message(ret)));
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* hm, doesn't that create a new one if the old one wasn't there? - Guenther */
|
||||
ret = krb5_cc_initialize(context, ccache, creds_in.client);
|
||||
if (ret) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
ret = krb5_cc_store_cred(context, ccache, creds);
|
||||
|
||||
if (new_start_time) {
|
||||
*new_start_time = (time_t) creds->times.renew_till;
|
||||
}
|
||||
|
||||
krb5_free_cred_contents(context, &creds_in);
|
||||
krb5_free_creds(context, creds);
|
||||
}
|
||||
#else
|
||||
#error No suitable krb5 ticket renew function available
|
||||
#endif
|
||||
|
||||
|
||||
done:
|
||||
if (client) {
|
||||
krb5_free_principal(context, client);
|
||||
}
|
||||
if (context) {
|
||||
krb5_free_context(context);
|
||||
}
|
||||
if (ccache) {
|
||||
krb5_cc_close(context, ccache);
|
||||
}
|
||||
|
||||
return ret;
|
||||
|
||||
}
|
||||
|
||||
#else /* HAVE_KRB5 */
|
||||
/* this saves a few linking headaches */
|
||||
int cli_krb5_get_ticket(const char *principal, time_t time_offset,
|
||||
DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts)
|
||||
DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts,
|
||||
const char *ccname)
|
||||
{
|
||||
DEBUG(0,("NO KERBEROS SUPPORT\n"));
|
||||
return 1;
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
@ -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
|
||||
|
@ -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)) {
|
||||
|
167
source/libsmb/gpo.c
Normal file
167
source/libsmb/gpo.c
Normal file
@ -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
|
||||
*/
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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;\
|
||||
};\
|
||||
};
|
||||
|
@ -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;
|
||||
}
|
||||
|
@ -199,7 +199,7 @@ static BOOL wbinfo_get_userdomgroups(const char *user_sid)
|
||||
return False;
|
||||
|
||||
if (response.data.num_entries != 0)
|
||||
d_printf("%s", (char *)response.extra_data);
|
||||
printf("%s", (char *)response.extra_data);
|
||||
|
||||
SAFE_FREE(response.extra_data);
|
||||
|
||||
@ -260,15 +260,19 @@ static BOOL wbinfo_wins_byip(char *ip)
|
||||
|
||||
/* List trusted domains */
|
||||
|
||||
static BOOL wbinfo_list_domains(void)
|
||||
static BOOL wbinfo_list_domains(BOOL list_all_domains)
|
||||
{
|
||||
struct winbindd_request request;
|
||||
struct winbindd_response response;
|
||||
|
||||
ZERO_STRUCT(request);
|
||||
ZERO_STRUCT(response);
|
||||
|
||||
/* Send request */
|
||||
|
||||
if (winbindd_request_response(WINBINDD_LIST_TRUSTDOM, NULL, &response) !=
|
||||
request.data.list_all_domains = list_all_domains;
|
||||
|
||||
if (winbindd_request_response(WINBINDD_LIST_TRUSTDOM, &request, &response) !=
|
||||
NSS_STATUS_SUCCESS)
|
||||
return False;
|
||||
|
||||
@ -510,14 +514,26 @@ static BOOL wbinfo_sid_to_gid(char *sid)
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL wbinfo_allocate_rid(void)
|
||||
static BOOL wbinfo_allocate_uid(void)
|
||||
{
|
||||
uint32 rid;
|
||||
uid_t uid;
|
||||
|
||||
if (!winbind_allocate_rid(&rid))
|
||||
if (!winbind_allocate_uid(&uid))
|
||||
return False;
|
||||
|
||||
d_printf("New rid: %d\n", rid);
|
||||
d_printf("New uid: %d\n", uid);
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
static BOOL wbinfo_allocate_gid(void)
|
||||
{
|
||||
gid_t gid;
|
||||
|
||||
if (!winbind_allocate_gid(&gid))
|
||||
return False;
|
||||
|
||||
d_printf("New gid: %d\n", gid);
|
||||
|
||||
return True;
|
||||
}
|
||||
@ -577,6 +593,67 @@ static BOOL wbinfo_lookupname(char *name)
|
||||
|
||||
/* Authenticate a user with a plaintext password */
|
||||
|
||||
static BOOL wbinfo_auth_krb5(char *username, const char *cctype, uint32 flags)
|
||||
{
|
||||
struct winbindd_request request;
|
||||
struct winbindd_response response;
|
||||
NSS_STATUS result;
|
||||
char *p;
|
||||
|
||||
/* Send off request */
|
||||
|
||||
ZERO_STRUCT(request);
|
||||
ZERO_STRUCT(response);
|
||||
|
||||
p = strchr(username, '%');
|
||||
|
||||
if (p) {
|
||||
*p = 0;
|
||||
fstrcpy(request.data.auth.user, username);
|
||||
fstrcpy(request.data.auth.pass, p + 1);
|
||||
*p = '%';
|
||||
} else
|
||||
fstrcpy(request.data.auth.user, username);
|
||||
|
||||
request.flags = flags;
|
||||
|
||||
fstrcpy(request.data.auth.krb5_cc_type, cctype);
|
||||
|
||||
request.data.auth.uid = geteuid();
|
||||
|
||||
result = winbindd_request_response(WINBINDD_PAM_AUTH, &request, &response);
|
||||
|
||||
/* Display response */
|
||||
|
||||
d_printf("plaintext kerberos password authentication for [%s] %s (requesting cctype: %s)\n",
|
||||
username, (result == NSS_STATUS_SUCCESS) ? "succeeded" : "failed", cctype);
|
||||
|
||||
if (response.data.auth.nt_status)
|
||||
d_fprintf(stderr, "error code was %s (0x%x)\nerror messsage was: %s\n",
|
||||
response.data.auth.nt_status_string,
|
||||
response.data.auth.nt_status,
|
||||
response.data.auth.error_string);
|
||||
|
||||
if (result == NSS_STATUS_SUCCESS) {
|
||||
|
||||
if (request.flags & WBFLAG_PAM_INFO3_TEXT) {
|
||||
if (response.data.auth.info3.user_flgs & LOGON_CACHED_ACCOUNT) {
|
||||
d_printf("user_flgs: LOGON_CACHED_ACCOUNT\n");
|
||||
}
|
||||
}
|
||||
|
||||
if (response.data.auth.krb5ccname[0] != '\0') {
|
||||
d_printf("credentials were put in: %s\n", response.data.auth.krb5ccname);
|
||||
} else {
|
||||
d_printf("no credentials cached\n");
|
||||
}
|
||||
}
|
||||
|
||||
return result == NSS_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
/* Authenticate a user with a plaintext password */
|
||||
|
||||
static BOOL wbinfo_auth(char *username)
|
||||
{
|
||||
struct winbindd_request request;
|
||||
@ -968,7 +1045,10 @@ enum {
|
||||
OPT_GETDCNAME,
|
||||
OPT_USERDOMGROUPS,
|
||||
OPT_USERSIDS,
|
||||
OPT_SEPARATOR
|
||||
OPT_ALLOCATE_UID,
|
||||
OPT_ALLOCATE_GID,
|
||||
OPT_SEPARATOR,
|
||||
OPT_LIST_ALL_DOMAINS
|
||||
};
|
||||
|
||||
int main(int argc, char **argv)
|
||||
@ -997,9 +1077,13 @@ int main(int argc, char **argv)
|
||||
{ "gid-to-sid", 'G', POPT_ARG_INT, &int_arg, 'G', "Converts gid to sid", "GID" },
|
||||
{ "sid-to-uid", 'S', POPT_ARG_STRING, &string_arg, 'S', "Converts sid to uid", "SID" },
|
||||
{ "sid-to-gid", 'Y', POPT_ARG_STRING, &string_arg, 'Y', "Converts sid to gid", "SID" },
|
||||
{ "allocate-rid", 'A', POPT_ARG_NONE, 0, 'A', "Get a new RID out of idmap" },
|
||||
{ "allocate-uid", 0, POPT_ARG_NONE, 0, OPT_ALLOCATE_UID,
|
||||
"Get a new UID out of idmap" },
|
||||
{ "allocate-gid", 0, POPT_ARG_NONE, 0, OPT_ALLOCATE_GID,
|
||||
"Get a new GID out of idmap" },
|
||||
{ "check-secret", 't', POPT_ARG_NONE, 0, 't', "Check shared secret" },
|
||||
{ "trusted-domains", 'm', POPT_ARG_NONE, 0, 'm', "List trusted domains" },
|
||||
{ "all-domains", 0, POPT_ARG_NONE, 0, OPT_LIST_ALL_DOMAINS, "List all domains (trusted and own domain)" },
|
||||
{ "sequence", 0, POPT_ARG_NONE, 0, OPT_SEQUENCE, "Show sequence numbers of all domains" },
|
||||
{ "domain-info", 'D', POPT_ARG_STRING, &string_arg, 'D', "Show most of the info we have about the domain" },
|
||||
{ "user-groups", 'r', POPT_ARG_STRING, &string_arg, 'r', "Get user groups", "USER" },
|
||||
@ -1015,6 +1099,11 @@ int main(int argc, char **argv)
|
||||
{ "domain", 0, POPT_ARG_STRING, &opt_domain_name, OPT_DOMAIN_NAME, "Define to the domain to restrict operation", "domain" },
|
||||
#ifdef WITH_FAKE_KASERVER
|
||||
{ "klog", 'k', POPT_ARG_STRING, &string_arg, 'k', "set an AFS token from winbind", "user%password" },
|
||||
#endif
|
||||
#ifdef HAVE_KRB5
|
||||
{ "krb5auth", 'K', POPT_ARG_STRING, &string_arg, 'K', "authenticate user using Kerberos", "user%password" },
|
||||
/* destroys wbinfo --help output */
|
||||
/* "user%password,DOM\\user%password,user@EXAMPLE.COM,EXAMPLE.COM\\user%password" }, */
|
||||
#endif
|
||||
{ "separator", 0, POPT_ARG_NONE, 0, OPT_SEPARATOR, "Get the active winbind separator", NULL },
|
||||
POPT_COMMON_VERSION
|
||||
@ -1120,9 +1209,15 @@ int main(int argc, char **argv)
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case 'A':
|
||||
if (!wbinfo_allocate_rid()) {
|
||||
d_fprintf(stderr, "Could not allocate a RID\n");
|
||||
case OPT_ALLOCATE_UID:
|
||||
if (!wbinfo_allocate_uid()) {
|
||||
d_fprintf(stderr, "Could not allocate a uid\n");
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
case OPT_ALLOCATE_GID:
|
||||
if (!wbinfo_allocate_gid()) {
|
||||
d_fprintf(stderr, "Could not allocate a gid\n");
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
@ -1133,7 +1228,7 @@ int main(int argc, char **argv)
|
||||
}
|
||||
break;
|
||||
case 'm':
|
||||
if (!wbinfo_list_domains()) {
|
||||
if (!wbinfo_list_domains(False)) {
|
||||
d_fprintf(stderr, "Could not list trusted domains\n");
|
||||
goto done;
|
||||
}
|
||||
@ -1190,6 +1285,38 @@ int main(int argc, char **argv)
|
||||
goto done;
|
||||
break;
|
||||
}
|
||||
case 'K': {
|
||||
BOOL got_error = False;
|
||||
uint32 flags = WBFLAG_PAM_KRB5 |
|
||||
WBFLAG_PAM_CACHED_LOGIN |
|
||||
WBFLAG_PAM_FALLBACK_AFTER_KRB5 |
|
||||
WBFLAG_PAM_INFO3_TEXT;
|
||||
fstring tok;
|
||||
int i;
|
||||
const char *arg[] = { string_arg, NULL };
|
||||
const char *cctypes[] = { "FILE",
|
||||
"KCM",
|
||||
"KCM:0",
|
||||
"Garbage",
|
||||
NULL,
|
||||
"0"};
|
||||
|
||||
while (next_token(arg, tok, LIST_SEP, sizeof(tok))) {
|
||||
|
||||
for (i=0; i < ARRAY_SIZE(cctypes); i++) {
|
||||
if (!wbinfo_auth_krb5(tok, cctypes[i], flags)) {
|
||||
d_fprintf(stderr, "Could not authenticate user [%s] with "
|
||||
"Kerberos (ccache: %s)\n", tok, cctypes[i]);
|
||||
got_error = True;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (got_error)
|
||||
goto done;
|
||||
|
||||
break;
|
||||
}
|
||||
case 'k':
|
||||
if (!wbinfo_klog(string_arg)) {
|
||||
d_fprintf(stderr, "Could not klog user\n");
|
||||
@ -1198,7 +1325,7 @@ int main(int argc, char **argv)
|
||||
break;
|
||||
case 'p':
|
||||
if (!wbinfo_ping()) {
|
||||
d_fprintf(stderr, "Could not ping winbindd!\n");
|
||||
d_fprintf(stderr, "could not ping winbindd!\n");
|
||||
goto done;
|
||||
}
|
||||
break;
|
||||
@ -1223,6 +1350,10 @@ int main(int argc, char **argv)
|
||||
d_printf("%c\n", sep);
|
||||
break;
|
||||
}
|
||||
case OPT_LIST_ALL_DOMAINS:
|
||||
if (!wbinfo_list_domains(True)) {
|
||||
goto done;
|
||||
}
|
||||
/* generic configuration options */
|
||||
case OPT_DOMAIN_NAME:
|
||||
break;
|
||||
|
@ -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 */
|
||||
|
@ -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 */
|
||||
|
@ -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,
|
||||
};
|
||||
|
||||
|
@ -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;
|
||||
@ -187,6 +170,22 @@ static uint32 centry_uint32(struct cache_entry *centry)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
pull a uint16 from a cache entry
|
||||
*/
|
||||
static uint16 centry_uint16(struct cache_entry *centry)
|
||||
{
|
||||
uint16 ret;
|
||||
if (centry->len - centry->ofs < 2) {
|
||||
DEBUG(0,("centry corruption? needed 2 bytes, have %d\n",
|
||||
centry->len - centry->ofs));
|
||||
smb_panic("centry_uint16");
|
||||
}
|
||||
ret = CVAL(centry->data, centry->ofs);
|
||||
centry->ofs += 2;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
pull a uint8 from a cache entry
|
||||
*/
|
||||
@ -203,6 +202,40 @@ static uint8 centry_uint8(struct cache_entry *centry)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
pull a NTTIME from a cache entry
|
||||
*/
|
||||
static NTTIME centry_nttime(struct cache_entry *centry)
|
||||
{
|
||||
NTTIME ret;
|
||||
if (centry->len - centry->ofs < 8) {
|
||||
DEBUG(0,("centry corruption? needed 8 bytes, have %d\n",
|
||||
centry->len - centry->ofs));
|
||||
smb_panic("centry_nttime");
|
||||
}
|
||||
ret.low = IVAL(centry->data, centry->ofs);
|
||||
centry->ofs += 4;
|
||||
ret.high = IVAL(centry->data, centry->ofs);
|
||||
centry->ofs += 4;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
pull a time_t from a cache entry
|
||||
*/
|
||||
static time_t centry_time(struct cache_entry *centry)
|
||||
{
|
||||
time_t ret;
|
||||
if (centry->len - centry->ofs < sizeof(time_t)) {
|
||||
DEBUG(0,("centry corruption? needed %d bytes, have %d\n",
|
||||
sizeof(time_t), centry->len - centry->ofs));
|
||||
smb_panic("centry_time");
|
||||
}
|
||||
ret = IVAL(centry->data, centry->ofs); /* FIXME: correct ? */
|
||||
centry->ofs += sizeof(time_t);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* pull a string from a cache entry, using the supplied
|
||||
talloc context
|
||||
*/
|
||||
@ -403,10 +436,28 @@ done:
|
||||
*/
|
||||
static BOOL centry_expired(struct winbindd_domain *domain, const char *keystr, struct cache_entry *centry)
|
||||
{
|
||||
/* If we've been told to be offline - stay in that state... */
|
||||
if (lp_winbind_offline_logon() && global_winbindd_offline_state) {
|
||||
DEBUG(10,("centry_expired: Key %s for domain %s valid as winbindd is globally offline.\n",
|
||||
keystr, domain->name ));
|
||||
return False;
|
||||
}
|
||||
|
||||
/* when the domain is offline and we havent checked in the last 30
|
||||
* seconds if it has become online again, return the cached entry.
|
||||
* This deals with transient offline states... */
|
||||
|
||||
if (!domain->online &&
|
||||
!NT_STATUS_IS_OK(check_negative_conn_cache(domain->name, domain->dcname))) {
|
||||
DEBUG(10,("centry_expired: Key %s for domain %s valid as domain is offline.\n",
|
||||
keystr, domain->name ));
|
||||
return False;
|
||||
}
|
||||
|
||||
/* if the server is OK and our cache entry came from when it was down then
|
||||
the entry is invalid */
|
||||
if (domain->sequence_number != DOM_SEQUENCE_NONE &&
|
||||
centry->sequence_number == DOM_SEQUENCE_NONE) {
|
||||
if ((domain->sequence_number != DOM_SEQUENCE_NONE) &&
|
||||
(centry->sequence_number == DOM_SEQUENCE_NONE)) {
|
||||
DEBUG(10,("centry_expired: Key %s for domain %s invalid sequence.\n",
|
||||
keystr, domain->name ));
|
||||
return True;
|
||||
@ -428,6 +479,38 @@ static BOOL centry_expired(struct winbindd_domain *domain, const char *keystr, s
|
||||
return True;
|
||||
}
|
||||
|
||||
static struct cache_entry *wcache_fetch_raw(char *kstr)
|
||||
{
|
||||
TDB_DATA data;
|
||||
struct cache_entry *centry;
|
||||
TDB_DATA key;
|
||||
|
||||
key.dptr = kstr;
|
||||
key.dsize = strlen(kstr);
|
||||
data = tdb_fetch(wcache->tdb, key);
|
||||
if (!data.dptr) {
|
||||
/* a cache miss */
|
||||
return NULL;
|
||||
}
|
||||
|
||||
centry = SMB_XMALLOC_P(struct cache_entry);
|
||||
centry->data = (unsigned char *)data.dptr;
|
||||
centry->len = data.dsize;
|
||||
centry->ofs = 0;
|
||||
|
||||
if (centry->len < 8) {
|
||||
/* huh? corrupt cache? */
|
||||
DEBUG(10,("wcache_fetch_raw: Corrupt cache for key %s (len < 8) ?\n", kstr));
|
||||
centry_free(centry);
|
||||
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
|
||||
@ -441,42 +524,20 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
|
||||
{
|
||||
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 */
|
||||
|
||||
centry = wcache_fetch_raw(kstr);
|
||||
if (centry == NULL) {
|
||||
free(kstr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
centry = SMB_XMALLOC_P(struct cache_entry);
|
||||
centry->data = (unsigned char *)data.dptr;
|
||||
centry->len = data.dsize;
|
||||
centry->ofs = 0;
|
||||
|
||||
if (centry->len < 8) {
|
||||
/* huh? corrupt cache? */
|
||||
DEBUG(10,("wcache_fetch: Corrupt cache for key %s domain %s (len < 8) ?\n",
|
||||
kstr, domain->name ));
|
||||
centry_free(centry);
|
||||
free(kstr);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
centry->status = NT_STATUS(centry_uint32(centry));
|
||||
centry->sequence_number = centry_uint32(centry);
|
||||
|
||||
if (centry_expired(domain, kstr, centry)) {
|
||||
|
||||
DEBUG(10,("wcache_fetch: entry %s expired for domain %s\n",
|
||||
@ -521,6 +582,16 @@ static void centry_put_uint32(struct cache_entry *centry, uint32 v)
|
||||
centry->ofs += 4;
|
||||
}
|
||||
|
||||
/*
|
||||
push a uint16 into a centry
|
||||
*/
|
||||
static void centry_put_uint16(struct cache_entry *centry, uint16 v)
|
||||
{
|
||||
centry_expand(centry, 2);
|
||||
SIVAL(centry->data, centry->ofs, v);
|
||||
centry->ofs += 2;
|
||||
}
|
||||
|
||||
/*
|
||||
push a uint8 into a centry
|
||||
*/
|
||||
@ -562,6 +633,28 @@ static void centry_put_sid(struct cache_entry *centry, const DOM_SID *sid)
|
||||
centry_put_string(centry, sid_to_string(sid_string, sid));
|
||||
}
|
||||
|
||||
/*
|
||||
push a NTTIME into a centry
|
||||
*/
|
||||
static void centry_put_nttime(struct cache_entry *centry, NTTIME nt)
|
||||
{
|
||||
centry_expand(centry, 8);
|
||||
SIVAL(centry->data, centry->ofs, nt.low);
|
||||
centry->ofs += 4;
|
||||
SIVAL(centry->data, centry->ofs, nt.high);
|
||||
centry->ofs += 4;
|
||||
}
|
||||
|
||||
/*
|
||||
push a time_t into a centry
|
||||
*/
|
||||
static void centry_put_time(struct cache_entry *centry, time_t t)
|
||||
{
|
||||
centry_expand(centry, sizeof(time_t));
|
||||
SIVAL(centry->data, centry->ofs, t); /* FIXME: is this correct ?? */
|
||||
centry->ofs += sizeof(time_t);
|
||||
}
|
||||
|
||||
/*
|
||||
start a centry for output. When finished, call centry_end()
|
||||
*/
|
||||
@ -666,6 +759,129 @@ static void wcache_save_user(struct winbindd_domain *domain, NTSTATUS status, WI
|
||||
centry_free(centry);
|
||||
}
|
||||
|
||||
static void wcache_save_lockout_policy(struct winbindd_domain *domain, NTSTATUS status, SAM_UNK_INFO_12 *lockout_policy)
|
||||
{
|
||||
struct cache_entry *centry;
|
||||
|
||||
centry = centry_start(domain, status);
|
||||
if (!centry)
|
||||
return;
|
||||
|
||||
centry_put_nttime(centry, lockout_policy->duration);
|
||||
centry_put_nttime(centry, lockout_policy->reset_count);
|
||||
centry_put_uint16(centry, lockout_policy->bad_attempt_lockout);
|
||||
|
||||
centry_end(centry, "LOC_POL/%s", domain->name);
|
||||
|
||||
DEBUG(10,("wcache_save_lockout_policy: %s\n", domain->name));
|
||||
|
||||
centry_free(centry);
|
||||
}
|
||||
|
||||
static void wcache_save_password_policy(struct winbindd_domain *domain, NTSTATUS status, SAM_UNK_INFO_1 *password_policy)
|
||||
{
|
||||
struct cache_entry *centry;
|
||||
|
||||
centry = centry_start(domain, status);
|
||||
if (!centry)
|
||||
return;
|
||||
|
||||
centry_put_uint16(centry, password_policy->min_length_password);
|
||||
centry_put_uint16(centry, password_policy->password_history);
|
||||
centry_put_uint32(centry, password_policy->password_properties);
|
||||
centry_put_nttime(centry, password_policy->expire);
|
||||
centry_put_nttime(centry, password_policy->min_passwordage);
|
||||
|
||||
centry_end(centry, "PWD_POL/%s", domain->name);
|
||||
|
||||
DEBUG(10,("wcache_save_password_policy: %s\n", domain->name));
|
||||
|
||||
centry_free(centry);
|
||||
}
|
||||
|
||||
NTSTATUS wcache_cached_creds_exist(struct winbindd_domain *domain, const DOM_SID *sid)
|
||||
{
|
||||
struct winbind_cache *cache = get_cache(domain);
|
||||
TDB_DATA data;
|
||||
fstring key_str;
|
||||
|
||||
if (!cache->tdb) {
|
||||
return NT_STATUS_INTERNAL_DB_ERROR;
|
||||
}
|
||||
|
||||
fstr_sprintf(key_str, "CRED/%s", sid_string_static(sid));
|
||||
|
||||
data = tdb_fetch(cache->tdb, make_tdb_data(key_str, strlen(key_str)));
|
||||
if (!data.dptr) {
|
||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/* Lookup creds for a SID */
|
||||
NTSTATUS wcache_get_creds(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const DOM_SID *sid,
|
||||
const uint8 **cached_nt_pass)
|
||||
{
|
||||
struct winbind_cache *cache = get_cache(domain);
|
||||
struct cache_entry *centry = NULL;
|
||||
NTSTATUS status;
|
||||
time_t t;
|
||||
|
||||
if (!cache->tdb) {
|
||||
return NT_STATUS_INTERNAL_DB_ERROR;
|
||||
}
|
||||
|
||||
centry = wcache_fetch(cache, domain, "CRED/%s", sid_string_static(sid));
|
||||
|
||||
if (!centry) {
|
||||
DEBUG(10,("wcache_get_creds: entry for [CRED/%s] not found\n",
|
||||
sid_string_static(sid)));
|
||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
t = centry_time(centry);
|
||||
*cached_nt_pass = (const uint8 *)centry_string(centry, mem_ctx);
|
||||
|
||||
dump_data(10, (const char *)cached_nt_pass, NT_HASH_LEN);
|
||||
status = centry->status;
|
||||
|
||||
DEBUG(10,("wcache_get_creds: [Cached] - cached creds for user %s status %s\n",
|
||||
sid_string_static(sid), get_friendly_nt_error_msg(status) ));
|
||||
|
||||
centry_free(centry);
|
||||
return status;
|
||||
}
|
||||
|
||||
NTSTATUS wcache_save_creds(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
const DOM_SID *sid,
|
||||
const uint8 nt_pass[NT_HASH_LEN])
|
||||
{
|
||||
struct cache_entry *centry;
|
||||
fstring sid_string;
|
||||
NTSTATUS status = NT_STATUS_OK; /* ??? */
|
||||
|
||||
centry = centry_start(domain, status);
|
||||
if (!centry) {
|
||||
return NT_STATUS_INTERNAL_DB_ERROR;
|
||||
}
|
||||
|
||||
dump_data(100, (const char *)nt_pass, NT_HASH_LEN);
|
||||
|
||||
centry_put_time(centry, time(NULL));
|
||||
centry_put_string(centry, (const char *)nt_pass);
|
||||
centry_end(centry, "CRED/%s", sid_to_string(sid_string, sid));
|
||||
|
||||
DEBUG(10,("wcache_save_creds: %s\n", sid_string));
|
||||
|
||||
centry_free(centry);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
|
||||
/* Query display info. This is the basic user list fn */
|
||||
static NTSTATUS query_user_list(struct winbindd_domain *domain,
|
||||
@ -991,7 +1207,9 @@ do_query:
|
||||
status = domain->backend->name_to_sid(domain, mem_ctx, domain_name, name, sid, type);
|
||||
|
||||
/* and save it */
|
||||
wcache_save_name_to_sid(domain, status, domain_name, name, sid, *type);
|
||||
if (domain->online || !is_null_sid(sid)) {
|
||||
wcache_save_name_to_sid(domain, status, domain_name, name, sid, *type);
|
||||
}
|
||||
|
||||
if (NT_STATUS_IS_OK(status)) {
|
||||
strupper_m(CONST_DISCARD(char *,domain_name));
|
||||
@ -1390,7 +1608,9 @@ static NTSTATUS sequence_number(struct winbindd_domain *domain, uint32 *seq)
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
/* enumerate trusted domains */
|
||||
/* enumerate trusted domains
|
||||
* (we need to have the list of trustdoms in the cache when we go offline) -
|
||||
* Guenther */
|
||||
static NTSTATUS trusted_domains(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
uint32 *num_domains,
|
||||
@ -1398,15 +1618,183 @@ 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;
|
||||
|
||||
/* we don't cache this call */
|
||||
return domain->backend->trusted_domains(domain, mem_ctx, num_domains,
|
||||
names, alt_names, dom_sids);
|
||||
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);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Invalidate cached user and group lists coherently */
|
||||
|
||||
@ -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
|
||||
};
|
||||
|
@ -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)
|
||||
{
|
||||
|
270
source/nsswitch/winbindd_cred_cache.c
Normal file
270
source/nsswitch/winbindd_cred_cache.c
Normal file
@ -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;
|
||||
}
|
162
source/nsswitch/winbindd_creds.c
Normal file
162
source/nsswitch/winbindd_creds.c
Normal file
@ -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);
|
||||
}
|
||||
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
}
|
||||
|
||||
|
@ -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 */
|
||||
|
@ -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
|
||||
|
File diff suppressed because it is too large
Load Diff
@ -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));
|
||||
|
||||
if (NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_MORE_ENTRIES)) {
|
||||
return NT_STATUS_OK;
|
||||
nt_status = secrets_trusted_domains(mem_ctx, num_domains,
|
||||
&domains);
|
||||
if (!NT_STATUS_IS_OK(nt_status)) {
|
||||
return nt_status;
|
||||
}
|
||||
return nt_status;
|
||||
|
||||
*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;
|
||||
}
|
||||
|
||||
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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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,
|
||||
};
|
||||
|
@ -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;
|
||||
union unid_t id;
|
||||
|
||||
/* 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);
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
|
@ -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;
|
||||
|
@ -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.
|
||||
*****************************************************************************/
|
||||
|
@ -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';
|
||||
|
@ -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)",
|
||||
|
@ -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()),
|
||||
|
@ -54,6 +54,7 @@
|
||||
#include "includes.h"
|
||||
|
||||
BOOL in_client = False; /* Not in the client by default */
|
||||
BOOL in_server = False; /* Not in the server by default */
|
||||
BOOL bLoaded = False;
|
||||
|
||||
extern userdom_struct current_user_info;
|
||||
@ -76,6 +77,9 @@ extern enum protocol_types Protocol;
|
||||
#define LP_SNUM_OK(i) (((i) >= 0) && ((i) < iNumServices) && (ServicePtrs != NULL) && ServicePtrs[(i)]->valid)
|
||||
#define VALID(i) (ServicePtrs != NULL && ServicePtrs[i]->valid)
|
||||
|
||||
#define USERSHARE_VALID 1
|
||||
#define USERSHARE_PENDING_DELETE 2
|
||||
|
||||
int keepalive = DEFAULT_KEEPALIVE;
|
||||
BOOL use_getwd_cache = True;
|
||||
|
||||
@ -94,8 +98,7 @@ struct _param_opt_struct {
|
||||
/*
|
||||
* This structure describes global (ie., server-wide) parameters.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
char *smb_ports;
|
||||
char *dos_charset;
|
||||
char *unix_charset;
|
||||
@ -167,7 +170,6 @@ typedef struct
|
||||
BOOL bUtmp;
|
||||
char *szIdmapUID;
|
||||
char *szIdmapGID;
|
||||
BOOL bEnableRidAlgorithm;
|
||||
BOOL bPassdbExpandExplicit;
|
||||
int AlgorithmicRidBase;
|
||||
char *szTemplateHomedir;
|
||||
@ -178,6 +180,8 @@ typedef struct
|
||||
BOOL bWinbindUseDefaultDomain;
|
||||
BOOL bWinbindTrustedDomainsOnly;
|
||||
BOOL bWinbindNestedGroups;
|
||||
BOOL bWinbindRefreshTickets;
|
||||
BOOL bWinbindOfflineLogon;
|
||||
char **szIdmapBackend;
|
||||
char *szAddShareCommand;
|
||||
char *szChangeShareCommand;
|
||||
@ -186,6 +190,10 @@ typedef struct
|
||||
char *szGuestaccount;
|
||||
char *szManglingMethod;
|
||||
char **szServicesList;
|
||||
char *szUsersharePath;
|
||||
char *szUsershareTemplateShare;
|
||||
char **szUsersharePrefixAllowList;
|
||||
char **szUsersharePrefixDenyList;
|
||||
int mangle_prefix;
|
||||
int max_log_size;
|
||||
char *szLogLevel;
|
||||
@ -299,24 +307,27 @@ typedef struct
|
||||
BOOL bDeferSharingViolations;
|
||||
BOOL bEnablePrivileges;
|
||||
BOOL bASUSupport;
|
||||
BOOL bUsershareOwnerOnly;
|
||||
int restrict_anonymous;
|
||||
int name_cache_timeout;
|
||||
int client_signing;
|
||||
int server_signing;
|
||||
int iUsershareMaxShares;
|
||||
|
||||
BOOL bResetOnZeroVC;
|
||||
param_opt_struct *param_opt;
|
||||
}
|
||||
global;
|
||||
} global;
|
||||
|
||||
static global Globals;
|
||||
|
||||
/*
|
||||
* This structure describes a single service.
|
||||
*/
|
||||
typedef struct
|
||||
{
|
||||
typedef struct {
|
||||
BOOL valid;
|
||||
BOOL autoloaded;
|
||||
int usershare;
|
||||
time_t usershare_last_mod;
|
||||
char *szService;
|
||||
char *szPath;
|
||||
char *szUsername;
|
||||
@ -445,14 +456,15 @@ typedef struct
|
||||
param_opt_struct *param_opt;
|
||||
|
||||
char dummy[3]; /* for alignment */
|
||||
}
|
||||
service;
|
||||
} service;
|
||||
|
||||
|
||||
/* This is a default service used to prime a services structure */
|
||||
static service sDefault = {
|
||||
True, /* valid */
|
||||
False, /* not autoloaded */
|
||||
0, /* not a usershare */
|
||||
(time_t)0, /* No last mod time */
|
||||
NULL, /* szService */
|
||||
NULL, /* szPath */
|
||||
NULL, /* szUsername */
|
||||
@ -1214,6 +1226,12 @@ static struct parm_struct parm_table[] = {
|
||||
{"root preexec close", P_BOOL, P_LOCAL, &sDefault.bRootpreexecClose, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
|
||||
{"root postexec", P_STRING, P_LOCAL, &sDefault.szRootPostExec, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
|
||||
{"available", P_BOOL, P_LOCAL, &sDefault.bAvailable, NULL, NULL, FLAG_BASIC | FLAG_ADVANCED | FLAG_SHARE | FLAG_PRINT},
|
||||
{"usershare max shares", P_INTEGER, P_GLOBAL, &Globals.iUsershareMaxShares, NULL, NULL, FLAG_ADVANCED},
|
||||
{"usershare owner only", P_BOOL, P_GLOBAL, &Globals.bUsershareOwnerOnly, NULL, NULL, FLAG_ADVANCED},
|
||||
{"usershare path", P_STRING, P_GLOBAL, &Globals.szUsersharePath, NULL, NULL, FLAG_ADVANCED},
|
||||
{"usershare prefix allow list", P_LIST, P_GLOBAL, &Globals.szUsersharePrefixAllowList, NULL, NULL, FLAG_ADVANCED},
|
||||
{"usershare prefix deny list", P_LIST, P_GLOBAL, &Globals.szUsersharePrefixDenyList, NULL, NULL, FLAG_ADVANCED},
|
||||
{"usershare template share", P_STRING, P_GLOBAL, &Globals.szUsershareTemplateShare, NULL, NULL, FLAG_ADVANCED},
|
||||
{"volume", P_STRING, P_LOCAL, &sDefault.volume, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE },
|
||||
{"fstype", P_STRING, P_LOCAL, &sDefault.fstype, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
|
||||
{"set directory", P_BOOLREV, P_LOCAL, &sDefault.bNo_set_dir, NULL, NULL, FLAG_ADVANCED | FLAG_SHARE},
|
||||
@ -1242,7 +1260,6 @@ static struct parm_struct parm_table[] = {
|
||||
|
||||
{N_("Winbind options"), P_SEP, P_SEPARATOR},
|
||||
|
||||
{"enable rid algorithm", P_BOOL, P_GLOBAL, &Globals.bEnableRidAlgorithm, NULL, NULL, FLAG_DEPRECATED},
|
||||
{"passdb expand explicit", P_BOOL, P_GLOBAL, &Globals.bPassdbExpandExplicit, NULL, NULL, FLAG_ADVANCED},
|
||||
{"idmap backend", P_LIST, P_GLOBAL, &Globals.szIdmapBackend, NULL, NULL, FLAG_ADVANCED},
|
||||
{"idmap uid", P_STRING, P_GLOBAL, &Globals.szIdmapUID, handle_idmap_uid, NULL, FLAG_ADVANCED},
|
||||
@ -1260,6 +1277,8 @@ static struct parm_struct parm_table[] = {
|
||||
{"winbind nested groups", P_BOOL, P_GLOBAL, &Globals.bWinbindNestedGroups, NULL, NULL, FLAG_ADVANCED},
|
||||
{"winbind max idle children", P_INTEGER, P_GLOBAL, &Globals.winbind_max_idle_children, NULL, NULL, FLAG_ADVANCED},
|
||||
{"winbind nss info", P_LIST, P_GLOBAL, &Globals.szWinbindNssInfo, NULL, NULL, FLAG_ADVANCED},
|
||||
{"winbind refresh tickets", P_BOOL, P_GLOBAL, &Globals.bWinbindRefreshTickets, NULL, NULL, FLAG_ADVANCED},
|
||||
{"winbind offline logon", P_BOOL, P_GLOBAL, &Globals.bWinbindOfflineLogon, NULL, NULL, FLAG_ADVANCED},
|
||||
|
||||
{NULL, P_BOOL, P_NONE, NULL, NULL, NULL, 0}
|
||||
};
|
||||
@ -1612,8 +1631,9 @@ static void init_globals(BOOL first_time_only)
|
||||
Globals.bWinbindNestedGroups = False;
|
||||
Globals.winbind_max_idle_children = 3;
|
||||
Globals.szWinbindNssInfo = str_list_make("template", NULL);
|
||||
Globals.bWinbindRefreshTickets = False;
|
||||
Globals.bWinbindOfflineLogon = False;
|
||||
|
||||
Globals.bEnableRidAlgorithm = True;
|
||||
Globals.bPassdbExpandExplicit = True;
|
||||
|
||||
Globals.name_cache_timeout = 660; /* In seconds */
|
||||
@ -1636,6 +1656,15 @@ static void init_globals(BOOL first_time_only)
|
||||
Globals.bASUSupport = True;
|
||||
|
||||
Globals.szServicesList = str_list_make( "Spooler NETLOGON", NULL );
|
||||
|
||||
/* User defined shares. */
|
||||
pstrcpy(s, dyn_LOCKDIR);
|
||||
pstrcat(s, "/usershares");
|
||||
string_set(&Globals.szUsersharePath, s);
|
||||
string_set(&Globals.szUsershareTemplateShare, "");
|
||||
Globals.iUsershareMaxShares = 0;
|
||||
/* By default disallow sharing of directories not owned by the sharer. */
|
||||
Globals.bUsershareOwnerOnly = True;
|
||||
}
|
||||
|
||||
static TALLOC_CTX *lp_talloc;
|
||||
@ -1652,6 +1681,19 @@ void lp_talloc_free(void)
|
||||
lp_talloc = NULL;
|
||||
}
|
||||
|
||||
TALLOC_CTX *tmp_talloc_ctx(void)
|
||||
{
|
||||
if (lp_talloc == NULL) {
|
||||
lp_talloc = talloc_init(NULL);
|
||||
}
|
||||
|
||||
if (lp_talloc == NULL) {
|
||||
smb_panic("Could not create temporary talloc context\n");
|
||||
}
|
||||
|
||||
return lp_talloc;
|
||||
}
|
||||
|
||||
/*******************************************************************
|
||||
Convenience routine to grab string parameters into temporary memory
|
||||
and run standard_sub_basic on them. The buffers can be written to by
|
||||
@ -1800,10 +1842,10 @@ FN_GLOBAL_BOOL(lp_winbind_enum_groups, &Globals.bWinbindEnumGroups)
|
||||
FN_GLOBAL_BOOL(lp_winbind_use_default_domain, &Globals.bWinbindUseDefaultDomain)
|
||||
FN_GLOBAL_BOOL(lp_winbind_trusted_domains_only, &Globals.bWinbindTrustedDomainsOnly)
|
||||
FN_GLOBAL_BOOL(lp_winbind_nested_groups, &Globals.bWinbindNestedGroups)
|
||||
|
||||
FN_GLOBAL_BOOL(lp_winbind_refresh_tickets, &Globals.bWinbindRefreshTickets)
|
||||
FN_GLOBAL_BOOL(lp_winbind_offline_logon, &Globals.bWinbindOfflineLogon)
|
||||
|
||||
FN_GLOBAL_LIST(lp_idmap_backend, &Globals.szIdmapBackend)
|
||||
FN_GLOBAL_BOOL(lp_enable_rid_algorithm, &Globals.bEnableRidAlgorithm)
|
||||
FN_GLOBAL_BOOL(lp_passdb_expand_explicit, &Globals.bPassdbExpandExplicit)
|
||||
|
||||
#ifdef WITH_LDAP_SAMCONFIG
|
||||
@ -1821,9 +1863,13 @@ FN_GLOBAL_INTEGER(lp_ldap_page_size, &Globals.ldap_page_size)
|
||||
FN_GLOBAL_STRING(lp_add_share_cmd, &Globals.szAddShareCommand)
|
||||
FN_GLOBAL_STRING(lp_change_share_cmd, &Globals.szChangeShareCommand)
|
||||
FN_GLOBAL_STRING(lp_delete_share_cmd, &Globals.szDeleteShareCommand)
|
||||
FN_GLOBAL_STRING(lp_usershare_path, &Globals.szUsersharePath)
|
||||
FN_GLOBAL_LIST(lp_usershare_prefix_allow_list, &Globals.szUsersharePrefixAllowList)
|
||||
FN_GLOBAL_LIST(lp_usershare_prefix_deny_list, &Globals.szUsersharePrefixDenyList)
|
||||
|
||||
FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs)
|
||||
|
||||
FN_GLOBAL_BOOL(lp_usershare_owner_only, &Globals.bUsershareOwnerOnly)
|
||||
FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios)
|
||||
FN_GLOBAL_BOOL(lp_reset_on_zero_vc, &Globals.bResetOnZeroVC)
|
||||
FN_GLOBAL_BOOL(lp_ms_add_printer_wizard, &Globals.bMsAddPrinterWizard)
|
||||
@ -1912,6 +1958,8 @@ FN_GLOBAL_INTEGER(lp_map_to_guest, &Globals.map_to_guest)
|
||||
FN_GLOBAL_INTEGER(lp_oplock_break_wait_time, &Globals.oplock_break_wait_time)
|
||||
FN_GLOBAL_INTEGER(lp_lock_spin_count, &Globals.iLockSpinCount)
|
||||
FN_GLOBAL_INTEGER(lp_lock_sleep_time, &Globals.iLockSpinTime)
|
||||
FN_GLOBAL_INTEGER(lp_usershare_max_shares, &Globals.iUsershareMaxShares)
|
||||
|
||||
FN_LOCAL_STRING(lp_preexec, szPreExec)
|
||||
FN_LOCAL_STRING(lp_postexec, szPostExec)
|
||||
FN_LOCAL_STRING(lp_rootpreexec, szRootPreExec)
|
||||
@ -2479,7 +2527,7 @@ static char *canonicalize_servicename(const char *src)
|
||||
}
|
||||
|
||||
fstrcpy( canon, src );
|
||||
strupper_m( canon );
|
||||
strlower_m( canon );
|
||||
|
||||
return canon;
|
||||
}
|
||||
@ -4028,9 +4076,11 @@ void lp_killunused(BOOL (*snumused) (int))
|
||||
if (!VALID(i))
|
||||
continue;
|
||||
|
||||
/* don't kill autoloaded services */
|
||||
if ( ServicePtrs[i]->autoloaded )
|
||||
/* don't kill autoloaded or usershare services */
|
||||
if ( ServicePtrs[i]->autoloaded ||
|
||||
ServicePtrs[i]->usershare == USERSHARE_VALID) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!snumused || !snumused(i)) {
|
||||
free_service_byindex(i);
|
||||
@ -4179,6 +4229,7 @@ static void set_server_role(void)
|
||||
/***********************************************************
|
||||
If we should send plaintext/LANMAN passwords in the clinet
|
||||
************************************************************/
|
||||
|
||||
static void set_allowed_client_auth(void)
|
||||
{
|
||||
if (Globals.bClientNTLMv2Auth) {
|
||||
@ -4189,6 +4240,611 @@ static void set_allowed_client_auth(void)
|
||||
}
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
JRA.
|
||||
The following code allows smbd to read a user defined share file.
|
||||
Yes, this is my intent. Yes, I'm comfortable with that...
|
||||
|
||||
THE FOLLOWING IS SECURITY CRITICAL CODE.
|
||||
|
||||
It washes your clothes, it cleans your house, it guards you while you sleep...
|
||||
Do not f%^k with it....
|
||||
***************************************************************************/
|
||||
|
||||
#define MAX_USERSHARE_FILE_SIZE (10*1024)
|
||||
|
||||
/***************************************************************************
|
||||
Check allowed stat state of a usershare file.
|
||||
Ensure we print out who is dicking with us so the admin can
|
||||
get their sorry ass fired.
|
||||
***************************************************************************/
|
||||
|
||||
static BOOL check_usershare_stat(const char *fname, SMB_STRUCT_STAT *psbuf)
|
||||
{
|
||||
if (!S_ISREG(psbuf->st_mode)) {
|
||||
DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
|
||||
"not a regular file\n",
|
||||
fname, (unsigned int)psbuf->st_uid ));
|
||||
return False;
|
||||
}
|
||||
|
||||
/* Ensure this doesn't have the other write bit set. */
|
||||
if (psbuf->st_mode & S_IWOTH) {
|
||||
DEBUG(0,("check_usershare_stat: file %s owned by uid %u allows "
|
||||
"public write. Refusing to allow as a usershare file.\n",
|
||||
fname, (unsigned int)psbuf->st_uid ));
|
||||
return False;
|
||||
}
|
||||
|
||||
/* Should be 10k or less. */
|
||||
if (psbuf->st_size > MAX_USERSHARE_FILE_SIZE) {
|
||||
DEBUG(0,("check_usershare_stat: file %s owned by uid %u is "
|
||||
"too large (%u) to be a user share file.\n",
|
||||
fname, (unsigned int)psbuf->st_uid,
|
||||
(unsigned int)psbuf->st_size ));
|
||||
return False;
|
||||
}
|
||||
|
||||
return True;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Parse the contents of a usershare file.
|
||||
***************************************************************************/
|
||||
|
||||
enum usershare_err parse_usershare_file(TALLOC_CTX *ctx,
|
||||
SMB_STRUCT_STAT *psbuf,
|
||||
const char *servicename,
|
||||
int snum,
|
||||
char **lines,
|
||||
int numlines,
|
||||
pstring sharepath,
|
||||
pstring comment,
|
||||
SEC_DESC **ppsd)
|
||||
{
|
||||
const char **prefixallowlist = lp_usershare_prefix_allow_list();
|
||||
const char **prefixdenylist = lp_usershare_prefix_deny_list();
|
||||
SMB_STRUCT_DIR *dp;
|
||||
SMB_STRUCT_STAT sbuf;
|
||||
|
||||
if (numlines < 4) {
|
||||
return USERSHARE_MALFORMED_FILE;
|
||||
}
|
||||
|
||||
if (!strequal(lines[0], "#VERSION 1")) {
|
||||
return USERSHARE_BAD_VERSION;
|
||||
}
|
||||
|
||||
if (!strnequal(lines[1], "path=", 5)) {
|
||||
return USERSHARE_MALFORMED_PATH;
|
||||
}
|
||||
|
||||
pstrcpy(sharepath, &lines[1][5]);
|
||||
trim_string(sharepath, " ", " ");
|
||||
|
||||
if (!strnequal(lines[2], "comment=", 8)) {
|
||||
return USERSHARE_MALFORMED_COMMENT_DEF;
|
||||
}
|
||||
|
||||
pstrcpy(comment, &lines[2][8]);
|
||||
trim_string(comment, " ", " ");
|
||||
trim_char(comment, '"', '"');
|
||||
|
||||
if (!strnequal(lines[3], "usershare_acl=", 14)) {
|
||||
return USERSHARE_MALFORMED_ACL_DEF;
|
||||
}
|
||||
|
||||
if (!parse_usershare_acl(ctx, &lines[3][14], ppsd)) {
|
||||
return USERSHARE_ACL_ERR;
|
||||
}
|
||||
|
||||
if (snum != -1 && strequal(sharepath, ServicePtrs[snum]->szPath)) {
|
||||
/* Path didn't change, no checks needed. */
|
||||
return USERSHARE_OK;
|
||||
}
|
||||
|
||||
/* The path *must* be absolute. */
|
||||
if (sharepath[0] != '/') {
|
||||
DEBUG(2,("parse_usershare_file: share %s: path %s is not an absolute path.\n",
|
||||
servicename, sharepath));
|
||||
return USERSHARE_PATH_NOT_ABSOLUTE;
|
||||
}
|
||||
|
||||
/* If there is a usershare prefix deny list ensure one of these paths
|
||||
doesn't match the start of the user given path. */
|
||||
if (prefixdenylist) {
|
||||
int i;
|
||||
for ( i=0; prefixdenylist[i]; i++ ) {
|
||||
DEBUG(10,("parse_usershare_file: share %s : checking prefixdenylist[%d]='%s' against %s\n",
|
||||
servicename, i, prefixdenylist[i], sharepath ));
|
||||
if (memcmp( sharepath, prefixdenylist[i], strlen(prefixdenylist[i])) == 0) {
|
||||
DEBUG(2,("parse_usershare_file: share %s path %s starts with one of the "
|
||||
"usershare prefix deny list entries.\n",
|
||||
servicename, sharepath));
|
||||
return USERSHARE_PATH_IS_DENIED;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* If there is a usershare prefix allow list ensure one of these paths
|
||||
does match the start of the user given path. */
|
||||
|
||||
if (prefixallowlist) {
|
||||
int i;
|
||||
for ( i=0; prefixallowlist[i]; i++ ) {
|
||||
DEBUG(10,("parse_usershare_file: share %s checking prefixallowlist[%d]='%s' against %s\n",
|
||||
servicename, i, prefixallowlist[i], sharepath ));
|
||||
if (memcmp( sharepath, prefixallowlist[i], strlen(prefixallowlist[i])) == 0) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (prefixallowlist[i] == NULL) {
|
||||
DEBUG(2,("parse_usershare_file: share %s path %s doesn't start with one of the "
|
||||
"usershare prefix allow list entries.\n",
|
||||
servicename, sharepath));
|
||||
return USERSHARE_PATH_NOT_ALLOWED;
|
||||
}
|
||||
}
|
||||
|
||||
/* Ensure this is pointing to a directory. */
|
||||
dp = sys_opendir(sharepath);
|
||||
|
||||
if (!dp) {
|
||||
DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
|
||||
servicename, sharepath));
|
||||
return USERSHARE_PATH_NOT_DIRECTORY;
|
||||
}
|
||||
|
||||
/* Ensure the owner of the usershare file has permission to share
|
||||
this directory. */
|
||||
|
||||
if (sys_stat(sharepath, &sbuf) == -1) {
|
||||
DEBUG(2,("parse_usershare_file: share %s : stat failed on path %s. %s\n",
|
||||
servicename, sharepath, strerror(errno) ));
|
||||
sys_closedir(dp);
|
||||
return USERSHARE_POSIX_ERR;
|
||||
}
|
||||
|
||||
sys_closedir(dp);
|
||||
|
||||
if (!S_ISDIR(sbuf.st_mode)) {
|
||||
DEBUG(2,("parse_usershare_file: share %s path %s is not a directory.\n",
|
||||
servicename, sharepath ));
|
||||
return USERSHARE_PATH_NOT_DIRECTORY;
|
||||
}
|
||||
|
||||
/* Check if sharing is restricted to owner-only. */
|
||||
/* psbuf is the stat of the usershare definition file,
|
||||
sbuf is the stat of the target directory to be shared. */
|
||||
|
||||
if (lp_usershare_owner_only()) {
|
||||
/* root can share anything. */
|
||||
if ((psbuf->st_uid != 0) && (sbuf.st_uid != psbuf->st_uid)) {
|
||||
return USERSHARE_PATH_NOT_ALLOWED;
|
||||
}
|
||||
}
|
||||
|
||||
return USERSHARE_OK;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Deal with a usershare file.
|
||||
Returns:
|
||||
>= 0 - snum
|
||||
-1 - Bad name, invalid contents.
|
||||
- service name already existed and not a usershare, problem
|
||||
with permissions to share directory etc.
|
||||
***************************************************************************/
|
||||
|
||||
static int process_usershare_file(const char *dir_name, const char *file_name, int snum_template)
|
||||
{
|
||||
SMB_STRUCT_STAT sbuf;
|
||||
SMB_STRUCT_STAT lsbuf;
|
||||
pstring fname;
|
||||
pstring sharepath;
|
||||
pstring comment;
|
||||
fstring service_name;
|
||||
char **lines = NULL;
|
||||
int numlines = 0;
|
||||
int fd = -1;
|
||||
int iService = -1;
|
||||
TALLOC_CTX *ctx = NULL;
|
||||
SEC_DESC *psd = NULL;
|
||||
|
||||
/* Ensure share name doesn't contain invalid characters. */
|
||||
if (!validate_net_name(file_name, INVALID_SHARENAME_CHARS, strlen(file_name))) {
|
||||
DEBUG(0,("process_usershare_file: share name %s contains "
|
||||
"invalid characters (any of %s)\n",
|
||||
file_name, INVALID_SHARENAME_CHARS ));
|
||||
return -1;
|
||||
}
|
||||
|
||||
fstrcpy(service_name, file_name);
|
||||
|
||||
pstrcpy(fname, dir_name);
|
||||
pstrcat(fname, "/");
|
||||
pstrcat(fname, file_name);
|
||||
|
||||
/* Minimize the race condition by doing an lstat before we
|
||||
open and fstat. Ensure this isn't a symlink link. */
|
||||
|
||||
if (sys_lstat(fname, &lsbuf) != 0) {
|
||||
DEBUG(0,("process_usershare_file: stat of %s failed. %s\n",
|
||||
fname, strerror(errno) ));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* This must be a regular file, not a symlink, directory or
|
||||
other strange filetype. */
|
||||
if (!check_usershare_stat(fname, &lsbuf)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* See if there is already a servicenum for this name. */
|
||||
/* tdb_fetch_int32 returns -1 if not found. */
|
||||
iService = (int)tdb_fetch_int32(ServiceHash, canonicalize_servicename(service_name) );
|
||||
|
||||
if (iService != -1 && ServicePtrs[iService]->usershare_last_mod == lsbuf.st_mtime) {
|
||||
/* Nothing changed - Mark valid and return. */
|
||||
DEBUG(10,("process_usershare_file: service %s not changed.\n",
|
||||
service_name ));
|
||||
ServicePtrs[iService]->usershare = USERSHARE_VALID;
|
||||
return iService;
|
||||
}
|
||||
|
||||
/* Try and open the file read only - no symlinks allowed. */
|
||||
#ifdef O_NOFOLLOW
|
||||
fd = sys_open(fname, O_RDONLY|O_NOFOLLOW, 0);
|
||||
#else
|
||||
fd = sys_open(fname, O_RDONLY, 0);
|
||||
#endif
|
||||
|
||||
if (fd == -1) {
|
||||
DEBUG(0,("process_usershare_file: unable to open %s. %s\n",
|
||||
fname, strerror(errno) ));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Now fstat to be *SURE* it's a regular file. */
|
||||
if (sys_fstat(fd, &sbuf) != 0) {
|
||||
close(fd);
|
||||
DEBUG(0,("process_usershare_file: fstat of %s failed. %s\n",
|
||||
fname, strerror(errno) ));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Is it the same dev/inode as was lstated ? */
|
||||
if (lsbuf.st_dev != sbuf.st_dev || lsbuf.st_ino != sbuf.st_ino) {
|
||||
close(fd);
|
||||
DEBUG(0,("process_usershare_file: fstat of %s is a different file from lstat. "
|
||||
"Symlink spoofing going on ?\n", fname ));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* This must be a regular file, not a symlink, directory or
|
||||
other strange filetype. */
|
||||
if (!check_usershare_stat(fname, &sbuf)) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
lines = fd_lines_load(fd, &numlines, MAX_USERSHARE_FILE_SIZE);
|
||||
|
||||
close(fd);
|
||||
if (lines == NULL) {
|
||||
DEBUG(0,("process_usershare_file: loading file %s owned by %u failed.\n",
|
||||
fname, (unsigned int)sbuf.st_uid ));
|
||||
}
|
||||
|
||||
/* Should we allow printers to be shared... ? */
|
||||
ctx = talloc_init("usershare_sd_xctx");
|
||||
if (!ctx) {
|
||||
SAFE_FREE(lines);
|
||||
return 1;
|
||||
}
|
||||
|
||||
if (parse_usershare_file(ctx, &sbuf, service_name, iService, lines, numlines, sharepath, comment, &psd) != USERSHARE_OK) {
|
||||
talloc_destroy(ctx);
|
||||
SAFE_FREE(lines);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SAFE_FREE(lines);
|
||||
|
||||
/* Everything ok - add the service possibly using a template. */
|
||||
if (iService < 0) {
|
||||
const service *sp = &sDefault;
|
||||
if (snum_template != -1) {
|
||||
sp = ServicePtrs[snum_template];
|
||||
}
|
||||
|
||||
if ((iService = add_a_service(sp, service_name)) < 0) {
|
||||
DEBUG(0, ("process_usershare_file: Failed to add "
|
||||
"new service %s\n", service_name));
|
||||
talloc_destroy(ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Read only is controlled by usershare ACL below. */
|
||||
ServicePtrs[iService]->bRead_only = False;
|
||||
}
|
||||
|
||||
/* Write the ACL of the new/modified share. */
|
||||
if (!set_share_security(ctx, service_name, psd)) {
|
||||
DEBUG(0, ("process_usershare_file: Failed to set share "
|
||||
"security for user share %s\n",
|
||||
service_name ));
|
||||
lp_remove_service(iService);
|
||||
talloc_destroy(ctx);
|
||||
return -1;
|
||||
}
|
||||
|
||||
talloc_destroy(ctx);
|
||||
|
||||
/* If from a template it may be marked invalid. */
|
||||
ServicePtrs[iService]->valid = True;
|
||||
|
||||
/* Set the service as a valid usershare. */
|
||||
ServicePtrs[iService]->usershare = USERSHARE_VALID;
|
||||
|
||||
/* And note when it was loaded. */
|
||||
ServicePtrs[iService]->usershare_last_mod = sbuf.st_mtime;
|
||||
string_set(&ServicePtrs[iService]->szPath, sharepath);
|
||||
string_set(&ServicePtrs[iService]->comment, comment);
|
||||
|
||||
return iService;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Checks if a usershare entry has been modified since last load.
|
||||
***************************************************************************/
|
||||
|
||||
static BOOL usershare_exists(int iService, time_t *last_mod)
|
||||
{
|
||||
SMB_STRUCT_STAT lsbuf;
|
||||
const char *usersharepath = Globals.szUsersharePath;
|
||||
pstring fname;
|
||||
|
||||
pstrcpy(fname, usersharepath);
|
||||
pstrcat(fname, "/");
|
||||
pstrcat(fname, ServicePtrs[iService]->szService);
|
||||
|
||||
if (sys_lstat(fname, &lsbuf) != 0) {
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!S_ISREG(lsbuf.st_mode)) {
|
||||
return False;
|
||||
}
|
||||
|
||||
*last_mod = lsbuf.st_mtime;
|
||||
return True;
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Load a usershare service by name. Returns a valid servicenumber or -1.
|
||||
***************************************************************************/
|
||||
|
||||
int load_usershare_service(const char *servicename)
|
||||
{
|
||||
SMB_STRUCT_STAT sbuf;
|
||||
const char *usersharepath = Globals.szUsersharePath;
|
||||
int max_user_shares = Globals.iUsershareMaxShares;
|
||||
int snum_template = -1;
|
||||
|
||||
if (*usersharepath == 0 || max_user_shares == 0) {
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (sys_stat(usersharepath, &sbuf) != 0) {
|
||||
DEBUG(0,("load_usershare_service: stat of %s failed. %s\n",
|
||||
usersharepath, strerror(errno) ));
|
||||
return -1;
|
||||
}
|
||||
|
||||
if (!S_ISDIR(sbuf.st_mode)) {
|
||||
DEBUG(0,("load_usershare_service: %s is not a directory.\n",
|
||||
usersharepath ));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/*
|
||||
* This directory must be owned by root, and have the 't' bit set.
|
||||
* It also must not be writable by "other".
|
||||
*/
|
||||
|
||||
#ifdef S_ISVTX
|
||||
if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
|
||||
#else
|
||||
if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
|
||||
#endif
|
||||
DEBUG(0,("load_usershare_service: directory %s is not owned by root "
|
||||
"or does not have the sticky bit 't' set or is writable by anyone.\n",
|
||||
usersharepath ));
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Ensure the template share exists if it's set. */
|
||||
if (Globals.szUsershareTemplateShare[0]) {
|
||||
/* We can't use lp_servicenumber here as we are recommending that
|
||||
template shares have -valid=False set. */
|
||||
for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
|
||||
if (ServicePtrs[snum_template]->szService &&
|
||||
strequal(ServicePtrs[snum_template]->szService,
|
||||
Globals.szUsershareTemplateShare)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (snum_template == -1) {
|
||||
DEBUG(0,("load_usershare_service: usershare template share %s "
|
||||
"does not exist.\n",
|
||||
Globals.szUsershareTemplateShare ));
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
|
||||
return process_usershare_file(usersharepath, servicename, snum_template);
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Load all user defined shares from the user share directory.
|
||||
We only do this if we're enumerating the share list.
|
||||
This is the function that can delete usershares that have
|
||||
been removed.
|
||||
***************************************************************************/
|
||||
|
||||
int load_usershare_shares(void)
|
||||
{
|
||||
SMB_STRUCT_DIR *dp;
|
||||
SMB_STRUCT_STAT sbuf;
|
||||
SMB_STRUCT_DIRENT *de;
|
||||
int num_usershares = 0;
|
||||
int max_user_shares = Globals.iUsershareMaxShares;
|
||||
unsigned int num_dir_entries, num_bad_dir_entries, num_tmp_dir_entries;
|
||||
unsigned int allowed_bad_entries = ((2*max_user_shares)/10);
|
||||
unsigned int allowed_tmp_entries = ((2*max_user_shares)/10);
|
||||
int iService;
|
||||
int snum_template = -1;
|
||||
const char *usersharepath = Globals.szUsersharePath;
|
||||
int ret = lp_numservices();
|
||||
|
||||
if (max_user_shares == 0 || *usersharepath == '\0') {
|
||||
return lp_numservices();
|
||||
}
|
||||
|
||||
if (sys_stat(usersharepath, &sbuf) != 0) {
|
||||
DEBUG(0,("load_usershare_shares: stat of %s failed. %s\n",
|
||||
usersharepath, strerror(errno) ));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/*
|
||||
* This directory must be owned by root, and have the 't' bit set.
|
||||
* It also must not be writable by "other".
|
||||
*/
|
||||
|
||||
#ifdef S_ISVTX
|
||||
if (sbuf.st_uid != 0 || !(sbuf.st_mode & S_ISVTX) || (sbuf.st_mode & S_IWOTH)) {
|
||||
#else
|
||||
if (sbuf.st_uid != 0 || (sbuf.st_mode & S_IWOTH)) {
|
||||
#endif
|
||||
DEBUG(0,("load_usershare_shares: directory %s is not owned by root "
|
||||
"or does not have the sticky bit 't' set or is writable by anyone.\n",
|
||||
usersharepath ));
|
||||
return ret;
|
||||
}
|
||||
|
||||
/* Ensure the template share exists if it's set. */
|
||||
if (Globals.szUsershareTemplateShare[0]) {
|
||||
/* We can't use lp_servicenumber here as we are recommending that
|
||||
template shares have -valid=False set. */
|
||||
for (snum_template = iNumServices - 1; snum_template >= 0; snum_template--) {
|
||||
if (ServicePtrs[snum_template]->szService &&
|
||||
strequal(ServicePtrs[snum_template]->szService,
|
||||
Globals.szUsershareTemplateShare)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (snum_template == -1) {
|
||||
DEBUG(0,("load_usershare_shares: usershare template share %s "
|
||||
"does not exist.\n",
|
||||
Globals.szUsershareTemplateShare ));
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
/* Mark all existing usershares as pending delete. */
|
||||
for (iService = iNumServices - 1; iService >= 0; iService--) {
|
||||
if (VALID(iService) && ServicePtrs[iService]->usershare) {
|
||||
ServicePtrs[iService]->usershare = USERSHARE_PENDING_DELETE;
|
||||
}
|
||||
}
|
||||
|
||||
dp = sys_opendir(usersharepath);
|
||||
if (!dp) {
|
||||
DEBUG(0,("load_usershare_shares:: failed to open directory %s. %s\n",
|
||||
usersharepath, strerror(errno) ));
|
||||
return ret;
|
||||
}
|
||||
|
||||
for (num_dir_entries = 0, num_bad_dir_entries = 0, num_tmp_dir_entries = 0;
|
||||
(de = sys_readdir(dp));
|
||||
num_dir_entries++ ) {
|
||||
int r;
|
||||
const char *n = de->d_name;
|
||||
|
||||
/* Ignore . and .. */
|
||||
if (*n == '.') {
|
||||
if ((n[1] == '\0') || (n[1] == '.' && n[2] == '\0')) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
if (n[0] == ':') {
|
||||
/* Temporary file used when creating a share. */
|
||||
num_tmp_dir_entries++;
|
||||
}
|
||||
|
||||
/* Allow 20% tmp entries. */
|
||||
if (num_tmp_dir_entries > allowed_tmp_entries) {
|
||||
DEBUG(0,("load_usershare_shares: too many temp entries (%u) "
|
||||
"in directory %s\n",
|
||||
num_tmp_dir_entries, usersharepath));
|
||||
break;
|
||||
}
|
||||
|
||||
r = process_usershare_file(usersharepath, n, snum_template);
|
||||
if (r == 0) {
|
||||
/* Update the services count. */
|
||||
num_usershares++;
|
||||
if (num_usershares >= max_user_shares) {
|
||||
DEBUG(0,("load_usershare_shares: max user shares reached "
|
||||
"on file %s in directory %s\n",
|
||||
n, usersharepath ));
|
||||
break;
|
||||
}
|
||||
} else if (r == -1) {
|
||||
num_bad_dir_entries++;
|
||||
}
|
||||
|
||||
/* Allow 20% bad entries. */
|
||||
if (num_bad_dir_entries > allowed_bad_entries) {
|
||||
DEBUG(0,("load_usershare_shares: too many bad entries (%u) "
|
||||
"in directory %s\n",
|
||||
num_bad_dir_entries, usersharepath));
|
||||
break;
|
||||
}
|
||||
|
||||
/* Allow 20% bad entries. */
|
||||
if (num_dir_entries > max_user_shares + allowed_bad_entries) {
|
||||
DEBUG(0,("load_usershare_shares: too many total entries (%u) "
|
||||
"in directory %s\n",
|
||||
num_dir_entries, usersharepath));
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
sys_closedir(dp);
|
||||
|
||||
/* Sweep through and delete any non-refreshed usershares that are
|
||||
not currently in use. */
|
||||
for (iService = iNumServices - 1; iService >= 0; iService--) {
|
||||
if (VALID(iService) && (ServicePtrs[iService]->usershare == USERSHARE_PENDING_DELETE)) {
|
||||
if (conn_snum_used(iService)) {
|
||||
continue;
|
||||
}
|
||||
/* Remove from the share ACL db. */
|
||||
DEBUG(10,("load_usershare_shares: Removing deleted usershare %s\n",
|
||||
lp_servicename(iService) ));
|
||||
delete_share_security(iService);
|
||||
free_service_byindex(iService);
|
||||
}
|
||||
}
|
||||
|
||||
return lp_numservices();
|
||||
}
|
||||
|
||||
/***************************************************************************
|
||||
Load the services array from the services file. Return True on success,
|
||||
False on failure.
|
||||
@ -4339,8 +4995,9 @@ int lp_servicenumber(const char *pszServiceName)
|
||||
int iService;
|
||||
fstring serviceName;
|
||||
|
||||
if (!pszServiceName)
|
||||
if (!pszServiceName) {
|
||||
return GLOBAL_SECTION_SNUM;
|
||||
}
|
||||
|
||||
for (iService = iNumServices - 1; iService >= 0; iService--) {
|
||||
if (VALID(iService) && ServicePtrs[iService]->szService) {
|
||||
@ -4350,8 +5007,30 @@ int lp_servicenumber(const char *pszServiceName)
|
||||
*/
|
||||
fstrcpy(serviceName, ServicePtrs[iService]->szService);
|
||||
standard_sub_basic(get_current_username(), serviceName,sizeof(serviceName));
|
||||
if (strequal(serviceName, pszServiceName))
|
||||
if (strequal(serviceName, pszServiceName)) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (iService >= 0 && ServicePtrs[iService]->usershare == USERSHARE_VALID) {
|
||||
time_t last_mod;
|
||||
|
||||
if (!usershare_exists(iService, &last_mod)) {
|
||||
/* Remove the share security tdb entry for it. */
|
||||
delete_share_security(iService);
|
||||
/* Remove it from the array. */
|
||||
free_service_byindex(iService);
|
||||
/* Doesn't exist anymore. */
|
||||
return GLOBAL_SECTION_SNUM;
|
||||
}
|
||||
|
||||
/* Has it been modified ? If so delete and reload. */
|
||||
if (ServicePtrs[iService]->usershare_last_mod < last_mod) {
|
||||
/* Remove it from the array. */
|
||||
free_service_byindex(iService);
|
||||
/* and now reload it. */
|
||||
iService = load_usershare_service(pszServiceName);
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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)) );
|
||||
|
File diff suppressed because it is too large
Load Diff
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user