mirror of
https://github.com/samba-team/samba.git
synced 2024-12-22 13:34:15 +03:00
r13316: Let the carnage begin....
Sync with trunk as off r13315
(This used to be commit 17e63ac4ed
)
This commit is contained in:
parent
21a30a1346
commit
0af1500fc0
@ -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,8 +245,7 @@ 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) \
|
||||
@ -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
source3/include/event.h
Normal file
31
source3/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
source3/include/gpo.h
Normal file
91
source3/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.
|
||||
#ifndef _RPC_NETDFS_H
|
||||
#define _RPC_NETDFS_H
|
||||
|
||||
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.
|
||||
*/
|
||||
#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
|
||||
|
||||
#ifndef _RPC_DFS_H
|
||||
#define _RPC_DFS_H
|
||||
|
||||
/* NETDFS pipe: calls */
|
||||
#define DFS_EXIST 0x00
|
||||
#define DFS_ADD 0x01
|
||||
#define DFS_REMOVE 0x02
|
||||
#define DFS_GET_INFO 0x04
|
||||
#define DFS_ENUM 0x05
|
||||
|
||||
/* dfsadd flags */
|
||||
#define DFSFLAG_ADD_VOLUME 0x00000001
|
||||
#define DFSFLAG_RESTORE_VOLUME 0x00000002
|
||||
|
||||
typedef struct dfs_q_dfs_exist {
|
||||
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;
|
||||
typedef struct netdfs_dfs_EnumArray1 {
|
||||
uint32 count;
|
||||
uint32 ptr0_s;
|
||||
uint32 size_s;
|
||||
NETDFS_DFS_INFO1 *s;
|
||||
} NETDFS_DFS_ENUMARRAY1;
|
||||
|
||||
uint32 ptr_server;
|
||||
UNISTR2 uni_server;
|
||||
typedef struct netdfs_dfs_EnumArray2 {
|
||||
uint32 count;
|
||||
uint32 ptr0_s;
|
||||
uint32 size_s;
|
||||
NETDFS_DFS_INFO2 *s;
|
||||
} NETDFS_DFS_ENUMARRAY2;
|
||||
|
||||
uint32 ptr_share;
|
||||
UNISTR2 uni_share;
|
||||
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,17 +224,25 @@ 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
|
||||
|
||||
@ -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
source3/lib/events.c
Normal file
125
source3/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
source3/lib/sharesec.c
Normal file
308
source3/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 */
|
||||
|
||||
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)));
|
||||
}
|
||||
|
||||
list[num] = SMB_STRDUP(tok);
|
||||
if (mem_ctx) {
|
||||
list[num] = talloc_strdup(mem_ctx, tok);
|
||||
} else {
|
||||
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
source3/libads/gpo.c
Normal file
680
source3/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
source3/libads/gpo_util.c
Normal file
496
source3/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)))
|
||||
@ -78,8 +82,10 @@ int kerberos_kinit_password(const char *principal,
|
||||
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;
|
||||
}
|
||||
@ -89,9 +95,19 @@ int kerberos_kinit_password(const char *principal,
|
||||
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;
|
||||
@ -112,8 +128,13 @@ int kerberos_kinit_password(const char *principal,
|
||||
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
source3/libads/krb5_errs.c
Normal file
132
source3/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,8 +426,8 @@ 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;
|
||||
}
|
||||
|
||||
@ -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;
|
||||
@ -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
source3/libsmb/gpo.c
Normal file
167
source3/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 */
|
||||
|
||||
@ -1063,6 +1063,10 @@ int main(int argc, char **argv)
|
||||
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,9 +524,7 @@ 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);
|
||||
|
||||
@ -451,32 +532,12 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache,
|
||||
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,16 +1618,184 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain,
|
||||
char ***alt_names,
|
||||
DOM_SID **dom_sids)
|
||||
{
|
||||
get_cache(domain);
|
||||
struct winbind_cache *cache = get_cache(domain);
|
||||
struct cache_entry *centry = NULL;
|
||||
NTSTATUS status;
|
||||
int i;
|
||||
|
||||
if (!cache->tdb)
|
||||
goto do_query;
|
||||
|
||||
centry = wcache_fetch(cache, domain, "TRUSTDOMS/%s", domain->name);
|
||||
|
||||
if (!centry) {
|
||||
goto do_query;
|
||||
}
|
||||
|
||||
*num_domains = centry_uint32(centry);
|
||||
|
||||
(*names) = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
|
||||
(*alt_names) = TALLOC_ARRAY(mem_ctx, char *, *num_domains);
|
||||
(*dom_sids) = TALLOC_ARRAY(mem_ctx, DOM_SID, *num_domains);
|
||||
|
||||
if (! (*dom_sids) || ! (*names) || ! (*alt_names)) {
|
||||
smb_panic("trusted_domains out of memory");
|
||||
}
|
||||
|
||||
for (i=0; i<(*num_domains); i++) {
|
||||
(*names)[i] = centry_string(centry, mem_ctx);
|
||||
(*alt_names)[i] = centry_string(centry, mem_ctx);
|
||||
centry_sid(centry, &(*dom_sids)[i]);
|
||||
}
|
||||
|
||||
status = centry->status;
|
||||
|
||||
DEBUG(10,("trusted_domains: [Cached] - cached info for domain %s status %s\n",
|
||||
domain->name, get_friendly_nt_error_msg(status) ));
|
||||
|
||||
centry_free(centry);
|
||||
return status;
|
||||
|
||||
do_query:
|
||||
(*num_domains) = 0;
|
||||
(*dom_sids) = NULL;
|
||||
(*names) = NULL;
|
||||
(*alt_names) = NULL;
|
||||
|
||||
/* Return status value returned by seq number check */
|
||||
|
||||
if (!NT_STATUS_IS_OK(domain->last_status))
|
||||
return domain->last_status;
|
||||
|
||||
DEBUG(10,("trusted_domains: [Cached] - doing backend query for info for domain %s\n",
|
||||
domain->name ));
|
||||
|
||||
/* we don't cache this call */
|
||||
return domain->backend->trusted_domains(domain, mem_ctx, num_domains,
|
||||
names, alt_names, dom_sids);
|
||||
status = domain->backend->trusted_domains(domain, mem_ctx, num_domains,
|
||||
names, alt_names, dom_sids);
|
||||
|
||||
/* and save it */
|
||||
refresh_sequence_number(domain, False);
|
||||
|
||||
centry = centry_start(domain, status);
|
||||
if (!centry)
|
||||
goto skip_save;
|
||||
|
||||
centry_put_uint32(centry, *num_domains);
|
||||
|
||||
for (i=0; i<(*num_domains); i++) {
|
||||
centry_put_string(centry, (*names)[i]);
|
||||
centry_put_string(centry, (*alt_names)[i]);
|
||||
centry_put_sid(centry, &(*dom_sids)[i]);
|
||||
}
|
||||
|
||||
centry_end(centry, "TRUSTDOMS/%s", domain->name);
|
||||
|
||||
centry_free(centry);
|
||||
|
||||
skip_save:
|
||||
return status;
|
||||
}
|
||||
|
||||
/* get lockout policy */
|
||||
static NTSTATUS lockout_policy(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
SAM_UNK_INFO_12 *lockout_policy){
|
||||
struct winbind_cache *cache = get_cache(domain);
|
||||
struct cache_entry *centry = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
if (!cache->tdb)
|
||||
goto do_query;
|
||||
|
||||
centry = wcache_fetch(cache, domain, "LOC_POL/%s", domain->name);
|
||||
|
||||
if (!centry)
|
||||
goto do_query;
|
||||
|
||||
lockout_policy->duration = centry_nttime(centry);
|
||||
lockout_policy->reset_count = centry_nttime(centry);
|
||||
lockout_policy->bad_attempt_lockout = centry_uint16(centry);
|
||||
|
||||
status = centry->status;
|
||||
|
||||
DEBUG(10,("lockout_policy: [Cached] - cached info for domain %s status %s\n",
|
||||
domain->name, get_friendly_nt_error_msg(status) ));
|
||||
|
||||
centry_free(centry);
|
||||
return status;
|
||||
|
||||
do_query:
|
||||
ZERO_STRUCTP(lockout_policy);
|
||||
|
||||
/* Return status value returned by seq number check */
|
||||
|
||||
if (!NT_STATUS_IS_OK(domain->last_status))
|
||||
return domain->last_status;
|
||||
|
||||
DEBUG(10,("lockout_policy: [Cached] - doing backend query for info for domain %s\n",
|
||||
domain->name ));
|
||||
|
||||
status = domain->backend->lockout_policy(domain, mem_ctx, lockout_policy);
|
||||
|
||||
/* and save it */
|
||||
refresh_sequence_number(domain, False);
|
||||
wcache_save_lockout_policy(domain, status, lockout_policy);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* get password policy */
|
||||
static NTSTATUS password_policy(struct winbindd_domain *domain,
|
||||
TALLOC_CTX *mem_ctx,
|
||||
SAM_UNK_INFO_1 *password_policy)
|
||||
{
|
||||
struct winbind_cache *cache = get_cache(domain);
|
||||
struct cache_entry *centry = NULL;
|
||||
NTSTATUS status;
|
||||
|
||||
if (!cache->tdb)
|
||||
goto do_query;
|
||||
|
||||
centry = wcache_fetch(cache, domain, "PWD_POL/%s", domain->name);
|
||||
|
||||
if (!centry)
|
||||
goto do_query;
|
||||
|
||||
password_policy->min_length_password = centry_uint16(centry);
|
||||
password_policy->password_history = centry_uint16(centry);
|
||||
password_policy->password_properties = centry_uint32(centry);
|
||||
password_policy->expire = centry_nttime(centry);
|
||||
password_policy->min_passwordage = centry_nttime(centry);
|
||||
|
||||
status = centry->status;
|
||||
|
||||
DEBUG(10,("lockout_policy: [Cached] - cached info for domain %s status %s\n",
|
||||
domain->name, get_friendly_nt_error_msg(status) ));
|
||||
|
||||
centry_free(centry);
|
||||
return status;
|
||||
|
||||
do_query:
|
||||
ZERO_STRUCTP(password_policy);
|
||||
|
||||
/* Return status value returned by seq number check */
|
||||
|
||||
if (!NT_STATUS_IS_OK(domain->last_status))
|
||||
return domain->last_status;
|
||||
|
||||
DEBUG(10,("password_policy: [Cached] - doing backend query for info for domain %s\n",
|
||||
domain->name ));
|
||||
|
||||
status = domain->backend->password_policy(domain, mem_ctx, password_policy);
|
||||
|
||||
/* and save it */
|
||||
refresh_sequence_number(domain, False);
|
||||
wcache_save_password_policy(domain, status, password_policy);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
|
||||
/* Invalidate cached user and group lists coherently */
|
||||
|
||||
static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
|
||||
@ -1448,22 +1836,6 @@ void wcache_invalidate_cache(void)
|
||||
}
|
||||
}
|
||||
|
||||
/* the ADS backend methods are exposed via this structure */
|
||||
struct winbindd_methods cache_methods = {
|
||||
True,
|
||||
query_user_list,
|
||||
enum_dom_groups,
|
||||
enum_local_groups,
|
||||
name_to_sid,
|
||||
sid_to_name,
|
||||
query_user,
|
||||
lookup_usergroups,
|
||||
lookup_useraliases,
|
||||
lookup_groupmem,
|
||||
sequence_number,
|
||||
trusted_domains,
|
||||
};
|
||||
|
||||
static BOOL init_wcache(void)
|
||||
{
|
||||
if (wcache == NULL) {
|
||||
@ -1474,8 +1846,10 @@ static BOOL init_wcache(void)
|
||||
if (wcache->tdb != NULL)
|
||||
return True;
|
||||
|
||||
wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"), 5000,
|
||||
TDB_CLEAR_IF_FIRST, O_RDWR|O_CREAT, 0600);
|
||||
/* when working offline we must not clear the cache on restart */
|
||||
wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
|
||||
WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
|
||||
TDB_DEFAULT /*TDB_CLEAR_IF_FIRST*/, O_RDWR|O_CREAT, 0600);
|
||||
|
||||
if (wcache->tdb == NULL) {
|
||||
DEBUG(0,("Failed to open winbindd_cache.tdb!\n"));
|
||||
@ -1577,6 +1951,25 @@ BOOL cache_retrieve_response(pid_t pid, struct winbindd_response * response)
|
||||
return True;
|
||||
}
|
||||
|
||||
void cache_cleanup_response(pid_t pid)
|
||||
{
|
||||
fstring key_str;
|
||||
|
||||
if (!init_wcache())
|
||||
return;
|
||||
|
||||
DEBUG(10,("Cleaning up response for pid %d\n", pid));
|
||||
|
||||
fstr_sprintf(key_str, "DR/%d", pid);
|
||||
tdb_delete(wcache->tdb, string_tdb_data(key_str));
|
||||
|
||||
fstr_sprintf(key_str, "DE/%d", pid);
|
||||
tdb_delete(wcache->tdb, string_tdb_data(key_str));
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
|
||||
BOOL lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
|
||||
const char **domain_name, const char **name,
|
||||
enum SID_NAME_USE *type)
|
||||
@ -1613,6 +2006,48 @@ BOOL lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid,
|
||||
return NT_STATUS_IS_OK(status);
|
||||
}
|
||||
|
||||
BOOL lookup_cached_name(TALLOC_CTX *mem_ctx,
|
||||
const char *domain_name,
|
||||
const char *name,
|
||||
DOM_SID *sid,
|
||||
enum SID_NAME_USE *type)
|
||||
{
|
||||
struct winbindd_domain *domain;
|
||||
struct winbind_cache *cache;
|
||||
struct cache_entry *centry = NULL;
|
||||
NTSTATUS status;
|
||||
fstring uname;
|
||||
|
||||
domain = find_lookup_domain_from_name(domain_name);
|
||||
if (domain == NULL) {
|
||||
return False;
|
||||
}
|
||||
|
||||
cache = get_cache(domain);
|
||||
|
||||
if (cache->tdb == NULL) {
|
||||
return False;
|
||||
}
|
||||
|
||||
fstrcpy(uname, name);
|
||||
strupper_m(uname);
|
||||
|
||||
centry = wcache_fetch(cache, domain, "NS/%s/%s", domain_name, uname);
|
||||
if (centry == NULL) {
|
||||
return False;
|
||||
}
|
||||
|
||||
if (NT_STATUS_IS_OK(centry->status)) {
|
||||
*type = (enum SID_NAME_USE)centry_uint32(centry);
|
||||
centry_sid(centry, sid);
|
||||
}
|
||||
|
||||
status = centry->status;
|
||||
centry_free(centry);
|
||||
|
||||
return NT_STATUS_IS_OK(status);
|
||||
}
|
||||
|
||||
void cache_sid2name(struct winbindd_domain *domain, const DOM_SID *sid,
|
||||
const char *domain_name, const char *name,
|
||||
enum SID_NAME_USE type)
|
||||
@ -1620,3 +2055,282 @@ void cache_sid2name(struct winbindd_domain *domain, const DOM_SID *sid,
|
||||
wcache_save_sid_to_name(domain, NT_STATUS_OK, sid, domain_name,
|
||||
name, type);
|
||||
}
|
||||
|
||||
/* delete all centries that don't have NT_STATUS_OK set */
|
||||
static int traverse_fn_cleanup(TDB_CONTEXT *the_tdb, TDB_DATA kbuf,
|
||||
TDB_DATA dbuf, void *state)
|
||||
{
|
||||
struct cache_entry *centry;
|
||||
char buf[1024];
|
||||
|
||||
if (!snprintf(buf, kbuf.dsize + 1, "%s", kbuf.dptr)) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
centry = wcache_fetch_raw(buf);
|
||||
if (!centry) {
|
||||
return 0;
|
||||
}
|
||||
|
||||
if (!NT_STATUS_IS_OK(centry->status)) {
|
||||
DEBUG(10,("deleting centry %s\n", buf));
|
||||
tdb_delete(the_tdb, kbuf);
|
||||
}
|
||||
|
||||
centry_free(centry);
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* flush the cache */
|
||||
void wcache_flush_cache(void)
|
||||
{
|
||||
extern BOOL opt_nocache;
|
||||
|
||||
if (!wcache)
|
||||
return;
|
||||
if (wcache->tdb) {
|
||||
tdb_close(wcache->tdb);
|
||||
wcache->tdb = NULL;
|
||||
}
|
||||
if (opt_nocache)
|
||||
return;
|
||||
|
||||
/* when working offline we must not clear the cache on restart */
|
||||
wcache->tdb = tdb_open_log(lock_path("winbindd_cache.tdb"),
|
||||
WINBINDD_CACHE_TDB_DEFAULT_HASH_SIZE,
|
||||
TDB_DEFAULT /* TDB_CLEAR_IF_FIRST */, O_RDWR|O_CREAT, 0600);
|
||||
|
||||
if (!wcache->tdb) {
|
||||
DEBUG(0,("Failed to open winbindd_cache.tdb!\n"));
|
||||
}
|
||||
|
||||
tdb_traverse(wcache->tdb, traverse_fn_cleanup, NULL);
|
||||
|
||||
DEBUG(10,("wcache_flush_cache success\n"));
|
||||
}
|
||||
|
||||
/* Count cached creds */
|
||||
|
||||
static int traverse_fn_cached_creds(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
|
||||
void *state)
|
||||
{
|
||||
int *cred_count = (int*)state;
|
||||
|
||||
if (strncmp(kbuf.dptr, "CRED/", 5) == 0) {
|
||||
(*cred_count)++;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS wcache_count_cached_creds(struct winbindd_domain *domain, int *count)
|
||||
{
|
||||
struct winbind_cache *cache = get_cache(domain);
|
||||
|
||||
*count = 0;
|
||||
|
||||
if (!cache->tdb) {
|
||||
return NT_STATUS_INTERNAL_DB_ERROR;
|
||||
}
|
||||
|
||||
tdb_traverse(cache->tdb, traverse_fn_cached_creds, (void *)count);
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
struct cred_list {
|
||||
struct cred_list *prev, *next;
|
||||
TDB_DATA key;
|
||||
fstring name;
|
||||
time_t created;
|
||||
};
|
||||
static struct cred_list *wcache_cred_list;
|
||||
|
||||
static int traverse_fn_get_credlist(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf,
|
||||
void *state)
|
||||
{
|
||||
struct cred_list *cred;
|
||||
|
||||
if (strncmp(kbuf.dptr, "CRED/", 5) == 0) {
|
||||
|
||||
cred = SMB_MALLOC_P(struct cred_list);
|
||||
if (cred == NULL) {
|
||||
DEBUG(0,("traverse_fn_remove_first_creds: failed to malloc new entry for list\n"));
|
||||
return -1;
|
||||
}
|
||||
|
||||
ZERO_STRUCTP(cred);
|
||||
|
||||
/* save a copy of the key */
|
||||
|
||||
fstrcpy(cred->name, kbuf.dptr);
|
||||
DLIST_ADD(wcache_cred_list, cred);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
NTSTATUS wcache_remove_oldest_cached_creds(struct winbindd_domain *domain, const DOM_SID *sid)
|
||||
{
|
||||
struct winbind_cache *cache = get_cache(domain);
|
||||
NTSTATUS status;
|
||||
int ret;
|
||||
struct cred_list *cred, *oldest = NULL;
|
||||
|
||||
if (!cache->tdb) {
|
||||
return NT_STATUS_INTERNAL_DB_ERROR;
|
||||
}
|
||||
|
||||
/* we possibly already have an entry */
|
||||
if (sid && NT_STATUS_IS_OK(wcache_cached_creds_exist(domain, sid))) {
|
||||
|
||||
fstring key_str;
|
||||
|
||||
DEBUG(11,("we already have an entry, deleting that\n"));
|
||||
|
||||
fstr_sprintf(key_str, "CRED/%s", sid_string_static(sid));
|
||||
|
||||
tdb_delete(cache->tdb, string_tdb_data(key_str));
|
||||
|
||||
return NT_STATUS_OK;
|
||||
}
|
||||
|
||||
ret = tdb_traverse(cache->tdb, traverse_fn_get_credlist, NULL);
|
||||
if (ret == 0) {
|
||||
return NT_STATUS_OK;
|
||||
} else if (ret == -1) {
|
||||
return NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
}
|
||||
|
||||
ZERO_STRUCTP(oldest);
|
||||
|
||||
for (cred = wcache_cred_list; cred; cred = cred->next) {
|
||||
|
||||
TDB_DATA data;
|
||||
time_t t;
|
||||
|
||||
data = tdb_fetch(cache->tdb, make_tdb_data(cred->name, strlen(cred->name)));
|
||||
if (!data.dptr) {
|
||||
DEBUG(10,("wcache_remove_oldest_cached_creds: entry for [%s] not found\n",
|
||||
cred->name));
|
||||
status = NT_STATUS_OBJECT_NAME_NOT_FOUND;
|
||||
goto done;
|
||||
}
|
||||
|
||||
t = IVAL(data.dptr, 0);
|
||||
SAFE_FREE(data.dptr);
|
||||
|
||||
if (!oldest) {
|
||||
oldest = SMB_MALLOC_P(struct cred_list);
|
||||
if (oldest == NULL) {
|
||||
status = NT_STATUS_NO_MEMORY;
|
||||
goto done;
|
||||
}
|
||||
|
||||
fstrcpy(oldest->name, cred->name);
|
||||
oldest->created = t;
|
||||
continue;
|
||||
}
|
||||
|
||||
if (t < oldest->created) {
|
||||
fstrcpy(oldest->name, cred->name);
|
||||
oldest->created = t;
|
||||
}
|
||||
}
|
||||
|
||||
if (tdb_delete(cache->tdb, string_tdb_data(oldest->name)) == 0) {
|
||||
status = NT_STATUS_OK;
|
||||
} else {
|
||||
status = NT_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
done:
|
||||
SAFE_FREE(wcache_cred_list);
|
||||
SAFE_FREE(oldest);
|
||||
|
||||
return status;
|
||||
}
|
||||
|
||||
/* Change the global online/offline state. */
|
||||
BOOL set_global_winbindd_state_offline(void)
|
||||
{
|
||||
TDB_DATA data;
|
||||
int err;
|
||||
|
||||
DEBUG(10,("set_global_winbindd_state_offline: offline requested.\n"));
|
||||
|
||||
/* Only go offline if someone has created
|
||||
the key "WINBINDD_OFFLINE" in the cache tdb. */
|
||||
|
||||
if (wcache == NULL || wcache->tdb == NULL) {
|
||||
DEBUG(10,("set_global_winbindd_state_offline: wcache not open yet.\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (!lp_winbind_offline_logon()) {
|
||||
DEBUG(10,("set_global_winbindd_state_offline: rejecting.\n"));
|
||||
return False;
|
||||
}
|
||||
|
||||
if (global_winbindd_offline_state) {
|
||||
/* Already offline. */
|
||||
return True;
|
||||
}
|
||||
|
||||
wcache->tdb->ecode = 0;
|
||||
|
||||
data = tdb_fetch_bystring( wcache->tdb, "WINBINDD_OFFLINE" );
|
||||
|
||||
/* As this is a key with no data we don't need to free, we
|
||||
check for existence by looking at tdb_err. */
|
||||
|
||||
err = tdb_error(wcache->tdb);
|
||||
|
||||
if (err == TDB_ERR_NOEXIST) {
|
||||
DEBUG(10,("set_global_winbindd_state_offline: offline state not set.\n"));
|
||||
return False;
|
||||
} else {
|
||||
DEBUG(10,("set_global_winbindd_state_offline: offline state set.\n"));
|
||||
global_winbindd_offline_state = True;
|
||||
return True;
|
||||
}
|
||||
}
|
||||
|
||||
void set_global_winbindd_state_online(void)
|
||||
{
|
||||
DEBUG(10,("set_global_winbindd_state_online: online requested.\n"));
|
||||
|
||||
if (!lp_winbind_offline_logon()) {
|
||||
DEBUG(10,("set_global_winbindd_state_online: rejecting.\n"));
|
||||
return;
|
||||
}
|
||||
|
||||
if (!global_winbindd_offline_state) {
|
||||
/* Already online. */
|
||||
return;
|
||||
}
|
||||
global_winbindd_offline_state = False;
|
||||
|
||||
if (!wcache->tdb) {
|
||||
return;
|
||||
}
|
||||
|
||||
/* Ensure there is no key "WINBINDD_OFFLINE" in the cache tdb. */
|
||||
tdb_delete_bystring(wcache->tdb, "WINBINDD_OFFLINE");
|
||||
}
|
||||
|
||||
/* the cache backend methods are exposed via this structure */
|
||||
struct winbindd_methods cache_methods = {
|
||||
True,
|
||||
query_user_list,
|
||||
enum_dom_groups,
|
||||
enum_local_groups,
|
||||
name_to_sid,
|
||||
sid_to_name,
|
||||
query_user,
|
||||
lookup_usergroups,
|
||||
lookup_useraliases,
|
||||
lookup_groupmem,
|
||||
sequence_number,
|
||||
lockout_policy,
|
||||
password_policy,
|
||||
trusted_domains
|
||||
};
|
||||
|
@ -792,11 +792,11 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
|
||||
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;
|
||||
}
|
||||
}
|
||||
@ -804,6 +804,12 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain,
|
||||
if ((fd == -1)
|
||||
&& !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
source3/nsswitch/winbindd_cred_cache.c
Normal file
270
source3/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
source3/nsswitch/winbindd_creds.c
Normal file
162
source3/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;
|
||||
}
|
||||
|
||||
@ -496,11 +639,79 @@ static BOOL fork_domain_child(struct winbindd_child *child)
|
||||
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))) {
|
||||
if (!NT_STATUS_IS_OK(idmap_sid_to_gid(&group_sid,
|
||||
&group_gid, 0))) {
|
||||
union unid_t id;
|
||||
enum SID_NAME_USE type;
|
||||
|
||||
DEBUG(1, ("could not look up gid for group %s\n",
|
||||
name_list[ent->sam_entry_index].acct_name));
|
||||
DEBUG(10, ("SID %s not in idmap\n",
|
||||
sid_string_static(&group_sid)));
|
||||
|
||||
ent->sam_entry_index++;
|
||||
goto tryagain;
|
||||
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…
Reference in New Issue
Block a user