From: Gerald Carter Date: Fri, 30 Sep 2005 17:13:37 +0000 (+0000) Subject: r10656: BIG merge from trunk. Features not copied over X-Git-Tag: samba-4.0.0alpha6~801^2~9709 X-Git-Url: http://git.samba.org/samba.git/?p=sfrench%2Fsamba-autobuild%2F.git;a=commitdiff_plain;h=54abd2aa66069e6baf7769c496f46d9dba18db39 r10656: BIG merge from trunk. Features not copied over * \PIPE\unixinfo * winbindd's {group,alias}membership new functions * winbindd's lookupsids() functionality * swat (trunk changes to be reverted as per discussion with Deryck) (This used to be commit 939c3cb5d78e3a2236209b296aa8aba8bdce32d3) --- diff --git a/examples/LDAP/samba.schema b/examples/LDAP/samba.schema index 2205c173095..daf4588ead5 100644 --- a/examples/LDAP/samba.schema +++ b/examples/LDAP/samba.schema @@ -389,16 +389,68 @@ attributetype ( 1.3.6.1.4.1.7165.2.1.53 NAME 'sambaTrustFlags' EQUALITY caseIgnoreIA5Match SYNTAX 1.3.6.1.4.1.1466.115.121.1.26 ) -attributetype ( 1.3.6.1.4.1.7165.2.1.56 NAME 'sambaAccountPolicyName' - DESC 'Account Policy Name' - EQUALITY caseIgnoreMatch - SYNTAX 1.3.6.1.4.1.1466.115.121.1.15{255} SINGLE-VALUE ) +# "min password length" +attributetype ( 1.3.6.1.4.1.7165.2.1.58 NAME 'sambaMinPwdLength' + DESC 'Minimal password length (default: 5)' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) -attributetype ( 1.3.6.1.4.1.7165.2.1.57 NAME 'sambaAccountPolicyValue' - DESC 'Account Policy Value' +# "password history" +attributetype ( 1.3.6.1.4.1.7165.2.1.59 NAME 'sambaPwdHistoryLength' + DESC 'Length of Password History Entries (default: 0 => off)' EQUALITY integerMatch SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) +# "user must logon to change password" +attributetype ( 1.3.6.1.4.1.7165.2.1.60 NAME 'sambaLogonToChgPwd' + DESC 'Force Users to logon for password change (default: 0 => off, 2 => on)' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +# "maximum password age" +attributetype ( 1.3.6.1.4.1.7165.2.1.61 NAME 'sambaMaxPwdAge' + DESC 'Maximum password age, in seconds (default: -1 => never expire passwords)' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +# "minimum password age" +attributetype ( 1.3.6.1.4.1.7165.2.1.62 NAME 'sambaMinPwdAge' + DESC 'Minimum password age, in seconds (default: 0 => allow immediate password change)' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +# "lockout duration" +attributetype ( 1.3.6.1.4.1.7165.2.1.63 NAME 'sambaLockoutDuration' + DESC 'Lockout duration in minutes (default: 30, -1 => forever)' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +# "reset count minutes" +attributetype ( 1.3.6.1.4.1.7165.2.1.64 NAME 'sambaLockoutObservationWindow' + DESC 'Reset time after lockout in minutes (default: 30)' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +# "bad lockout attempt" +attributetype ( 1.3.6.1.4.1.7165.2.1.65 NAME 'sambaLockoutThreshold' + DESC 'Lockout users after bad logon attempts (default: 0 => off)' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +# "disconnect time" +attributetype ( 1.3.6.1.4.1.7165.2.1.66 NAME 'sambaForceLogoff' + DESC 'Disconnect Users outside logon hours (default: -1 => off, 0 => on)' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + +# "refuse machine password change" +attributetype ( 1.3.6.1.4.1.7165.2.1.67 NAME 'sambaRefuseMachinePwdChange' + DESC 'Allow Machine Password changes (default: 0 => off)' + EQUALITY integerMatch + SYNTAX 1.3.6.1.4.1.1466.115.121.1.27 SINGLE-VALUE ) + + + ####################################################################### ## objectClasses used by Samba 3.0 schema ## @@ -448,7 +500,11 @@ objectclass ( 1.3.6.1.4.1.7165.2.2.5 NAME 'sambaDomain' SUP top STRUCTURAL MUST ( sambaDomainName $ sambaSID ) MAY ( sambaNextRid $ sambaNextGroupRid $ sambaNextUserRid $ - sambaAlgorithmicRidBase ) ) + sambaAlgorithmicRidBase $ + sambaMinPwdLength $ sambaPwdHistoryLength $ sambaLogonToChgPwd $ + sambaMaxPwdAge $ sambaMinPwdAge $ + sambaLockoutDuration $ sambaLockoutObservationWindow $ sambaLockoutThreshold $ + sambaForceLogoff $ sambaRefuseMachinePwdChange )) ## ## used for idmap_ldap module @@ -488,9 +544,3 @@ objectclass ( 1.3.6.1.4.1.7165.2.2.12 NAME 'sambaConfigOption' SUP top STRUCTURA ## DESC 'Samba Privilege' ## MUST ( sambaSID ) ## MAY ( sambaPrivilegeList ) ) - -objectclass ( 1.3.6.1.4.1.7165.2.2.15 NAME 'sambaAccountPolicy' SUP top STRUCTURAL - DESC 'Samba Account Policy' - MUST ( sambaAccountPolicyName $ sambaAccountPolicyValue ) - MAY ( description ) ) - diff --git a/source3/Makefile.in b/source3/Makefile.in index 95457758a65..07c348bd84e 100644 --- a/source3/Makefile.in +++ b/source3/Makefile.in @@ -63,6 +63,7 @@ RPCLIBDIR = $(LIBDIR)/rpc IDMAPLIBDIR = $(LIBDIR)/idmap CHARSETLIBDIR = $(LIBDIR)/charset AUTHLIBDIR = $(LIBDIR)/auth +CONFIGLIBDIR = $(LIBDIR)/config CONFIGDIR = @configdir@ VARDIR = @localstatedir@ MANDIR = @mandir@ @@ -101,8 +102,7 @@ LIBSMBSHAREMODES=bin/libsmbsharemodes.a @LIBSMBSHAREMODES_SHARED@ LIBSMBSHAREMODES_MAJOR=0 LIBSMBSHAREMODES_MINOR=1 - -FLAGS1 = $(CFLAGS) @FLAGS1@ -Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx @SMBWRAP_INC@ -I. $(CPPFLAGS) -I$(srcdir) -I$(srcdir)/tdb +FLAGS1 = $(CFLAGS) @FLAGS1@ -Iinclude -I$(srcdir)/include -I$(srcdir)/ubiqx -I$(srcdir)/tdb @SMBWRAP_INC@ -I. $(CPPFLAGS) -I$(srcdir) FLAGS2 = FLAGS3 = FLAGS4 = @@ -199,12 +199,12 @@ LIB_OBJ = $(VERSION_OBJ) lib/charcnv.o lib/debug.o lib/fault.o \ lib/talloc.o lib/substitute.o lib/fsusage.o \ lib/ms_fnmatch.o lib/select.o lib/messages.o \ lib/tallocmsg.o lib/dmallocmsg.o libsmb/smb_signing.o \ - lib/md5.o lib/hmacmd5.o lib/iconv.o \ + lib/md5.o lib/hmacmd5.o lib/arc4.o lib/iconv.o \ nsswitch/wb_client.o $(WBCOMMON_OBJ) \ - lib/pam_errors.o intl/lang_tdb.o lib/account_pol.o \ + 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/privileges.o lib/secdesc.o lib/secace.o lib/secacl.o @SOCKWRAP@ + lib/secdesc.o lib/secace.o lib/secacl.o @SOCKWRAP@ LIB_DUMMY_OBJ = lib/dummysmbd.o lib/dummyroot.o LIB_NONSMBD_OBJ = $(LIB_OBJ) $(LIB_DUMMY_OBJ) @@ -256,13 +256,13 @@ LIBMSRPC_OBJ = rpc_client/cli_lsarpc.o rpc_client/cli_samr.o \ rpc_client/cli_reg.o $(RPC_CLIENT_OBJ) \ rpc_client/cli_spoolss.o rpc_client/cli_spoolss_notify.o \ rpc_client/cli_ds.o rpc_client/cli_echo.o \ - rpc_client/cli_shutdown.o rpc_client/cli_svcctl.o + rpc_client/cli_shutdown.o rpc_client/cli_svcctl.o REGOBJS_OBJ = registry/reg_objects.o REGISTRY_OBJ = registry/reg_frontend.o registry/reg_cachehook.o registry/reg_printing.o \ registry/reg_db.o registry/reg_eventlog.o registry/reg_shares.o \ - registry/reg_util.o registry/reg_dynamic.o + registry/reg_util.o registry/reg_dynamic.o registry/reg_perfcount.o RPC_LSA_OBJ = rpc_server/srv_lsa.o rpc_server/srv_lsa_nt.o @@ -282,7 +282,10 @@ RPC_SVC_OBJ = rpc_server/srv_srvsvc.o rpc_server/srv_srvsvc_nt.o RPC_WKS_OBJ = rpc_server/srv_wkssvc.o rpc_server/srv_wkssvc_nt.o RPC_SVCCTL_OBJ = rpc_server/srv_svcctl.o rpc_server/srv_svcctl_nt.o \ - services/svc_spoolss.o services/svc_rcinit.o services/services_db.o + services/svc_spoolss.o services/svc_rcinit.o services/services_db.o \ + services/svc_netlogon.o services/svc_winreg.o + +RPC_NTSVCS_OBJ = rpc_server/srv_ntsvcs.o rpc_server/srv_ntsvcs_nt.o RPC_DFS_OBJ = rpc_server/srv_dfs.o rpc_server/srv_dfs_nt.o @@ -308,7 +311,8 @@ RPC_PARSE_OBJ = rpc_parse/parse_lsa.o rpc_parse/parse_net.o \ rpc_parse/parse_spoolss.o rpc_parse/parse_dfs.o \ rpc_parse/parse_echo.o rpc_parse/parse_shutdown.o \ rpc_parse/parse_svcctl.o \ - rpc_parse/parse_eventlog.o rpc_parse/parse_buffer.o $(REGOBJS_OBJ) + rpc_parse/parse_eventlog.o rpc_parse/parse_buffer.o \ + rpc_parse/parse_ntsvcs.o $(REGOBJS_OBJ) RPC_CLIENT_OBJ = rpc_client/cli_pipe.o @@ -320,7 +324,7 @@ PASSDB_OBJ = $(PASSDB_GET_SET_OBJ) passdb/passdb.o passdb/pdb_interface.o \ passdb/util_sam_sid.o passdb/pdb_compat.o \ passdb/lookup_sid.o \ passdb/login_cache.o @PDB_STATIC@ passdb/pdb_sql.o \ - lib/system_smbd.o + lib/system_smbd.o lib/account_pol.o lib/privileges.o XML_OBJ = passdb/pdb_xml.o MYSQL_OBJ = passdb/pdb_mysql.o @@ -414,8 +418,7 @@ PRINTING_OBJ = printing/pcap.o printing/print_svid.o printing/print_aix.o \ printing/print_iprint.o PRINTBASE_OBJ = printing/notify.o printing/printing_db.o - -PRINTBACKEND_OBJ = printing/printing.o printing/nt_printing.o $(PRINTBASE_OBJ) +PRINTBACKEND_OBJ = printing/printing.o printing/nt_printing.o $(PRINTBASE_OBJ) SMBD_OBJ = $(SMBD_OBJ_BASE) $(SMBD_OBJ_MAIN) NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \ @@ -432,7 +435,7 @@ NMBD_OBJ1 = nmbd/asyncdns.o nmbd/nmbd.o nmbd/nmbd_become_dmb.o \ nmbd/nmbd_workgroupdb.o nmbd/nmbd_synclists.o NMBD_OBJ = $(NMBD_OBJ1) $(PARAM_OBJ) $(LIBSMB_OBJ) $(KRBCLIENT_OBJ) $(UBIQX_OBJ) \ - $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) + $(PROFILE_OBJ) $(LIB_NONSMBD_OBJ) $(SECRETS_OBJ) $(POPT_LIB_OBJ) WREPL_OBJ1 = wrepld/server.o wrepld/process.o wrepld/parser.o wrepld/socket.o \ wrepld/partners.o @@ -487,7 +490,8 @@ RPCCLIENT_OBJ1 = rpcclient/rpcclient.o rpcclient/cmd_lsarpc.o \ rpcclient/cmd_netlogon.o rpcclient/cmd_srvsvc.o \ rpcclient/cmd_dfs.o rpcclient/cmd_reg.o \ rpcclient/display_sec.o rpcclient/cmd_ds.o \ - rpcclient/cmd_echo.o rpcclient/cmd_shutdown.o + rpcclient/cmd_echo.o rpcclient/cmd_shutdown.o \ + rpcclient/cmd_test.o RPCCLIENT_OBJ = $(RPCCLIENT_OBJ1) \ $(PARAM_OBJ) $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) \ @@ -521,11 +525,6 @@ LIBSMBCLIENT_OBJ = libsmb/libsmbclient.o libsmb/libsmb_compat.o \ LIBSMBSHAREMODES_OBJ = libsmb/smb_share_modes.o tdb/tdb.o tdb/spinlock.o -CAC_OBJ = $(LIBSMBCLIENT_OBJ) \ - libmsrpc/libmsrpc.o libmsrpc/libmsrpc_internal.o \ - libmsrpc/cac_lsarpc.o libmsrpc/cac_winreg.o libmsrpc/cac_samr.o \ - libmsrpc/cac_svcctl.o - # This shared library is intended for linking with unit test programs # to test Samba internals. It's called libbigballofmud.so to # discourage casual usage. @@ -561,7 +560,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) $(PRINTERDB_OBJ) $(REGFIO_OBJ) + $(AFS_OBJ) $(AFS_SETTOKEN_OBJ) $(REGFIO_OBJ) CUPS_OBJ = client/smbspool.o $(PARAM_OBJ) $(LIBSMB_OBJ) \ $(LIB_NONSMBD_OBJ) $(KRBCLIENT_OBJ) $(SECRETS_OBJ) @@ -644,7 +643,8 @@ PROTO_OBJ = $(SMBD_OBJ_MAIN) \ $(RPC_LSA_OBJ) $(RPC_NETLOG_OBJ) $(RPC_SAMR_OBJ) $(RPC_REG_OBJ) $(RPC_LSA_DS_OBJ) \ $(RPC_SVC_OBJ) $(RPC_WKS_OBJ) $(RPC_DFS_OBJ) $(RPC_SPOOLSS_OBJ) \ $(RPC_ECHO_OBJ) $(RPC_SVCCTL_OBJ) $(RPC_EVENTLOG_OBJ) $(SMBLDAP_OBJ) \ - $(IDMAP_OBJ) libsmb/spnego.o $(PASSCHANGE_OBJ) + $(IDMAP_OBJ) libsmb/spnego.o $(PASSCHANGE_OBJ) \ + $(RPC_NTSVCS_OBJ) WINBIND_WINS_NSS_OBJ = nsswitch/wins.o $(PARAM_OBJ) \ $(LIBSMB_OBJ) $(LIB_NONSMBD_OBJ) $(NSSWINS_OBJ) $(KRBCLIENT_OBJ) @@ -655,8 +655,6 @@ PICOBJS = $(SMBWRAPPER_OBJ:.o=.@PICSUFFIX@) LIBSMBCLIENT_PICOBJS = $(LIBSMBCLIENT_OBJ:.o=.@PICSUFFIX@) LIBSMBSHAREMODES_PICOBJS = $(LIBSMBSHAREMODES_OBJ:.o=.@PICSUFFIX@) -CAC_PICOBJS = $(CAC_OBJ:.o=.@PICSUFFIX@) - PAM_SMBPASS_OBJ_0 = pam_smbpass/pam_smb_auth.o pam_smbpass/pam_smb_passwd.o \ pam_smbpass/pam_smb_acct.o pam_smbpass/support.o \ $(PARAM_OBJ) $(LIB_NONSMBD_OBJ) $(PASSDB_OBJ) $(GROUPDB_OBJ) \ @@ -715,7 +713,7 @@ 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) \ - $(SMBLDAP_OBJ) $(DOSERR_OBJ) + $(SMBLDAP_OBJ) $(DOSERR_OBJ) rpc_parse/parse_net.o ###################################################################### # now the rules... @@ -760,9 +758,7 @@ wins : SHOWFLAGS @WINBIND_WINS_NSS@ modules: SHOWFLAGS proto_exists $(MODULES) -cac: SHOWFLAGS bin/libmsrpc.@SHLIBEXT@ bin/libmsrpc.a - -everything: all libsmbclient debug2html smbfilter talloctort modules torture cac \ +everything: all libsmbclient debug2html smbfilter talloctort modules torture \ $(EVERYTHING_PROGS) .SUFFIXES: @@ -1045,16 +1041,6 @@ bin/libsmbsharemodes.a: $(LIBSMBSHAREMODES_PICOBJS) @echo Linking libsmbsharemodes non-shared library $@ @-$(AR) -rc $@ $(LIBSMBSHAREMODES_PICOBJS) -bin/libmsrpc.@SHLIBEXT@: $(CAC_PICOBJS) - @echo Linking libmsrpc shared library $@ - @$(SHLD) $(LDSHFLAGS) -o $@ $(CAC_PICOBJS) $(LDFLAGS) $(LIBS) \ - @SONAMEFLAG@`basename $@` - -bin/libmsrpc.a: $(CAC_PICOBJS) - @echo Linking libmsrpc non-shared library $@ - @-$(AR) -rc $@ $(CAC_PICOBJS) - - # This is probably wrong for anything other than the GNU linker. bin/libbigballofmud.@SHLIBEXT@: $(LIBBIGBALLOFMUD_PICOBJS) @echo Linking bigballofmud shared library $@ @@ -1091,6 +1077,11 @@ bin/librpc_svcctl.@SHLIBEXT@: $(RPC_SVCCTL_OBJ) @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_SVCCTL_OBJ) -lc \ @SONAMEFLAG@`basename $@` +bin/librpc_ntsvcs.@SHLIBEXT@: $(RPC_NTSVCS_OBJ) + @echo "Linking $@" + @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_NTSVCS_OBJ) -lc \ + @SONAMEFLAG@`basename $@` + bin/librpc_wkssvc.@SHLIBEXT@: $(RPC_WKS_OBJ) @echo "Linking $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(RPC_WKS_OBJ) -lc \ @@ -1328,6 +1319,9 @@ bin/pam_smbpass.@SHLIBEXT@: $(PAM_SMBPASS_PICOOBJ) @echo "Linking shared library $@" @$(SHLD) $(LDSHFLAGS) -o $@ $(PAM_SMBPASS_PICOOBJ) -lpam $(DYNEXP) $(LIBS) -lc $(LDAP_LIBS) $(KRB5LIBS) +bin/libmsrpc.a: $(LIBMSRPC_PICOBJ) + @-$(AR) -rc $@ $(LIBMSRPC_PICOBJ) + bin/tdbbackup@EXEEXT@: $(TDBBACKUP_OBJ) bin/.dummy @echo Linking $@ @$(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(LDFLAGS) $(DYNEXP) $(LIBS) $(TDBBACKUP_OBJ) @SOCKWRAP@ @@ -1346,6 +1340,9 @@ bin/t_strcmp@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_strcmp.o bin/t_strstr@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_strstr.o $(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(DYNEXP) $(LIBS) torture/t_strstr.o -L ./bin -lbigballofmud +bin/t_strappend@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_strappend.o + $(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(DYNEXP) $(LIBS) torture/t_strappend.o -L ./bin -lbigballofmud + bin/t_stringoverflow@EXEEXT@: bin/libbigballofmud.@SHLIBEXT@ torture/t_stringoverflow.o $(CC) $(FLAGS) @PIE_LDFLAGS@ -o $@ $(DYNEXP) torture/t_stringoverflow.o -L./bin -lbigballofmud @@ -1634,7 +1631,7 @@ Makefile: $(srcdir)/Makefile.in config.status # These are called by the test suite and need to be built before # running it. For the time being we don't build all of BIN_PROGS, # because they're not all needed. -check-programs: bin/t_strcmp bin/t_strstr bin/t_push_ucs2 bin/smbcontrol bin/t_snprintf +# check-programs: bin/t_strcmp bin/t_strstr bin/t_push_ucs2 bin/smbcontrol bin/t_snprintf bin/t_asn1 #test: all # @if test -z "$(SMB4TORTURE)"; then \ diff --git a/source3/auth/auth.c b/source3/auth/auth.c index 9886526cf96..92c90b62410 100644 --- a/source3/auth/auth.c +++ b/source3/auth/auth.c @@ -235,7 +235,7 @@ static NTSTATUS check_ntlm_password(const struct auth_context *auth_context, #ifdef DEBUG_PASSWORD DEBUG(100, ("user_info has passwords of length %d and %d\n", - user_info->lm_resp.length, user_info->nt_resp.length)); + (int)user_info->lm_resp.length, (int)user_info->nt_resp.length)); DEBUG(100, ("lm:\n")); dump_data(100, user_info->lm_resp.data, user_info->lm_resp.length); DEBUG(100, ("nt:\n")); diff --git a/source3/auth/auth_domain.c b/source3/auth/auth_domain.c index cdf87adebb9..4abc6c66560 100644 --- a/source3/auth/auth_domain.c +++ b/source3/auth/auth_domain.c @@ -40,15 +40,17 @@ extern BOOL global_machine_password_needs_changing; * **/ -static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, - const char *domain, const char *dc_name, - struct in_addr dc_ip, - const char *setup_creds_as, - uint16 sec_chan, - const unsigned char *trust_passwd, - BOOL *retry) +static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, + const char *domain, + const char *dc_name, + struct in_addr dc_ip, + struct rpc_pipe_client **pipe_ret, + BOOL *retry) { NTSTATUS result; + struct rpc_pipe_client *netlogon_pipe = NULL; + + *pipe_ret = NULL; /* TODO: Send a SAMLOGON request to determine whether this is a valid logonserver. We can avoid a 30-second timeout if the DC is down @@ -64,8 +66,9 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, * ACCESS_DENIED errors if 2 auths are done from the same machine. JRA. */ - if (!grab_server_mutex(dc_name)) + if (!grab_server_mutex(dc_name)) { return NT_STATUS_NO_LOGON_SERVERS; + } /* Attempt connection */ *retry = True; @@ -95,36 +98,65 @@ static NTSTATUS connect_to_domain_password_server(struct cli_state **cli, * into account also. This patch from "Bjart Kvarme" . */ - if(cli_nt_session_open(*cli, PI_NETLOGON) == False) { + /* open the netlogon pipe. */ + if (lp_client_schannel()) { + /* We also setup the creds chain in the open_schannel call. */ + netlogon_pipe = cli_rpc_pipe_open_schannel(*cli, PI_NETLOGON, + PIPE_AUTH_LEVEL_PRIVACY, domain, &result); + } else { + netlogon_pipe = cli_rpc_pipe_open_noauth(*cli, PI_NETLOGON, &result); + } + + if(!netlogon_pipe) { DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \ -machine %s. Error was : %s.\n", dc_name, cli_errstr(*cli))); - cli_nt_session_close(*cli); - cli_ulogoff(*cli); +machine %s. Error was : %s.\n", dc_name, nt_errstr(result))); cli_shutdown(*cli); release_server_mutex(); - return NT_STATUS_NO_LOGON_SERVERS; + return result; } - fstr_sprintf((*cli)->mach_acct, "%s$", setup_creds_as); - - /* This must be the remote domain (not ours) for schannel */ - - fstrcpy( (*cli)->domain, domain ); + if (!lp_client_schannel()) { + /* We need to set up a creds chain on an unauthenticated netlogon pipe. */ + uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint32 sec_chan_type = 0; + char machine_pwd[16]; + + if (!get_trust_pw(domain, machine_pwd, &sec_chan_type)) { + DEBUG(0, ("connect_to_domain_password_server: could not fetch " + "trust account password for domain '%s'\n", + domain)); + cli_shutdown(*cli); + release_server_mutex(); + return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } - result = cli_nt_establish_netlogon(*cli, sec_chan, trust_passwd); + result = rpccli_netlogon_setup_creds(netlogon_pipe, + dc_name, + domain, + global_myname(), + machine_pwd, + sec_chan_type, + &neg_flags); + + if (!NT_STATUS_IS_OK(result)) { + cli_shutdown(*cli); + release_server_mutex(); + return result; + } + } - if (!NT_STATUS_IS_OK(result)) { - DEBUG(0,("connect_to_domain_password_server: unable to setup the NETLOGON credentials to machine \ -%s. Error was : %s.\n", dc_name, nt_errstr(result))); - cli_nt_session_close(*cli); - cli_ulogoff(*cli); + if(!netlogon_pipe) { + DEBUG(0,("connect_to_domain_password_server: unable to open the domain client session to \ +machine %s. Error was : %s.\n", dc_name, cli_errstr(*cli))); cli_shutdown(*cli); release_server_mutex(); - return result; + return NT_STATUS_NO_LOGON_SERVERS; } /* We exit here with the mutex *locked*. JRA */ + *pipe_ret = netlogon_pipe; + return NT_STATUS_OK; } @@ -135,18 +167,17 @@ machine %s. Error was : %s.\n", dc_name, cli_errstr(*cli))); ************************************************************************/ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, - const auth_usersupplied_info *user_info, - const char *domain, - uchar chal[8], - auth_serversupplied_info **server_info, - const char *dc_name, struct in_addr dc_ip, - const char *setup_creds_as, - uint16 sec_chan, - unsigned char trust_passwd[16], - time_t last_change_time) + const auth_usersupplied_info *user_info, + const char *domain, + uchar chal[8], + auth_serversupplied_info **server_info, + const char *dc_name, + struct in_addr dc_ip) + { NET_USER_INFO_3 info3; struct cli_state *cli = NULL; + struct rpc_pipe_client *netlogon_pipe = NULL; NTSTATUS nt_status = NT_STATUS_NO_LOGON_SERVERS; int i; BOOL retry = True; @@ -162,8 +193,12 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, /* rety loop for robustness */ for (i = 0; !NT_STATUS_IS_OK(nt_status) && retry && (i < 3); i++) { - nt_status = connect_to_domain_password_server(&cli, domain, dc_name, - dc_ip, setup_creds_as, sec_chan, trust_passwd, &retry); + nt_status = connect_to_domain_password_server(&cli, + domain, + dc_name, + dc_ip, + &netlogon_pipe, + &retry); } if ( !NT_STATUS_IS_OK(nt_status) ) { @@ -181,13 +216,19 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, * in the info3 structure. */ - nt_status = cli_netlogon_sam_network_logon(cli, mem_ctx, - NULL, user_info->smb_name.str, user_info->domain.str, - user_info->wksta_name.str, chal, user_info->lm_resp, - user_info->nt_resp, &info3); - - /* let go as soon as possible so we avoid any potential deadlocks - with winbind lookup up users or groups */ + nt_status = rpccli_netlogon_sam_network_logon(netlogon_pipe, + mem_ctx, + 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 */ + chal, /* 8 byte challenge. */ + user_info->lm_resp, /* lanman 24 byte response */ + user_info->nt_resp, /* nt 24 byte response */ + &info3); /* info3 out */ + + /* Let go as soon as possible so we avoid any potential deadlocks + with winbind lookup up users or groups. */ release_server_mutex(); @@ -195,7 +236,7 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, 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, cli->srv_name_slash, + user_info->domain.str, dc_name, nt_errstr(nt_status))); /* map to something more useful */ @@ -203,32 +244,18 @@ static NTSTATUS domain_client_validate(TALLOC_CTX *mem_ctx, nt_status = NT_STATUS_NO_LOGON_SERVERS; } } else { - nt_status = make_server_info_info3(mem_ctx, user_info->internal_username.str, - user_info->smb_name.str, domain, server_info, &info3); + nt_status = make_server_info_info3(mem_ctx, + user_info->internal_username.str, + user_info->smb_name.str, + domain, + server_info, + &info3); } -#if 0 - /* - * We don't actually need to do this - plus it fails currently with - * NT_STATUS_INVALID_INFO_CLASS - we need to know *exactly* what to - * send here. JRA. - */ - - if (NT_STATUS_IS_OK(status)) { - if(cli_nt_logoff(&cli, &ctr) == False) { - DEBUG(0,("domain_client_validate: unable to log off user %s in domain \ -%s to Domain controller %s. Error was %s.\n", user, domain, dc_name, cli_errstr(&cli))); - nt_status = NT_STATUS_LOGON_FAILURE; - } - } -#endif /* 0 */ - /* Note - once the cli stream is shutdown the mem_ctx used to allocate the other_sids and gids structures has been deleted - so these pointers are no longer valid..... */ - cli_nt_session_close(cli); - cli_ulogoff(cli); cli_shutdown(cli); return nt_status; } @@ -244,10 +271,7 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context, auth_serversupplied_info **server_info) { NTSTATUS nt_status = NT_STATUS_LOGON_FAILURE; - unsigned char trust_passwd[16]; - time_t last_change_time; const char *domain = lp_workgroup(); - uint32 sec_channel_type = 0; fstring dc_name; struct in_addr dc_ip; @@ -273,26 +297,6 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context, return NT_STATUS_NOT_IMPLEMENTED; } - /* - * Get the machine account password for our primary domain - * No need to become_root() as secrets_init() is done at startup. - */ - - if (!secrets_fetch_trust_account_password(domain, trust_passwd, &last_change_time, &sec_channel_type)) - { - DEBUG(0, ("check_ntdomain_security: could not fetch trust account password for domain '%s'\n", domain)); - return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - } - - /* Test if machine password has expired and needs to be changed */ - if (lp_machine_password_timeout()) { - if (last_change_time > 0 && - time(NULL) > (last_change_time + - lp_machine_password_timeout())) { - global_machine_password_needs_changing = True; - } - } - /* we need our DC to send the net_sam_logon() request to */ if ( !get_dc_name(domain, NULL, dc_name, &dc_ip) ) { @@ -301,9 +305,13 @@ static NTSTATUS check_ntdomain_security(const struct auth_context *auth_context, return NT_STATUS_NO_LOGON_SERVERS; } - nt_status = domain_client_validate(mem_ctx, user_info, domain, - (uchar *)auth_context->challenge.data, server_info, dc_name, dc_ip, - global_myname(), sec_channel_type,trust_passwd, last_change_time); + nt_status = domain_client_validate(mem_ctx, + user_info, + domain, + (uchar *)auth_context->challenge.data, + server_info, + dc_name, + dc_ip); return nt_status; } @@ -357,7 +365,7 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte /* No point is bothering if this is not a trusted domain. This return makes "map to guest = bad user" work again. The logic is that if we know nothing about the domain, that - user is known to us and does not exist */ + user is not known to us and does not exist */ if ( !is_trusted_domain( user_info->domain.str ) ) return NT_STATUS_NOT_IMPLEMENTED; @@ -367,8 +375,8 @@ 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, &sid, &last_change_time)) - { + if (!secrets_fetch_trusted_domain_password(user_info->domain.str, &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)); return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; } @@ -396,9 +404,13 @@ static NTSTATUS check_trustdomain_security(const struct auth_context *auth_conte return NT_STATUS_NO_LOGON_SERVERS; } - nt_status = domain_client_validate(mem_ctx, user_info, user_info->domain.str, - (uchar *)auth_context->challenge.data, server_info, dc_name, dc_ip, - lp_workgroup(), SEC_CHAN_DOMAIN, trust_md4_password, last_change_time); + nt_status = domain_client_validate(mem_ctx, + user_info, + user_info->domain.str, + (uchar *)auth_context->challenge.data, + server_info, + dc_name, + dc_ip); return nt_status; } diff --git a/source3/auth/auth_ntlmssp.c b/source3/auth/auth_ntlmssp.c index 11d9aa09c4c..738af73f496 100644 --- a/source3/auth/auth_ntlmssp.c +++ b/source3/auth/auth_ntlmssp.c @@ -114,13 +114,15 @@ static NTSTATUS auth_ntlmssp_check_password(struct ntlmssp_state *ntlmssp_state, return nt_status; } if (auth_ntlmssp_state->server_info->user_session_key.length) { - DEBUG(10, ("Got NT session key of length %u\n", 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)); *user_session_key = data_blob_talloc(auth_ntlmssp_state->mem_ctx, auth_ntlmssp_state->server_info->user_session_key.data, auth_ntlmssp_state->server_info->user_session_key.length); } if (auth_ntlmssp_state->server_info->lm_session_key.length) { - DEBUG(10, ("Got LM session key of length %u\n", auth_ntlmssp_state->server_info->lm_session_key.length)); + DEBUG(10, ("Got LM session key of length %u\n", + (unsigned int)auth_ntlmssp_state->server_info->lm_session_key.length)); *lm_session_key = data_blob_talloc(auth_ntlmssp_state->mem_ctx, auth_ntlmssp_state->server_info->lm_session_key.data, auth_ntlmssp_state->server_info->lm_session_key.length); diff --git a/source3/auth/auth_util.c b/source3/auth/auth_util.c index 6624631b53d..194a1ad532d 100644 --- a/source3/auth/auth_util.c +++ b/source3/auth/auth_util.c @@ -372,7 +372,7 @@ BOOL make_user_info_for_reply(auth_usersupplied_info **user_info, unsigned char local_lm_response[24]; #ifdef DEBUG_PASSWORD - DEBUG(10,("Unencrypted password (len %d):\n",plaintext_password.length)); + DEBUG(10,("Unencrypted password (len %d):\n",(int)plaintext_password.length)); dump_data(100, plaintext_password.data, plaintext_password.length); #endif @@ -640,6 +640,44 @@ NT_USER_TOKEN *create_nt_token(uid_t uid, gid_t gid, int ngroups, gid_t *groups, return token; } +/****************************************************************************** + Create a token for the root user to be used internally by smbd. + This is similar to running under the context of the LOCAL_SYSTEM account + in Windows. This is a read-only token. Do not modify it or free() it. + Create a copy if your need to change it. +******************************************************************************/ + +NT_USER_TOKEN *get_root_nt_token( void ) +{ + static NT_USER_TOKEN *token = NULL; + DOM_SID u_sid, g_sid; + DOM_SID g_sids[1]; + struct passwd *pw; + NTSTATUS result; + + if ( token ) + return token; + + if ( !(pw = getpwnam( "root" )) ) { + DEBUG(0,("create_root_nt_token: getpwnam\"root\") failed!\n")); + return NULL; + } + + /* get the user and primary group SIDs; although the + BUILTIN\Administrators SId is really the one that matters here */ + + if ( !NT_STATUS_IS_OK(uid_to_sid(&u_sid, pw->pw_uid)) ) + return NULL; + if ( !NT_STATUS_IS_OK(gid_to_sid(&g_sid, pw->pw_gid)) ) + return NULL; + + sid_copy( &g_sids[0], &global_sid_Builtin_Administrators ); + + result = create_nt_user_token( &u_sid, &g_sid, 1, g_sids, False, &token); + + return NT_STATUS_IS_OK(result) ? token : NULL; +} + /****************************************************************************** * this function returns the groups (SIDs) of the local SAM the user is in. * If this samba server is a DC of the domain the user belongs to, it returns @@ -831,6 +869,61 @@ NTSTATUS make_server_info_sam(auth_serversupplied_info **server_info, return nt_status; } +/*************************************************************************** + Make (and fill) a user_info struct from a Kerberos PAC logon_info by conversion + to a SAM_ACCOUNT +***************************************************************************/ + +NTSTATUS make_server_info_pac(auth_serversupplied_info **server_info, + char *unix_username, + struct passwd *pwd, + PAC_LOGON_INFO *logon_info) +{ + NTSTATUS nt_status; + SAM_ACCOUNT *sampass = NULL; + DOM_SID user_sid, group_sid; + fstring dom_name; + + if (!NT_STATUS_IS_OK(nt_status = pdb_init_sam_pw(&sampass, pwd))) { + return nt_status; + } + if (!NT_STATUS_IS_OK(nt_status = make_server_info(server_info))) { + return nt_status; + } + + /* only copy user_sid, group_sid and domain name out of the PAC for + * now, we will benefit from more later - Guenther */ + + sid_copy(&user_sid, &logon_info->info3.dom_sid.sid); + sid_append_rid(&user_sid, logon_info->info3.user_rid); + pdb_set_user_sid(sampass, &user_sid, PDB_SET); + + sid_copy(&group_sid, &logon_info->info3.dom_sid.sid); + sid_append_rid(&group_sid, logon_info->info3.group_rid); + pdb_set_group_sid(sampass, &group_sid, PDB_SET); + + unistr2_to_ascii(dom_name, &logon_info->info3.uni_logon_dom, -1); + pdb_set_domain(sampass, dom_name, PDB_SET); + + pdb_set_logon_count(sampass, logon_info->info3.logon_count, PDB_SET); + + (*server_info)->sam_account = sampass; + + if (!NT_STATUS_IS_OK(nt_status = add_user_groups(server_info, unix_username, + sampass, pwd->pw_uid, pwd->pw_gid))) + { + return nt_status; + } + + (*server_info)->unix_name = smb_xstrdup(unix_username); + + (*server_info)->sam_fill_level = SAM_FILL_ALL; + (*server_info)->uid = pwd->pw_uid; + (*server_info)->gid = pwd->pw_gid; + return nt_status; +} + + /*************************************************************************** Make (and fill) a user_info struct from a 'struct passwd' by conversion to a SAM_ACCOUNT diff --git a/source3/auth/auth_winbind.c b/source3/auth/auth_winbind.c index 3a81cba626d..0c263b6ab31 100644 --- a/source3/auth/auth_winbind.c +++ b/source3/auth/auth_winbind.c @@ -38,7 +38,7 @@ static NTSTATUS get_info3_from_ndr(TALLOC_CTX *mem_ctx, struct winbindd_response } prs_copy_data_in(&ps, (char *)info3_ndr, len); prs_set_offset(&ps,0); - if (!net_io_user_info3("", info3, &ps, 1, 3)) { + if (!net_io_user_info3("", info3, &ps, 1, 3, False)) { DEBUG(2, ("get_info3_from_ndr: could not parse info3 struct!\n")); return NT_STATUS_UNSUCCESSFUL; } diff --git a/source3/client/mount.cifs.c b/source3/client/mount.cifs.c index a6136a9e2c2..5750deb31ca 100755 --- a/source3/client/mount.cifs.c +++ b/source3/client/mount.cifs.c @@ -39,7 +39,7 @@ #include #define MOUNT_CIFS_VERSION_MAJOR "1" -#define MOUNT_CIFS_VERSION_MINOR "9" +#define MOUNT_CIFS_VERSION_MINOR "8" #ifndef MOUNT_CIFS_VENDOR_SUFFIX #define MOUNT_CIFS_VENDOR_SUFFIX "" @@ -127,10 +127,8 @@ static int open_cred_file(char * file_name) if(fs == NULL) return errno; line_buf = malloc(4096); - if(line_buf == NULL) { - fclose(fs); + if(line_buf == NULL) return -ENOMEM; - } while(fgets(line_buf,4096,fs)) { /* parse line from credential file */ @@ -506,8 +504,6 @@ static int parse_options(char * options, int * filesys_flags) *filesys_flags &= ~MS_NOSUID; } else if (strncmp(data, "nodev", 5) == 0) { *filesys_flags |= MS_NODEV; - } else if (strncmp(data, "nobrl", 5) == 0) { - *filesys_flags &= ~MS_MANDLOCK; } else if (strncmp(data, "dev", 3) == 0) { *filesys_flags &= ~MS_NODEV; } else if (strncmp(data, "noexec", 6) == 0) { @@ -574,15 +570,13 @@ static void check_for_comma(char ** ppasswrd) char *pass; int i,j; int number_of_commas = 0; - int len; + int len = strlen(*ppasswrd); if(ppasswrd == NULL) return; else (pass = *ppasswrd); - len = strlen(pass); - for(i=0;i 1023) { printf("mount error: UNC name too long"); @@ -720,13 +715,6 @@ static char * parse_server(char ** punc_name) if(share) { free_share_name = 1; *punc_name = malloc(length+3); - if(*punc_name == NULL) { - /* put the original string back if - no memory left */ - *punc_name = unc_name; - return NULL; - } - *share = '/'; strncpy((*punc_name)+2,unc_name,length); unc_name = *punc_name; @@ -756,7 +744,8 @@ continue_unc_parsing: return NULL; } if(host_entry == NULL) { - printf("mount error: could not find target server. TCP name %s not found\n", unc_name); + printf("mount error: could not find target server. TCP name %s not found ", unc_name); + printf(" rc = %d\n",rc); return NULL; } else { /* BB should we pass an alternate version of the share name as Unicode */ @@ -1029,9 +1018,6 @@ mount_retry: optlen = 0; if(share_name) optlen += strlen(share_name) + 4; - else { - printf("No server share name specified\n"); - } if(user_name) optlen += strlen(user_name) + 6; if(ipaddr) @@ -1140,6 +1126,8 @@ mount_retry: strcat(mountent.mnt_opts,"rw"); if(flags & MS_MANDLOCK) strcat(mountent.mnt_opts,",mand"); + else + strcat(mountent.mnt_opts,",nomand"); if(flags & MS_NOEXEC) strcat(mountent.mnt_opts,",noexec"); if(flags & MS_NOSUID) diff --git a/source3/client/smbspool.c b/source3/client/smbspool.c index d13ae39416f..da517297f71 100644 --- a/source3/client/smbspool.c +++ b/source3/client/smbspool.c @@ -70,6 +70,9 @@ static int smb_print(struct cli_state *, char *, FILE *); FILE *fp; /* File to print */ int status=0; /* Status of LPD job */ struct cli_state *cli; /* SMB interface */ + char null_str[1]; + + null_str[0] = '\0'; /* we expect the URI in argv[0]. Detect the case where it is in argv[1] and cope */ if (argc > 2 && strncmp(argv[0],"smb://", 6) && !strncmp(argv[1],"smb://", 6)) { @@ -158,12 +161,12 @@ static int smb_print(struct cli_state *, char *, FILE *); if ((password = strchr_m(username, ':')) != NULL) *password++ = '\0'; else - password = ""; + password = null_str; } else { - username = ""; - password = ""; + username = null_str; + password = null_str; server = uri + 6; } @@ -335,10 +338,8 @@ char * get_ticket_cache( uid_t uid ) if ( ticket_file == NULL ) { -#ifdef DEVELOPER /* no ticket cache found */ fprintf(stderr, "ERROR: No ticket cache found for userid=%d\n", uid); -#endif return NULL; } diff --git a/source3/configure.in b/source3/configure.in index aeb3dd5d479..deeab5886fe 100644 --- a/source3/configure.in +++ b/source3/configure.in @@ -235,6 +235,7 @@ AC_SUBST(SMBWRAP_INC) AC_SUBST(EXTRA_BIN_PROGS) AC_SUBST(EXTRA_SBIN_PROGS) AC_SUBST(EXTRA_ALL_TARGETS) +AC_SUBST(CONFIG_LIBS) # Set defaults PIE_CFLAGS="" @@ -359,9 +360,9 @@ if test "$ac_cv_prog_gnu_ld" = "yes"; then changequote([,])dnl AC_MSG_RESULT(${ac_cv_gnu_ld_date}) if test -n "$ac_cv_gnu_ld_date"; then - if test "$ac_cv_gnu_ld_date" -lt 20030217; then - ac_cv_gnu_ld_no_default_allow_shlib_undefined=yes - fi + if test "$ac_cv_gnu_ld_date" -lt 20030217; then + ac_cv_gnu_ld_no_default_allow_shlib_undefined=yes + fi else AC_MSG_CHECKING(GNU ld release version) changequote(,)dnl @@ -457,10 +458,10 @@ 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_net rpc_dfs rpc_srv rpc_spoolss rpc_eventlog auth_rhosts auth_sam auth_unix auth_winbind auth_server auth_domain auth_builtin printerdb_file" +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" 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" +default_shared_modules="vfs_recycle vfs_audit vfs_extd_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" if test "x$developer" = xyes; then default_static_modules="$default_static_modules rpc_echo" @@ -1990,14 +1991,14 @@ dnl For IA64 HPUX systems, the libs are located in lib/hpux32 instead of lib. for l in "lib32" "lib" "lib/hpux32"; do if test -d "$i/$l" ; then LDFLAGS="$save_LDFLAGS -L$i/$l" - LIBS= - export LDFLAGS LIBS CPPFLAGS + LIBS= + export LDFLAGS LIBS CPPFLAGS dnl Try to find iconv(3) jm_ICONV($i/$l) if test x"$ICONV_FOUND" = "xyes" ; then - libext="$l" - break; - fi + libext="$l" + break; + fi fi done @@ -2005,7 +2006,7 @@ dnl Try to find iconv(3) LDFLAGS=$save_LDFLAGS LIB_ADD_DIR(LDFLAGS, "$i/$libext") CFLAGS_ADD_DIR(CPPFLAGS, "$i/include") - LIBS="$save_LIBS" + LIBS="$save_LIBS" ICONV_LOCATION=$i export LDFLAGS LIBS CPPFLAGS dnl Now, check for a working iconv ... we want to do it here because @@ -2820,6 +2821,7 @@ if test x"$with_ldap_support" != x"no"; then if test x"$ac_cv_lib_ext_ldap_ldap_init" = x"yes" -a x"$ac_cv_func_ext_ldap_domain2hostlist" = x"yes"; then AC_DEFINE(HAVE_LDAP,1,[Whether ldap is available]) default_static_modules="$default_static_modules pdb_ldap idmap_ldap"; + default_shared_modules="$default_shared_modules"; SMBLDAP="lib/smbldap.o" SMBLDAPUTIL="lib/smbldap_util.o" with_ldap_support=yes @@ -3048,9 +3050,77 @@ if test x"$with_ads_support" != x"no"; then AC_CHECK_FUNC_EXT(krb5_krbhst_get_addrinfo, $KRB5_LIBS) AC_CHECK_FUNC_EXT(krb5_c_enctype_compare, $KRB5_LIBS) AC_CHECK_FUNC_EXT(krb5_enctypes_compatible_keys, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_crypto_init, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_crypto_destroy, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_decode_ap_req, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(decode_krb5_ap_req, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_free_ap_req, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(free_AP_REQ, $KRB5_LIBS) + AC_CHECK_FUNC_EXT(krb5_c_verify_checksum, $KRB5_LIBS) + 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) LIBS="$KRB5_LIBS $LIBS" - + + AC_CACHE_CHECK(whether krb5_verify_checksum takes 7 arguments, smb_krb5_verify_checksum, [ + AC_TRY_COMPILE([ + #include ], + [krb5_verify_checksum(0, 0, 0, 0, 0, 0, 0);], + [smb_krb5_verify_checksum=7], + [smb_krb5_verify_checksum=6], + ) + ]) + AC_DEFINE_UNQUOTED(KRB5_VERIFY_CHECKSUM_ARGS, $smb_krb5_verify_checksum, [Number of arguments to krb5_verify_checksum]) + + AC_CACHE_CHECK([for checksum in krb5_checksum], + samba_cv_HAVE_CHECKSUM_IN_KRB5_CHECKSUM,[ + AC_TRY_COMPILE([#include ], + [krb5_checksum cksum; cksum.checksum.length = 0;], + samba_cv_HAVE_CHECKSUM_IN_KRB5_CHECKSUM=yes, + samba_cv_HAVE_CHECKSUM_IN_KRB5_CHECKSUM=no)]) + + if test x"$samba_cv_HAVE_CHECKSUM_IN_KRB5_CHECKSUM" = x"yes"; then + AC_DEFINE(HAVE_CHECKSUM_IN_KRB5_CHECKSUM,1, + [Whether the krb5_checksum struct has a checksum property]) + fi + + AC_CACHE_CHECK([for etype in EncryptedData], + samba_cv_HAVE_ETYPE_IN_ENCRYPTEDDATA,[ + AC_TRY_COMPILE([#include ], + [EncryptedData edata; edata.etype = 0;], + samba_cv_HAVE_ETYPE_IN_ENCRYPTEDDATA=yes, + samba_cv_HAVE_ETYPE_IN_ENCRYPTEDDATA=no)]) + + if test x"$samba_cv_HAVE_ETYPE_IN_ENCRYPTEDDATA" = x"yes"; then + AC_DEFINE(HAVE_ETYPE_IN_ENCRYPTEDDATA,1, + [Whether the EncryptedData struct has a etype property]) + fi + + AC_CACHE_CHECK([for ticket pointer in krb5_ap_req], + samba_cv_HAVE_TICKET_POINTER_IN_KRB5_AP_REQ,[ + AC_TRY_COMPILE([#include ], + [krb5_ap_req *ap_req; ap_req->ticket = NULL;], + samba_cv_HAVE_TICKET_POINTER_IN_KRB5_AP_REQ=yes, + samba_cv_HAVE_TICKET_POINTER_IN_KRB5_AP_REQ=no)]) + + if test x"$samba_cv_HAVE_TICKET_POINTER_IN_KRB5_AP_REQ" = x"yes"; then + AC_DEFINE(HAVE_TICKET_POINTER_IN_KRB5_AP_REQ,1, + [Whether the krb5_ap_req struct has a ticket pointer]) + fi + + AC_CACHE_CHECK([for krb5_crypto type], + samba_cv_HAVE_KRB5_CRYPTO,[ + AC_TRY_COMPILE([#include ], + [krb5_crypto crypto;], + samba_cv_HAVE_KRB5_CRYPTO=yes, + samba_cv_HAVE_KRB5_CRYPTO=no)]) + + if test x"$samba_cv_HAVE_KRB5_CRYPTO" = x"yes"; then + AC_DEFINE(HAVE_KRB5_CRYPTO,1, + [Whether the type krb5_crypto exists]) + fi + AC_CACHE_CHECK([for krb5_encrypt_block type], samba_cv_HAVE_KRB5_ENCRYPT_BLOCK,[ AC_TRY_COMPILE([#include ], @@ -3178,6 +3248,30 @@ if test x"$with_ads_support" != x"no"; then [Whether the KV5M_KEYTAB option is available]) fi + AC_CACHE_CHECK([for KRB5_KU_OTHER_CKSUM], + samba_cv_HAVE_KRB5_KU_OTHER_CKSUM,[ + AC_TRY_COMPILE([#include ], + [krb5_keyusage usage = KRB5_KU_OTHER_CKSUM;], + samba_cv_HAVE_KRB5_KU_OTHER_CKSUM=yes, + samba_cv_HAVE_KRB5_KU_OTHER_CKSUM=no)]) + + if test x"$samba_cv_HAVE_KRB5_KU_OTHER_CKSUM" = x"yes"; then + AC_DEFINE(HAVE_KRB5_KU_OTHER_CKSUM,1, + [Whether KRB5_KU_OTHER_CKSUM is available]) + fi + + AC_CACHE_CHECK([for KRB5_KEYUSAGE_APP_DATA_CKSUM], + samba_cv_HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM,[ + AC_TRY_COMPILE([#include ], + [krb5_keyusage usage = KRB5_KEYUSAGE_APP_DATA_CKSUM;], + samba_cv_HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM=yes, + samba_cv_HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM=no)]) + + if test x"$samba_cv_HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM" = x"yes"; then + AC_DEFINE(HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM,1, + [Whether KRB5_KEYUSAGE_APP_DATA_CKSUM is available]) + fi + AC_CACHE_CHECK([for the krb5_princ_component macro], samba_cv_HAVE_KRB5_PRINC_COMPONENT,[ AC_TRY_LINK([#include ], @@ -3915,7 +4009,6 @@ AC_ARG_WITH(libsmbclient, INSTALLCLIENT=installclientlib ) - INSTALLCLIENTCMD_SH=: INSTALLCLIENTCMD_A=: INSTALLCLIENT= @@ -3925,19 +4018,19 @@ AC_MSG_CHECKING(whether to build the libsmbsharemodes shared library) AC_ARG_WITH(libsmbsharemodes, [ --with-libsmbsharemodes Build the libsmbsharemodes shared library (default=yes if shared libs supported)], [ case "$withval" in - no) + no) AC_MSG_RESULT(no) ;; *) if test $BLDSHARED = true; then INSTALLCLIENTCMD_SH="\$(INSTALLCMD)" - ## build the static version of libsmbsharemodes as well - INSTALLCLIENTCMD_A="\$(INSTALLCMD)" + ## build the static version of libsmbsharemodes as well + INSTALLCLIENTCMD_A="\$(INSTALLCMD)" LIBSMBSHAREMODES_SHARED=bin/libsmbsharemodes.$SHLIBEXT LIBSMBSHAREMODES=libsmbsharemodes AC_MSG_RESULT(yes) else - enable_static=yes + enable_static=yes AC_MSG_RESULT(no shared library support -- will supply static library) fi if test $enable_static = yes; then @@ -3965,7 +4058,6 @@ AC_ARG_WITH(libsmbsharemodes, INSTALLCLIENT=installclientlib ) - ################################################# # these tests are taken from the GNU fileutils package AC_CHECKING(how to get filesystem space usage) @@ -4951,11 +5043,13 @@ SMB_MODULE(pdb_tdbsam, passdb/pdb_tdb.o, "bin/tdbsam.$SHLIBEXT", PDB) SMB_MODULE(pdb_guest, passdb/pdb_guest.o, "bin/guest.$SHLIBEXT", PDB) SMB_SUBSYSTEM(PDB,passdb/pdb_interface.o) + SMB_MODULE(rpc_lsa, \$(RPC_LSA_OBJ), "bin/librpc_lsarpc.$SHLIBEXT", RPC) SMB_MODULE(rpc_reg, \$(RPC_REG_OBJ), "bin/librpc_winreg.$SHLIBEXT", RPC) SMB_MODULE(rpc_lsa_ds, \$(RPC_LSA_DS_OBJ), "bin/librpc_lsa_ds.$SHLIBEXT", RPC) 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_srv, \$(RPC_SVC_OBJ), "bin/librpc_srvsvc.$SHLIBEXT", RPC) diff --git a/source3/groupdb/mapping.c b/source3/groupdb/mapping.c index a30e8eed784..3ca074581c1 100644 --- a/source3/groupdb/mapping.c +++ b/source3/groupdb/mapping.c @@ -2,7 +2,7 @@ * Unix SMB/CIFS implementation. * RPC Pipe client / server routines * Copyright (C) Andrew Tridgell 1992-2000, - * Copyright (C) Jean François Micouleau 1998-2001. + * Copyright (C) Jean François Micouleau 1998-2001. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -365,7 +365,7 @@ static BOOL get_group_map_from_ntname(const char *name, GROUP_MAP *map) Remove a group mapping entry. ****************************************************************************/ -static BOOL group_map_remove(DOM_SID sid) +static BOOL group_map_remove(const DOM_SID *sid) { TDB_DATA kbuf, dbuf; pstring key; @@ -378,7 +378,7 @@ static BOOL group_map_remove(DOM_SID sid) /* the key is the SID, retrieving is direct */ - sid_to_string(string_sid, &sid); + sid_to_string(string_sid, sid); slprintf(key, sizeof(key), "%s%s", GROUP_PREFIX, string_sid); kbuf.dptr = key; @@ -954,7 +954,6 @@ BOOL get_group_from_gid(gid_t gid, GROUP_MAP *map) return True; } - /**************************************************************************** Create a UNIX group on demand. ****************************************************************************/ @@ -988,8 +987,8 @@ int smb_create_group(char *unix_group, gid_t *new_gid) close(fd); } - } - + } + if (*new_gid == 0) { struct group *grp = getgrnam(unix_group); @@ -1018,7 +1017,7 @@ int smb_delete_group(char *unix_group) DEBUG(ret ? 0 : 3,("smb_delete_group: Running the command `%s' gave %d\n",del_script,ret)); return ret; } - + return -1; } @@ -1131,7 +1130,7 @@ NTSTATUS pdb_default_update_group_mapping_entry(struct pdb_methods *methods, NTSTATUS pdb_default_delete_group_mapping_entry(struct pdb_methods *methods, DOM_SID sid) { - return group_map_remove(sid) ? + return group_map_remove(&sid) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } @@ -1173,18 +1172,12 @@ NTSTATUS pdb_default_create_alias(struct pdb_methods *methods, if (lookup_name(get_global_sam_name(), name, &sid, &type)) return NT_STATUS_ALIAS_EXISTS; - if (!winbind_allocate_rid(&new_rid)) + if (!winbind_allocate_rid_and_gid(&new_rid, &gid)) return NT_STATUS_ACCESS_DENIED; sid_copy(&sid, get_global_sam_sid()); sid_append_rid(&sid, new_rid); - /* Here we allocate the gid */ - if (!winbind_sid_to_gid(&gid, &sid)) { - DEBUG(0, ("Could not get gid for new RID\n")); - return NT_STATUS_ACCESS_DENIED; - } - map.gid = gid; sid_copy(&map.sid, &sid); map.sid_name_use = SID_NAME_ALIAS; @@ -1282,7 +1275,7 @@ NTSTATUS pdb_default_alias_memberships(struct pdb_methods *methods, return result; *alias_rids = TALLOC_ARRAY(mem_ctx, uint32, num_alias_sids); - if ((alias_sids != 0) && (*alias_rids == NULL)) + if (*alias_rids == NULL) return NT_STATUS_NO_MEMORY; *num_alias_rids = 0; @@ -1347,3 +1340,38 @@ NTSTATUS pdb_nop_enum_group_mapping(struct pdb_methods *methods, return NT_STATUS_UNSUCCESSFUL; } +/**************************************************************************** + These need to be redirected through pdb_interface.c +****************************************************************************/ +BOOL pdb_get_dom_grp_info(const DOM_SID *sid, struct acct_info *info) +{ + GROUP_MAP map; + BOOL res; + + become_root(); + res = get_domain_group_from_sid(*sid, &map); + unbecome_root(); + + if (!res) + return False; + + fstrcpy(info->acct_name, map.nt_name); + fstrcpy(info->acct_desc, map.comment); + sid_peek_rid(sid, &info->rid); + return True; +} + +BOOL pdb_set_dom_grp_info(const DOM_SID *sid, const struct acct_info *info) +{ + GROUP_MAP map; + + if (!get_domain_group_from_sid(*sid, &map)) + return False; + + fstrcpy(map.nt_name, info->acct_name); + fstrcpy(map.comment, info->acct_desc); + + return pdb_update_group_mapping_entry(&map); +} + + diff --git a/source3/include/ads.h b/source3/include/ads.h index 8f6cc6e582b..d2eeaab4d84 100644 --- a/source3/include/ads.h +++ b/source3/include/ads.h @@ -130,7 +130,7 @@ typedef void **ADS_MODLIST; #define UF_UNUSED_5 0x00800000 #define UF_UNUSED_6 0x01000000 -#define UF_UNUSED_7 0x02000000 +#define UF_NO_AUTH_DATA_REQUIRED 0x02000000 #define UF_UNUSED_8 0x04000000 #define UF_UNUSED_9 0x08000000 diff --git a/source3/include/asn_1.h b/source3/include/asn_1.h index 796c8bb7404..63a18c49230 100644 --- a/source3/include/asn_1.h +++ b/source3/include/asn_1.h @@ -27,7 +27,7 @@ struct nesting { struct nesting *next; }; -typedef struct { +typedef struct asn1_data { uint8 *data; size_t length; off_t ofs; @@ -37,13 +37,16 @@ typedef struct { #define ASN1_APPLICATION(x) ((x)+0x60) +#define ASN1_APPLICATION_SIMPLE(x) ((x)+0x40) #define ASN1_SEQUENCE(x) ((x)+0x30) #define ASN1_CONTEXT(x) ((x)+0xa0) +#define ASN1_CONTEXT_SIMPLE(x) ((x)+0x80) #define ASN1_GENERAL_STRING 0x1b #define ASN1_OCTET_STRING 0x4 #define ASN1_OID 0x6 #define ASN1_BOOLEAN 0x1 #define ASN1_INTEGER 0x2 +#define ASN1_BITFIELD 0x3 #define ASN1_ENUMERATED 0xa #define ASN1_SET 0x31 diff --git a/source3/include/authdata.h b/source3/include/authdata.h index 1be127aaac6..194429ab673 100644 --- a/source3/include/authdata.h +++ b/source3/include/authdata.h @@ -23,12 +23,22 @@ #define _AUTHDATA_H #include "rpc_misc.h" +#include "rpc_netlogon.h" #define PAC_TYPE_LOGON_INFO 1 #define PAC_TYPE_SERVER_CHECKSUM 6 #define PAC_TYPE_PRIVSVR_CHECKSUM 7 #define PAC_TYPE_LOGON_NAME 10 +#ifndef KRB5_AUTHDATA_WIN2K_PAC +#define KRB5_AUTHDATA_WIN2K_PAC 128 +#endif + +#ifndef KRB5_AUTHDATA_IF_RELEVANT +#define KRB5_AUTHDATA_IF_RELEVANT 1 +#endif + + typedef struct pac_logon_name { NTTIME logon_time; uint16 len; @@ -37,7 +47,7 @@ typedef struct pac_logon_name { typedef struct pac_signature_data { uint32 type; - uint8 *signature; + RPC_DATA_BLOB signature; /* this not the on-wire-format (!) */ } PAC_SIGNATURE_DATA; typedef struct group_membership { @@ -50,6 +60,8 @@ typedef struct group_membership_array { GROUP_MEMBERSHIP *group_membership; } GROUP_MEMBERSHIP_ARRAY; +#if 0 /* Unused, replaced by NET_USER_INFO_3 - Guenther */ + typedef struct krb_sid_and_attrs { uint32 sid_ptr; uint32 attrs; @@ -82,7 +94,7 @@ typedef struct pac_logon_info { UNIHDR hdr_dir_drive; uint16 logon_count; /* number of times user has logged onto domain */ - uint16 reserved12; + uint16 bad_password_count; /* samba4 idl */ uint32 user_rid; uint32 group_rid; @@ -90,15 +102,15 @@ typedef struct pac_logon_info { uint32 group_membership_ptr; uint32 user_flags; - uint32 reserved13[4]; + uint8 session_key[16]; /* samba4 idl */ UNIHDR hdr_dom_controller; UNIHDR hdr_dom_name; uint32 ptr_dom_sid; - - uint32 reserved16[2]; - uint32 reserved17; /* looks like it may be acb_info */ - uint32 reserved18[7]; + + uint8 lm_session_key[8]; /* samba4 idl */ + uint32 acct_flags; /* samba4 idl */ + uint32 unknown[7]; uint32 sid_count; uint32 ptr_extra_sids; @@ -121,6 +133,14 @@ typedef struct pac_logon_info { DOM_SID2 res_group_dom_sid; GROUP_MEMBERSHIP_ARRAY res_groups; +} PAC_LOGON_INFO; +#endif + +typedef struct pac_logon_info { + NET_USER_INFO_3 info3; + DOM_SID2 res_group_dom_sid; + GROUP_MEMBERSHIP_ARRAY res_groups; + } PAC_LOGON_INFO; typedef struct pac_info_ctr @@ -134,18 +154,19 @@ typedef struct pac_info_ctr } pac; } PAC_INFO_CTR; -typedef struct pac_info_hdr { +typedef struct pac_buffer { uint32 type; uint32 size; uint32 offset; uint32 offsethi; PAC_INFO_CTR *ctr; -} PAC_INFO_HDR; + uint32 pad; +} PAC_BUFFER; typedef struct pac_data { uint32 num_buffers; uint32 version; - PAC_INFO_HDR *pac_info_hdr_ptr; + PAC_BUFFER *pac_buffer; } PAC_DATA; diff --git a/source3/include/client.h b/source3/include/client.h index e9d40c3b7c9..df52e227f0c 100644 --- a/source3/include/client.h +++ b/source3/include/client.h @@ -57,25 +57,39 @@ struct print_job_info time_t t; }; +struct cli_pipe_auth_data { + enum pipe_auth_type auth_type; /* switch for the union below. Defined in ntdomain.h */ + enum pipe_auth_level auth_level; /* defined in ntdomain.h */ + union { + struct schannel_auth_struct *schannel_auth; + NTLMSSP_STATE *ntlmssp_state; + struct kerberos_auth_struct *kerberos_auth; + } a_u; + void (*cli_auth_data_free_func)(struct cli_pipe_auth_data *); +}; + struct rpc_pipe_client { + struct rpc_pipe_client *prev, *next; + TALLOC_CTX *mem_ctx; struct cli_state *cli; int pipe_idx; + const char *pipe_name; uint16 fnum; - int pipe_auth_flags; - - NTLMSSP_STATE *ntlmssp_pipe_state; - const char *user_name; const char *domain; + const char *user_name; struct pwd_info pwd; - struct netsec_auth_struct auth_info; - uint16 max_xmit_frag; uint16 max_recv_frag; + + struct cli_pipe_auth_data auth; + + /* The following is only non-null on a netlogon pipe. */ + struct dcinfo *dc; }; struct cli_state { @@ -92,8 +106,11 @@ struct cli_state { int privileges; fstring desthost; - fstring user_name; + + /* The credentials used to open the cli_state connection. */ fstring domain; + fstring user_name; + struct pwd_info pwd; /* * The following strings are the @@ -111,7 +128,6 @@ struct cli_state { fstring full_dest_host_name; struct in_addr dest_ip; - struct pwd_info pwd; DATA_BLOB secblob; /* cryptkey or negTokenInit */ uint32 sesskey; int serverzone; @@ -137,27 +153,8 @@ struct cli_state { any per-pipe authenticaion */ DATA_BLOB user_session_key; - /* - * Only used in NT domain calls. - */ - - int pipe_idx; /* Index (into list of known pipes) - of the pipe we're talking to, - if any */ - - struct rpc_pipe_client pipes[PI_MAX_PIPES]; - - /* Secure pipe parameters */ - int pipe_auth_flags; - - struct rpc_pipe_client netlogon_pipe; /* The "first" pipe to get - the session key for the - schannel. */ - unsigned char sess_key[16]; /* Current session key. */ - DOM_CRED clnt_cred; /* Client credential. */ - fstring mach_acct; /* MYNAME$. */ - fstring srv_name_slash; /* \\remote server. */ - fstring clnt_name_slash; /* \\local client. */ + /* The list of pipes currently open on this connection. */ + struct rpc_pipe_client *pipe_list; BOOL use_kerberos; BOOL fallback_after_kerberos; @@ -175,9 +172,6 @@ struct cli_state { /* was this structure allocated by cli_initialise? If so, then free in cli_shutdown() */ BOOL allocated; - - /* Name of the pipe we're talking to, if any */ - fstring pipe_name; }; #define CLI_FULL_CONNECTION_DONT_SPNEGO 0x0001 diff --git a/source3/include/dlinklist.h b/source3/include/dlinklist.h index 794aea75766..c856aaa7625 100644 --- a/source3/include/dlinklist.h +++ b/source3/include/dlinklist.h @@ -70,6 +70,20 @@ } \ } +/* insert 'p' after the given element 'el' in a list. If el is NULL then + this is the same as a DLIST_ADD() */ +#define DLIST_ADD_AFTER(list, p, el) \ +do { \ + if (!(list) || !(el)) { \ + DLIST_ADD(list, p); \ + } else { \ + p->prev = el; \ + p->next = el->next; \ + el->next = p; \ + if (p->next) p->next->prev = p; \ + }\ +} while (0) + /* demote an element to the top of the list, needs a tmp pointer */ #define DLIST_DEMOTE(list, p, tmp) \ { \ diff --git a/source3/include/doserr.h b/source3/include/doserr.h index 7c98171250c..593d5d99eef 100644 --- a/source3/include/doserr.h +++ b/source3/include/doserr.h @@ -5,6 +5,7 @@ Copyright (C) John H Terpstra 1996-2000 Copyright (C) Luke Kenneth Casson Leighton 1996-2000 Copyright (C) Paul Ashton 1998-2000 + Copyright (C) Gerald (Jerry) Carter 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 @@ -174,6 +175,7 @@ #define WERR_NOMEM W_ERROR(8) #define WERR_GENERAL_FAILURE W_ERROR(31) #define WERR_NOT_SUPPORTED W_ERROR(50) +#define WERR_DEVICE_NOT_EXIST W_ERROR(55) #define WERR_PRINTQ_FULL W_ERROR(61) #define WERR_NO_SPOOL_SPACE W_ERROR(62) #define WERR_NO_SUCH_SHARE W_ERROR(67) @@ -227,6 +229,12 @@ #define WERR_PRINT_MONITOR_IN_USE W_ERROR(ERRprintmonitorinuse) #define WERR_PRINTER_HAS_JOBS_QUEUED W_ERROR(ERRprinterhasjobsqueued) +/* Configuration Manager Errors */ +/* Basically Win32 errors meanings are specific to the \ntsvcs pipe */ + +#define WERR_CM_NO_MORE_HW_PROFILES W_ERROR(35) +#define WERR_CM_NO_SUCH_VALUE W_ERROR(37) + /* DFS errors */ diff --git a/source3/include/includes.h b/source3/include/includes.h index 51aa218ac6c..573982903b8 100644 --- a/source3/include/includes.h +++ b/source3/include/includes.h @@ -27,7 +27,8 @@ #ifndef __cplusplus #define class #error DONT_USE_CPLUSPLUS_RESERVED_NAMES -#define private #error DONT_USE_CPLUSPLUS_RESERVED_NAMES +/* allow to build with newer heimdal releases */ +/* #define private #error DONT_USE_CPLUSPLUS_RESERVED_NAMES */ #define public #error DONT_USE_CPLUSPLUS_RESERVED_NAMES #define protected #error DONT_USE_CPLUSPLUS_RESERVED_NAMES #define template #error DONT_USE_CPLUSPLUS_RESERVED_NAMES @@ -288,6 +289,7 @@ #include #endif + #ifdef HAVE_SYS_MOUNT_H #include #endif @@ -896,19 +898,17 @@ extern int errno; #include "privileges.h" -#include "rpc_creds.h" +#include "rpc_misc.h" + +#include "rpc_dce.h" #include "mapping.h" #include "passdb.h" -#include "ntdomain.h" - -#include "rpc_misc.h" - #include "rpc_secdes.h" -#include "nt_printing.h" +#include "authdata.h" #include "msdfs.h" @@ -923,6 +923,29 @@ extern int errno; #include "auth.h" +#include "ntdomain.h" + +#include "rpc_svcctl.h" +#include "rpc_ntsvcs.h" +#include "rpc_lsa.h" +#include "rpc_netlogon.h" +#include "reg_objects.h" +#include "rpc_reg.h" +#include "rpc_samr.h" +#include "rpc_srvsvc.h" +#include "rpc_wkssvc.h" +#include "rpc_spoolss.h" +#include "rpc_eventlog.h" +#include "rpc_dfs.h" +#include "rpc_ds.h" +#include "rpc_echo.h" +#include "rpc_shutdown.h" +#include "rpc_unixinfo.h" +#include "rpc_perfcount.h" +#include "rpc_perfcount_defs.h" + +#include "nt_printing.h" + #include "idmap.h" #include "client.h" @@ -945,6 +968,8 @@ extern int errno; #include "spnego.h" +#include "rpc_client.h" + /* * Type for wide character dirent structure. * Only d_name is defined by POSIX. @@ -995,6 +1020,8 @@ struct smb_ldap_privates; #include "smbldap.h" +#include "smb_ldap.h" + /***** automatically generated prototypes *****/ #ifndef NO_PROTO_H #include "proto.h" @@ -1414,7 +1441,7 @@ void krb5_free_unparsed_name(krb5_context ctx, char *val); void setup_kaddr( krb5_address *pkaddr, struct sockaddr *paddr); int create_kerberos_key_from_string(krb5_context context, krb5_principal host_princ, krb5_data *password, krb5_keyblock *key, krb5_enctype enctype); int create_kerberos_key_from_string_direct(krb5_context context, krb5_principal host_princ, krb5_data *password, krb5_keyblock *key, krb5_enctype enctype); -void get_auth_data_from_tkt(DATA_BLOB *auth_data, krb5_ticket *tkt); +BOOL get_auth_data_from_tkt(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, krb5_ticket *tkt); krb5_const_principal get_principal_from_tkt(krb5_ticket *tkt); krb5_error_code krb5_locate_kdc(krb5_context ctx, const krb5_data *realm, struct sockaddr **addr_pp, int *naddrs, int get_masters); krb5_error_code get_kerberos_allowed_etypes(krb5_context context, krb5_enctype **enctypes); diff --git a/source3/include/messages.h b/source3/include/messages.h index 1039e0d9a70..abe219374ed 100644 --- a/source3/include/messages.h +++ b/source3/include/messages.h @@ -63,6 +63,11 @@ #define MSG_SMB_SAM_SYNC 3003 #define MSG_SMB_SAM_REPL 3004 #define MSG_SMB_UNLOCK 3005 +#define MSG_SMB_BREAK_REQUEST 3006 +#define MSG_SMB_BREAK_RESPONSE 3007 +#define MSG_SMB_ASYNC_LEVEL2_BREAK 3008 +#define MSG_SMB_OPEN_RETRY 3009 +#define MSG_SMB_KERNEL_BREAK 3010 /* winbind messages */ #define MSG_WINBIND_FINISHED 4001 @@ -77,4 +82,8 @@ #define FLAG_MSG_PRINT_NOTIFY 0x0008 #define FLAG_MSG_PRINT_GENERAL 0x0010 +struct process_id { + pid_t pid; +}; + #endif diff --git a/source3/include/module.h b/source3/include/module.h index c41310c7f75..8b317a9d59d 100644 --- a/source3/include/module.h +++ b/source3/include/module.h @@ -33,6 +33,4 @@ typedef int smb_event_id_t; typedef void (smb_idle_event_fn)(void **data,time_t *interval,time_t now); -typedef void (smb_exit_event_fn)(void **data); - #endif /* _MODULE_H */ diff --git a/source3/include/ntdomain.h b/source3/include/ntdomain.h index 87fac492db3..967aac2bb5f 100644 --- a/source3/include/ntdomain.h +++ b/source3/include/ntdomain.h @@ -24,30 +24,6 @@ #ifndef _NT_DOMAIN_H /* _NT_DOMAIN_H */ #define _NT_DOMAIN_H -struct uuid { - uint32 time_low; - uint16 time_mid; - uint16 time_hi_and_version; - uint8 clock_seq[2]; - uint8 node[6]; -}; -#define UUID_SIZE 16 - -#define UUID_FLAT_SIZE 16 -typedef struct uuid_flat { - uint8 info[UUID_FLAT_SIZE]; -} UUID_FLAT; - -/* dce/rpc support */ -#include "rpc_dce.h" - -/* miscellaneous structures / defines */ -#include "rpc_misc.h" - -#include "rpc_creds.h" - -#include "talloc.h" - /* * A bunch of stuff that was put into smb.h * in the NTDOM branch - it didn't belong there. @@ -67,6 +43,7 @@ typedef struct _prs_struct { uint32 grow_size; /* size requested via prs_grow() calls */ char *data_p; /* The buffer itself. */ TALLOC_CTX *mem_ctx; /* When unmarshalling, use this.... */ + const char *sess_key; /* If we have to do encrypt/decrypt on the fly. */ } prs_struct; /* @@ -97,7 +74,7 @@ typedef struct _output_data { * The current PDU being returned. This inclues * headers, data and authentication footer. */ - unsigned char current_pdu[MAX_PDU_FRAG_LEN]; + unsigned char current_pdu[RPC_MAX_PDU_FRAG_LEN]; /* The amount of data in the current_pdu buffer. */ uint32 current_pdu_len; @@ -111,9 +88,9 @@ typedef struct _input_data { * This is the current incoming pdu. The data here * is collected via multiple writes until a complete * pdu is seen, then the data is copied into the in_data - * structure. The maximum size of this is 0x1630 (MAX_PDU_FRAG_LEN). + * structure. The maximum size of this is 0x1630 (RPC_MAX_PDU_FRAG_LEN). */ - unsigned char current_in_pdu[MAX_PDU_FRAG_LEN]; + unsigned char current_in_pdu[RPC_MAX_PDU_FRAG_LEN]; /* * The amount of data needed to complete the in_pdu. @@ -158,22 +135,22 @@ struct handle_list { /* Domain controller authentication protocol info */ struct dcinfo { - DOM_CHAL clnt_chal; /* Initial challenge received from client */ - DOM_CHAL srv_chal; /* Initial server challenge */ - DOM_CRED clnt_cred; /* Last client credential */ - DOM_CRED srv_cred; /* Last server credential */ + uint32 sequence; /* "timestamp" from client. */ + DOM_CHAL seed_chal; + DOM_CHAL clnt_chal; /* Client credential */ + DOM_CHAL srv_chal; /* Server credential */ uchar sess_key[8]; /* Session key */ - uchar md4pw[16]; /* md4(machine password) */ + uchar mach_pw[16]; /* md4(machine password) */ fstring mach_acct; /* Machine name we've authenticated. */ fstring remote_machine; /* Machine name we've authenticated. */ + fstring domain; BOOL challenge_sent; BOOL got_session_key; BOOL authenticated; - }; typedef struct pipe_rpc_fns { @@ -188,6 +165,46 @@ typedef struct pipe_rpc_fns { } PIPE_RPC_FNS; +/* + * Different auth types we support. + * Can't keep in sync with wire values as spnego wraps different auth methods. + */ + +enum pipe_auth_type { PIPE_AUTH_TYPE_NONE = 0, PIPE_AUTH_TYPE_NTLMSSP, PIPE_AUTH_TYPE_SCHANNEL, + PIPE_AUTH_TYPE_SPNEGO_NTLMSSP, PIPE_AUTH_TYPE_KRB5, PIPE_AUTH_TYPE_SPNEGO_KRB5 }; + +/* Possible auth levels - keep these in sync with the wire values. */ +enum pipe_auth_level { PIPE_AUTH_LEVEL_NONE = 0, + PIPE_AUTH_LEVEL_CONNECT = 1, /* We treat as NONE. */ + PIPE_AUTH_LEVEL_INTEGRITY = 5, /* Sign. */ + PIPE_AUTH_LEVEL_PRIVACY = 6 /* Seal. */ +}; + +/* auth state for krb5. */ +struct kerberos_auth_struct { + const char *service_principal; + DATA_BLOB session_key; +}; + +/* auth state for schannel. */ +struct schannel_auth_struct { + uchar sess_key[16]; + uint32 seq_num; +}; + +/* auth state for all bind types. */ + +struct pipe_auth_data { + enum pipe_auth_type auth_type; /* switch for union below. */ + enum pipe_auth_level auth_level; + union { + struct schannel_auth_struct *schannel_auth; + AUTH_NTLMSSP_STATE *auth_ntlmssp_state; +/* struct kerberos_auth_struct *kerberos_auth; TO BE ADDED... */ + } a_u; + void (*auth_data_free_func)(struct pipe_auth_data *); +}; + /* * DCE/RPC-specific samba-internal-specific handling of data on * NamedPipes. @@ -210,20 +227,12 @@ typedef struct pipes_struct { RPC_HDR hdr; /* Incoming RPC header. */ RPC_HDR_REQ hdr_req; /* Incoming request header. */ - uint32 ntlmssp_chal_flags; /* Client challenge flags. */ - BOOL ntlmssp_auth_requested; /* If the client wanted authenticated rpc. */ - BOOL ntlmssp_auth_validated; /* If the client *got* authenticated rpc. */ - unsigned char challenge[8]; - unsigned char ntlmssp_hash[258]; - uint32 ntlmssp_seq_num; - struct dcinfo dc; /* Keeps the creds data. */ + /* This context is used for pipe state storage and is freed when the pipe is closed. */ + TALLOC_CTX *pipe_state_mem_ctx; - /* Hmm. In my understanding the authentication happens - implicitly later, so there are no two stages for - schannel. */ + struct pipe_auth_data auth; - BOOL netsec_auth_validated; - struct netsec_auth_struct netsec_auth; + struct dcinfo *dc; /* Keeps the creds data from netlogon. */ /* * Windows user info. @@ -233,14 +242,13 @@ typedef struct pipes_struct { fstring wks; /* - * Unix user name and credentials. + * Unix user name and credentials used when a pipe is authenticated. */ fstring pipe_user_name; struct current_user pipe_user; - DATA_BLOB session_key; - + /* * Set to true when an RPC bind has been done on this pipe. */ @@ -277,7 +285,8 @@ typedef struct pipes_struct { output_data out_data; - /* talloc context to use when allocating memory on this pipe. */ + /* This context is used for PUD data and is freed between each pdu. + Don't use for pipe state storage. */ TALLOC_CTX *mem_ctx; /* handle database to use on this pipe. */ @@ -383,27 +392,11 @@ typedef struct { /* end higher order functions */ - -/* security descriptor structures */ -#include "rpc_secdes.h" - -/* pac */ -#include "authdata.h" - -/* different dce/rpc pipes */ -#include "rpc_buffer.h" -#include "rpc_lsa.h" -#include "rpc_netlogon.h" -#include "rpc_reg.h" -#include "rpc_samr.h" -#include "rpc_srvsvc.h" -#include "rpc_wkssvc.h" -#include "rpc_svcctl.h" -#include "rpc_spoolss.h" -#include "rpc_eventlog.h" -#include "rpc_dfs.h" -#include "rpc_ds.h" -#include "rpc_echo.h" -#include "rpc_shutdown.h" +typedef struct { + uint32 size; + prs_struct prs; + uint32 struct_start; + uint32 string_at_end; +} RPC_BUFFER; #endif /* _NT_DOMAIN_H */ diff --git a/source3/include/ntlmssp.h b/source3/include/ntlmssp.h index 267779c434d..30a37e06c3e 100644 --- a/source3/include/ntlmssp.h +++ b/source3/include/ntlmssp.h @@ -34,7 +34,8 @@ enum NTLM_MESSAGE_TYPE NTLMSSP_NEGOTIATE = 1, NTLMSSP_CHALLENGE = 2, NTLMSSP_AUTH = 3, - NTLMSSP_UNKNOWN = 4 + NTLMSSP_UNKNOWN = 4, + NTLMSSP_DONE = 5 /* samba final state */ }; /* NTLMSSP negotiation flags */ @@ -61,13 +62,15 @@ enum NTLM_MESSAGE_TYPE #define NTLMSSP_CHAL_TARGET_INFO 0x00800000 #define NTLMSSP_NEGOTIATE_128 0x20000000 /* 128-bit encryption */ #define NTLMSSP_NEGOTIATE_KEY_EXCH 0x40000000 -#define NTLMSSP_NEGOTIATE_080000000 0x80000000 +#define NTLMSSP_NEGOTIATE_56 0x80000000 #define NTLMSSP_NAME_TYPE_SERVER 0x01 #define NTLMSSP_NAME_TYPE_DOMAIN 0x02 #define NTLMSSP_NAME_TYPE_SERVER_DNS 0x03 #define NTLMSSP_NAME_TYPE_DOMAIN_DNS 0x04 +#define NTLMSSP_SIG_SIZE 16 + typedef struct ntlmssp_state { TALLOC_CTX *mem_ctx; @@ -142,23 +145,22 @@ typedef struct ntlmssp_state const char *(*get_global_myname)(void); const char *(*get_domain)(void); - /* SMB Signing */ - - uint32 ntlmssp_seq_num; - /* ntlmv2 */ - unsigned char send_sign_const[16]; - unsigned char send_seal_const[16]; - unsigned char recv_sign_const[16]; - unsigned char recv_seal_const[16]; - unsigned char send_sign_hash[258]; - unsigned char send_seal_hash[258]; - unsigned char recv_sign_hash[258]; - unsigned char recv_seal_hash[258]; + unsigned char send_sign_key[16]; + unsigned char send_seal_key[16]; + unsigned char recv_sign_key[16]; + unsigned char recv_seal_key[16]; + + unsigned char send_seal_arc4_state[258]; + unsigned char recv_seal_arc4_state[258]; + + uint32 ntlm2_send_seq_num; + uint32 ntlm2_recv_seq_num; /* ntlmv1 */ - unsigned char ntlmssp_hash[258]; + unsigned char ntlmv1_arc4_state[258]; + uint32 ntlmv1_seq_num; /* it turns out that we don't always get the response in at the time we want to process it. @@ -166,4 +168,3 @@ typedef struct ntlmssp_state DATA_BLOB stored_response; } NTLMSSP_STATE; - diff --git a/source3/include/passdb.h b/source3/include/passdb.h index 114585346e1..e985ab582dc 100644 --- a/source3/include/passdb.h +++ b/source3/include/passdb.h @@ -233,6 +233,7 @@ struct acct_info }; struct samr_displayentry { + uint32 idx; uint32 rid; uint16 acct_flags; const char *account_name; @@ -268,7 +269,7 @@ struct pdb_search { * this SAMBA will load. Increment this if *ANY* changes are made to the interface. */ -#define PASSDB_INTERFACE_VERSION 8 +#define PASSDB_INTERFACE_VERSION 9 typedef struct pdb_context { @@ -373,6 +374,14 @@ typedef struct pdb_context const char ***names, uint32 **attrs); + NTSTATUS (*pdb_get_account_policy)(struct pdb_context *context, + int policy_index, uint32 *value); + + NTSTATUS (*pdb_set_account_policy)(struct pdb_context *context, + int policy_index, uint32 value); + + NTSTATUS (*pdb_get_seq_num)(struct pdb_context *context, time_t *seq_num); + BOOL (*pdb_search_users)(struct pdb_context *context, struct pdb_search *search, uint16 acct_flags); @@ -478,6 +487,7 @@ typedef struct pdb_methods int num_members, uint32 **alias_rids, int *num_alias_rids); + NTSTATUS (*lookup_rids)(struct pdb_methods *methods, TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid, @@ -486,6 +496,14 @@ typedef struct pdb_methods const char ***names, uint32 **attrs); + NTSTATUS (*get_account_policy)(struct pdb_methods *methods, + int policy_index, uint32 *value); + + NTSTATUS (*set_account_policy)(struct pdb_methods *methods, + int policy_index, uint32 value); + + NTSTATUS (*get_seq_num)(struct pdb_methods *methods, time_t *seq_num); + BOOL (*search_users)(struct pdb_methods *methods, struct pdb_search *search, uint16 acct_flags); diff --git a/source3/include/printing.h b/source3/include/printing.h index 220fd08ef1e..54f32d5954c 100644 --- a/source3/include/printing.h +++ b/source3/include/printing.h @@ -57,7 +57,7 @@ struct printif print_status_struct *status); int (*queue_pause)(int snum); int (*queue_resume)(int snum); - int (*job_delete)(int snum, struct printjob *pjob); + int (*job_delete)(const char *sharename, const char *lprm_command, struct printjob *pjob); int (*job_pause)(int snum, struct printjob *pjob); int (*job_resume)(int snum, struct printjob *pjob); int (*job_submit)(int snum, struct printjob *pjob); diff --git a/source3/include/rpc_client.h b/source3/include/rpc_client.h index 9ca2d5aa8c9..8a83c0f8ae8 100644 --- a/source3/include/rpc_client.h +++ b/source3/include/rpc_client.h @@ -22,36 +22,68 @@ #define _RPC_CLIENT_H /* macro to expand cookie-cutter code in cli_xxx() using rpc_api_pipe_req() */ - -#define CLI_DO_RPC( pcli, ctx, pipe_num, opnum, q_in, r_out, \ + +#define CLI_DO_RPC( pcli, ctx, p_idx, opnum, q_in, r_out, \ q_ps, r_ps, q_io_fn, r_io_fn, default_error ) \ -{ r_out.status = default_error;\ - prs_init( &q_ps, MAX_PDU_FRAG_LEN, ctx, MARSHALL ); \ - prs_init( &r_ps, 0, ctx, UNMARSHALL );\ +{\ + SMB_ASSERT(pcli->pipe_idx == p_idx); \ + if (!prs_init( &q_ps, RPC_MAX_PDU_FRAG_LEN, ctx, MARSHALL )) { \ + return NT_STATUS_NO_MEMORY;\ + }\ + if (!prs_init( &r_ps, 0, ctx, UNMARSHALL )) {\ + prs_mem_free( &q_ps );\ + return NT_STATUS_NO_MEMORY;\ + }\ if ( q_io_fn("", &q_in, &q_ps, 0) ) {\ - if ( rpc_api_pipe_req(pcli, pipe_num, opnum, &q_ps, &r_ps) ) {\ - if (!r_io_fn("", &r_out, &r_ps, 0)) {\ - r_out.status = default_error;\ - }\ + NTSTATUS _smb_pipe_stat_ = rpc_api_pipe_req(pcli, opnum, &q_ps, &r_ps); \ + if (!NT_STATUS_IS_OK(_smb_pipe_stat_)) {\ + prs_mem_free( &q_ps );\ + prs_mem_free( &r_ps );\ + return _smb_pipe_stat_;\ + }\ + if (!r_io_fn("", &r_out, &r_ps, 0)) {\ + prs_mem_free( &q_ps );\ + prs_mem_free( &r_ps );\ + return default_error;\ }\ + } else {\ + prs_mem_free( &q_ps );\ + prs_mem_free( &r_ps );\ + return default_error;\ }\ prs_mem_free( &q_ps );\ prs_mem_free( &r_ps );\ } -/* macro to expand cookie-cutter code in cli_xxx() using rpc_api_pipe_req_int() */ +/* Arrrgg. Same but with WERRORS. Needed for registry code. */ -#define CLI_DO_RPC_EX( pcli, ctx, pipe_num, opnum, q_in, r_out, \ +#define CLI_DO_RPC_WERR( pcli, ctx, p_idx, opnum, q_in, r_out, \ q_ps, r_ps, q_io_fn, r_io_fn, default_error ) \ -{ r_out.status = default_error;\ - prs_init( &q_ps, MAX_PDU_FRAG_LEN, ctx, MARSHALL ); \ - prs_init( &r_ps, 0, ctx, UNMARSHALL );\ +{\ + SMB_ASSERT(pcli->pipe_idx == p_idx); \ + if (!prs_init( &q_ps, RPC_MAX_PDU_FRAG_LEN, ctx, MARSHALL )) { \ + return WERR_NOMEM;\ + }\ + if (!prs_init( &r_ps, 0, ctx, UNMARSHALL )) {\ + prs_mem_free( &q_ps );\ + return WERR_NOMEM;\ + }\ if ( q_io_fn("", &q_in, &q_ps, 0) ) {\ - if ( rpc_api_pipe_req_int(pcli, opnum, &q_ps, &r_ps) ) {\ - if (!r_io_fn("", &r_out, &r_ps, 0)) {\ - r_out.status = default_error;\ - }\ + NTSTATUS _smb_pipe_stat_ = rpc_api_pipe_req(pcli, opnum, &q_ps, &r_ps); \ + if (!NT_STATUS_IS_OK(_smb_pipe_stat_)) {\ + prs_mem_free( &q_ps );\ + prs_mem_free( &r_ps );\ + return ntstatus_to_werror(_smb_pipe_stat_);\ + }\ + if (!r_io_fn("", &r_out, &r_ps, 0)) {\ + prs_mem_free( &q_ps );\ + prs_mem_free( &r_ps );\ + return default_error;\ }\ + } else {\ + prs_mem_free( &q_ps );\ + prs_mem_free( &r_ps );\ + return default_error;\ }\ prs_mem_free( &q_ps );\ prs_mem_free( &r_ps );\ diff --git a/source3/include/rpc_dce.h b/source3/include/rpc_dce.h index 88b8380870e..3de4d2b691e 100644 --- a/source3/include/rpc_dce.h +++ b/source3/include/rpc_dce.h @@ -23,9 +23,6 @@ #ifndef _DCE_RPC_H /* _DCE_RPC_H */ #define _DCE_RPC_H -#include "rpc_misc.h" /* this only pulls in STRHDR */ - - /* DCE/RPC packet types */ enum RPC_PKT_TYPE { @@ -37,7 +34,7 @@ enum RPC_PKT_TYPE { RPC_BINDNACK = 0x0D, RPC_ALTCONT = 0x0E, RPC_ALTCONTRESP = 0x0F, - RPC_BINDRESP = 0x10 /* not the real name! this is undocumented! */ + RPC_AUTH3 = 0x10 /* not the real name! this is undocumented! */ }; /* DCE/RPC flags */ @@ -45,29 +42,41 @@ enum RPC_PKT_TYPE { #define RPC_FLG_LAST 0x02 #define RPC_FLG_NOCALL 0x20 + #define SMBD_NTLMSSP_NEG_FLAGS 0x000082b1 /* ALWAYS_SIGN|NEG_NTLM|NEG_LM|NEG_SEAL|NEG_SIGN|NEG_UNICODE */ /* NTLMSSP signature version */ #define NTLMSSP_SIGN_VERSION 0x01 -/* NTLMSSP auth type */ -#define NTLMSSP_AUTH_TYPE 0xa +/* DCE RPC auth types - extended by Microsoft. */ +#define RPC_ANONYMOUS_AUTH_TYPE 0 +#define RPC_AUTH_TYPE_KRB5_1 1 +#define RPC_SPNEGO_AUTH_TYPE 9 +#define RPC_NTLMSSP_AUTH_TYPE 10 +#define RPC_KRB5_AUTH_TYPE 16 /* Not yet implemented. */ +#define RPC_SCHANNEL_AUTH_TYPE 68 /* 0x44 */ /* DCE-RPC standard identifiers to indicate signing or sealing of an RPC pipe */ +#define RPC_AUTH_LEVEL_NONE 1 +#define RPC_AUTH_LEVEL_CONNECT 2 +#define RPC_AUTH_LEVEL_CALL 3 +#define RPC_AUTH_LEVEL_PACKET 4 +#define RPC_AUTH_LEVEL_INTEGRITY 5 +#define RPC_AUTH_LEVEL_PRIVACY 6 + +#if 0 #define RPC_PIPE_AUTH_SIGN_LEVEL 0x5 #define RPC_PIPE_AUTH_SEAL_LEVEL 0x6 +#endif /* Netlogon schannel auth type and level */ -#define NETSEC_AUTH_TYPE 0x44 -#define NETSEC_SIGN_SIGNATURE { 0x77, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 } -#define NETSEC_SEAL_SIGNATURE { 0x77, 0x00, 0x7a, 0x00, 0xff, 0xff, 0x00, 0x00 } +#define SCHANNEL_SIGN_SIGNATURE { 0x77, 0x00, 0xff, 0xff, 0xff, 0xff, 0x00, 0x00 } +#define SCHANNEL_SEAL_SIGNATURE { 0x77, 0x00, 0x7a, 0x00, 0xff, 0xff, 0x00, 0x00 } -#define RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN 0x20 -#define RPC_AUTH_NETSEC_SIGN_ONLY_CHK_LEN 0x18 +#define RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN 0x20 +#define RPC_AUTH_SCHANNEL_SIGN_ONLY_CHK_LEN 0x18 -/* SPNEGO auth type. */ -#define SPNEGO_AUTH_TYPE 0x9 /* The 7 here seems to be required to get Win2k not to downgrade us to NT4. Actually, anything other than 1ff would seem to do... */ @@ -76,20 +85,17 @@ enum RPC_PKT_TYPE { #define NETLOGON_NEG_SCHANNEL 0x40000000 #define NETLOGON_NEG_DOMAIN_TRUST_ACCOUNT 0x2010b000 -enum netsec_direction { +enum schannel_direction { SENDER_IS_INITIATOR, SENDER_IS_ACCEPTOR }; -/* Internal Flags to indicate what type of authentication on the pipe */ -#define AUTH_PIPE_SIGN 0x0001 -#define AUTH_PIPE_SEAL 0x0002 -#define AUTH_PIPE_NTLMSSP 0x0004 -#define AUTH_PIPE_NETSEC 0x0008 +/* Maximum size of the signing data in a fragment. */ +#define RPC_MAX_SIGN_SIZE 0x20 /* 32 */ /* Maximum PDU fragment size. */ /* #define MAX_PDU_FRAG_LEN 0x1630 this is what wnt sets */ -#define MAX_PDU_FRAG_LEN 0x10b8 /* this is what w2k sets */ +#define RPC_MAX_PDU_FRAG_LEN 0x10b8 /* this is what w2k sets */ /* RPC_IFACE */ typedef struct rpc_iface_info { @@ -163,7 +169,7 @@ typedef struct rpc_addr_info { fstring str; /* the string above in single byte, null terminated form */ } RPC_ADDR_STR; -/* RPC_HDR_BBA */ +/* RPC_HDR_BBA - bind acknowledge, and alter context response. */ typedef struct rpc_hdr_bba_info { uint16 max_tsize; /* maximum transmission fragment size (0x1630) */ uint16 max_rsize; /* max receive fragment size (0x1630) */ @@ -183,39 +189,24 @@ typedef struct rpc_hdr_auth_info { #define RPC_HDR_AUTH_LEN 8 -/* RPC_HDR_AUTHA */ -typedef struct rpc_hdr_autha_info { - uint16 max_tsize; /* maximum transmission fragment size (0x1630) */ - uint16 max_rsize; /* max receive fragment size (0x1630) */ - RPC_HDR_AUTH auth; -} RPC_HDR_AUTHA; - -#define RPC_HDR_AUTHA_LEN (RPC_HDR_AUTH_LEN+4) - /* this is TEMPORARILY coded up as a specific structure */ /* this structure comes after the bind request */ -/* RPC_AUTH_NETSEC_NEG */ -typedef struct rpc_auth_netsec_neg_info { +/* RPC_AUTH_SCHANNEL_NEG */ +typedef struct rpc_auth_schannel_neg_info { uint32 type1; /* Always zero ? */ uint32 type2; /* Types 0x3 and 0x13 seen. Check AcquireSecurityContext() docs.... */ fstring domain; /* calling workstations's domain */ fstring myname; /* calling workstation's name */ -} RPC_AUTH_NETSEC_NEG; +} RPC_AUTH_SCHANNEL_NEG; /* attached to the end of encrypted rpc requests and responses */ -/* RPC_AUTH_NETSEC_CHK */ -typedef struct rpc_auth_netsec_chk_info { +/* RPC_AUTH_SCHANNEL_CHK */ +typedef struct rpc_auth_schannel_chk_info { uint8 sig [8]; /* 77 00 7a 00 ff ff 00 00 */ uint8 packet_digest[8]; /* checksum over the packet, MD5'ed with session key */ uint8 seq_num[8]; /* verifier, seq num */ uint8 confounder[8]; /* random 8-byte nonce */ -} RPC_AUTH_NETSEC_CHK; - -struct netsec_auth_struct { - uchar sess_key[16]; - uint32 seq_num; - int auth_flags; -}; +} RPC_AUTH_SCHANNEL_CHK; typedef struct rpc_context { uint16 context_id; /* presentation context identifier. */ @@ -268,60 +259,4 @@ typedef struct rpc_auth_verif_info { uint32 msg_type; /* NTLMSSP_MESSAGE_TYPE (1,2,3) and 5 for schannel */ } RPC_AUTH_VERIFIER; -/* this is TEMPORARILY coded up as a specific structure */ -/* this structure comes after the bind request */ -/* RPC_AUTH_NTLMSSP_NEG */ - -typedef struct rpc_auth_ntlmssp_neg_info { - uint32 neg_flgs; /* 0x0000 b2b3 */ - - STRHDR hdr_myname; /* offset is against START of this structure */ - STRHDR hdr_domain; /* offset is against START of this structure */ - - fstring myname; /* calling workstation's name */ - fstring domain; /* calling workstations's domain */ -} RPC_AUTH_NTLMSSP_NEG; - -/* this is TEMPORARILY coded up as a specific structure */ -/* this structure comes after the bind acknowledgement */ -/* RPC_AUTH_NTLMSSP_CHAL */ -typedef struct rpc_auth_ntlmssp_chal_info { - uint32 unknown_1; /* 0x0000 0000 */ - uint32 unknown_2; /* 0x0000 0028 */ - uint32 neg_flags; /* 0x0000 82b1 */ - - uint8 challenge[8]; /* ntlm challenge */ - uint8 reserved [8]; /* zeros */ -} RPC_AUTH_NTLMSSP_CHAL; - - -/* RPC_AUTH_NTLMSSP_RESP */ -typedef struct rpc_auth_ntlmssp_resp_info { - STRHDR hdr_lm_resp; /* 24 byte response */ - STRHDR hdr_nt_resp; /* 24 byte response */ - STRHDR hdr_domain; - STRHDR hdr_usr; - STRHDR hdr_wks; - STRHDR hdr_sess_key; /* NULL unless negotiated */ - uint32 neg_flags; /* 0x0000 82b1 */ - - fstring sess_key; - fstring wks; - fstring user; - fstring domain; - fstring nt_resp; - fstring lm_resp; -} RPC_AUTH_NTLMSSP_RESP; - -/* attached to the end of encrypted rpc requests and responses */ -/* RPC_AUTH_NTLMSSP_CHK */ -typedef struct rpc_auth_ntlmssp_chk_info { - uint32 ver; /* 0x0000 0001 */ - uint32 reserved; - uint32 crc32; /* checksum using 0xEDB8 8320 as a polynomial */ - uint32 seq_num; -} RPC_AUTH_NTLMSSP_CHK; - -#define RPC_AUTH_NTLMSSP_CHK_LEN 16 - #endif /* _DCE_RPC_H */ diff --git a/source3/include/rpc_dfs.h b/source3/include/rpc_dfs.h index 39316a5d541..7aee208c14b 100644 --- a/source3/include/rpc_dfs.h +++ b/source3/include/rpc_dfs.h @@ -34,164 +34,131 @@ #define DFSFLAG_ADD_VOLUME 0x00000001 #define DFSFLAG_RESTORE_VOLUME 0x00000002 -typedef struct dfs_q_dfs_exist -{ - uint32 dummy; -} -DFS_Q_DFS_EXIST; +typedef struct dfs_q_dfs_exist { + uint32 dummy; +} DFS_Q_DFS_EXIST; /* status == 1 if dfs exists. */ -typedef struct dfs_r_dfs_exist -{ +typedef struct dfs_r_dfs_exist { uint32 status; /* Not a WERROR or NTSTATUS code */ -} -DFS_R_DFS_EXIST; - -typedef struct dfs_q_dfs_add -{ - uint32 ptr_DfsEntryPath; - UNISTR2 DfsEntryPath; - uint32 ptr_ServerName; - UNISTR2 ServerName; - uint32 ptr_ShareName; - UNISTR2 ShareName; - uint32 ptr_Comment; - UNISTR2 Comment; - uint32 Flags; -} -DFS_Q_DFS_ADD; - -typedef struct dfs_r_dfs_add -{ - WERROR status; -} -DFS_R_DFS_ADD; +} DFS_R_DFS_EXIST; + +typedef struct dfs_q_dfs_add { + uint32 ptr_DfsEntryPath; + UNISTR2 DfsEntryPath; + uint32 ptr_ServerName; + UNISTR2 ServerName; + uint32 ptr_ShareName; + UNISTR2 ShareName; + uint32 ptr_Comment; + UNISTR2 Comment; + uint32 Flags; +} DFS_Q_DFS_ADD; + +typedef struct dfs_r_dfs_add { + WERROR status; +} DFS_R_DFS_ADD; /********************************************/ -typedef struct dfs_q_dfs_remove -{ - UNISTR2 DfsEntryPath; - uint32 ptr_ServerName; - UNISTR2 ServerName; - uint32 ptr_ShareName; - UNISTR2 ShareName; -} -DFS_Q_DFS_REMOVE; - -typedef struct dfs_r_dfs_remove -{ - WERROR status; -} -DFS_R_DFS_REMOVE; +typedef struct dfs_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; - UNISTR2 comment; - uint32 state; - uint32 num_storages; -} -DFS_INFO_2; - -typedef struct dfs_storage_info -{ - uint32 state; - uint32 ptr_servername; - UNISTR2 servername; - uint32 ptr_sharename; - UNISTR2 sharename; -} -DFS_STORAGE_INFO; - -typedef struct dfs_info_3 -{ - uint32 ptr_entrypath; - UNISTR2 entrypath; - uint32 ptr_comment; - UNISTR2 comment; - uint32 state; - uint32 num_storages; - uint32 ptr_storages; - uint32 num_storage_infos; - DFS_STORAGE_INFO* storages; -} -DFS_INFO_3; - -typedef struct dfs_info_ctr -{ +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; + UNISTR2 comment; + uint32 state; + uint32 num_storages; +} DFS_INFO_2; + +typedef struct dfs_storage_info { + uint32 state; + uint32 ptr_servername; + UNISTR2 servername; + uint32 ptr_sharename; + UNISTR2 sharename; +} DFS_STORAGE_INFO; + +typedef struct dfs_info_3 { + uint32 ptr_entrypath; + UNISTR2 entrypath; + uint32 ptr_comment; + UNISTR2 comment; + uint32 state; + uint32 num_storages; + uint32 ptr_storages; + uint32 num_storage_infos; + DFS_STORAGE_INFO* storages; +} DFS_INFO_3; + +typedef struct dfs_info_ctr { + uint32 switch_value; + uint32 num_entries; + uint32 ptr_dfs_ctr; /* pointer to dfs info union */ + union { + DFS_INFO_1 *info1; + DFS_INFO_2 *info2; + DFS_INFO_3 *info3; + } dfs; +} DFS_INFO_CTR; + +typedef struct dfs_q_dfs_get_info { + UNISTR2 uni_path; - uint32 switch_value; - uint32 num_entries; - uint32 ptr_dfs_ctr; /* pointer to dfs info union */ - union - { - DFS_INFO_1 *info1; - DFS_INFO_2 *info2; - DFS_INFO_3 *info3; - } dfs; -} -DFS_INFO_CTR; - -typedef struct dfs_q_dfs_get_info -{ - UNISTR2 uni_path; - - uint32 ptr_server; - UNISTR2 uni_server; + uint32 ptr_server; + UNISTR2 uni_server; - uint32 ptr_share; - UNISTR2 uni_share; + uint32 ptr_share; + UNISTR2 uni_share; - uint32 level; -} -DFS_Q_DFS_GET_INFO; - -typedef struct dfs_r_dfs_get_info -{ - uint32 level; - uint32 ptr_ctr; - DFS_INFO_CTR ctr; - WERROR status; -} -DFS_R_DFS_GET_INFO; - -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 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; - WERROR status; -} -DFS_R_DFS_ENUM; - + uint32 level; +} DFS_Q_DFS_GET_INFO; + +typedef struct dfs_r_dfs_get_info { + uint32 level; + uint32 ptr_ctr; + DFS_INFO_CTR ctr; + WERROR status; +} DFS_R_DFS_GET_INFO; + +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 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; + WERROR status; +} DFS_R_DFS_ENUM; #endif diff --git a/source3/include/rpc_ds.h b/source3/include/rpc_ds.h index e06918730a4..24bf1e948a3 100644 --- a/source3/include/rpc_ds.h +++ b/source3/include/rpc_ds.h @@ -21,9 +21,6 @@ #ifndef _RPC_DS_H /* _RPC_LSA_H */ #define _RPC_DS_H -#include "rpc_misc.h" - - /* Opcodes available on PIPE_LSARPC_DS */ #define DS_GETPRIMDOMINFO 0x00 diff --git a/source3/include/rpc_eventlog.h b/source3/include/rpc_eventlog.h index b692a762257..7ce1199b213 100644 --- a/source3/include/rpc_eventlog.h +++ b/source3/include/rpc_eventlog.h @@ -47,77 +47,74 @@ #define EVENTLOG_AUDIT_FAILURE 0x0010 -typedef struct eventlog_q_open_eventlog -{ - uint32 unknown1; +/***********************************/ + +typedef struct { + uint16 unknown1; uint16 unknown2; - uint16 unknown3; - uint16 sourcename_length; - uint16 sourcename_size; - uint32 sourcename_ptr; - UNISTR2 sourcename; - uint32 servername_ptr; - UNISTR2 servername; -} -EVENTLOG_Q_OPEN_EVENTLOG; - -typedef struct eventlog_r_open_eventlog -{ +} EVENTLOG_OPEN_UNKNOWN0; + +typedef struct { + EVENTLOG_OPEN_UNKNOWN0 *unknown0; + UNISTR4 logname; + UNISTR4 servername; + uint32 unknown1; + uint32 unknown2; +} EVENTLOG_Q_OPEN_EVENTLOG; + +typedef struct { POLICY_HND handle; WERROR status; -} -EVENTLOG_R_OPEN_EVENTLOG; +} EVENTLOG_R_OPEN_EVENTLOG; -typedef struct eventlog_q_close_eventlog -{ + +/***********************************/ + +typedef struct { POLICY_HND handle; -} -EVENTLOG_Q_CLOSE_EVENTLOG; +} EVENTLOG_Q_CLOSE_EVENTLOG; -typedef struct eventlog_r_close_eventlog -{ +typedef struct { POLICY_HND handle; WERROR status; -} -EVENTLOG_R_CLOSE_EVENTLOG; +} EVENTLOG_R_CLOSE_EVENTLOG; -typedef struct eventlog_q_get_num_records -{ + +/***********************************/ + +typedef struct { POLICY_HND handle; -} -EVENTLOG_Q_GET_NUM_RECORDS; +} EVENTLOG_Q_GET_NUM_RECORDS; -typedef struct eventlog_r_get_num_records -{ +typedef struct { uint32 num_records; WERROR status; -} -EVENTLOG_R_GET_NUM_RECORDS; +} EVENTLOG_R_GET_NUM_RECORDS; -typedef struct eventlog_q_get_oldest_entry -{ + +/***********************************/ + +typedef struct { POLICY_HND handle; -} -EVENTLOG_Q_GET_OLDEST_ENTRY; +} EVENTLOG_Q_GET_OLDEST_ENTRY; -typedef struct eventlog_r_get_oldest_entry -{ +typedef struct { uint32 oldest_entry; WERROR status; -} -EVENTLOG_R_GET_OLDEST_ENTRY; +} EVENTLOG_R_GET_OLDEST_ENTRY; + -typedef struct eventlog_q_read_eventlog +/***********************************/ + +typedef struct { POLICY_HND handle; uint32 flags; uint32 offset; uint32 max_read_size; -} -EVENTLOG_Q_READ_EVENTLOG; +} EVENTLOG_Q_READ_EVENTLOG; -typedef struct eventlog_record -{ +typedef struct { uint32 length; uint32 reserved1; uint32 record_number; @@ -136,8 +133,7 @@ typedef struct eventlog_record uint32 data_offset; } Eventlog_record; -typedef struct eventlog_data_record -{ +typedef struct { uint32 source_name_len; wpstring source_name; uint32 computer_name_len; @@ -151,8 +147,7 @@ typedef struct eventlog_data_record uint32 data_padding; } Eventlog_data_record; -typedef struct eventlog_entry -{ +typedef struct eventlog_entry { Eventlog_record record; Eventlog_data_record data_record; uint8 *data; @@ -160,8 +155,7 @@ typedef struct eventlog_entry struct eventlog_entry *next; } Eventlog_entry; -typedef struct eventlog_r_read_eventlog -{ +typedef struct { uint32 num_bytes_in_resp; uint32 bytes_in_next_record; uint32 num_records; @@ -170,24 +164,18 @@ typedef struct eventlog_r_read_eventlog uint32 sent_size; uint32 real_size; WERROR status; -} -EVENTLOG_R_READ_EVENTLOG; +} EVENTLOG_R_READ_EVENTLOG; -typedef struct eventlog_q_clear_eventlog -{ + +/***********************************/ + +typedef struct { POLICY_HND handle; - uint32 unknown1; - uint16 backup_file_length; - uint16 backup_file_size; - uint32 backup_file_ptr; - UNISTR2 backup_file; -} -EVENTLOG_Q_CLEAR_EVENTLOG; - -typedef struct eventlog_r_clear_eventlog -{ + UNISTR4 backupfile; +} EVENTLOG_Q_CLEAR_EVENTLOG; + +typedef struct { WERROR status; -} -EVENTLOG_R_CLEAR_EVENTLOG; +} EVENTLOG_R_CLEAR_EVENTLOG; #endif /* _RPC_EVENTLOG_H */ diff --git a/source3/include/rpc_lsa.h b/source3/include/rpc_lsa.h index 053a23b2185..dd255c28d5d 100644 --- a/source3/include/rpc_lsa.h +++ b/source3/include/rpc_lsa.h @@ -24,8 +24,6 @@ #ifndef _RPC_LSA_H /* _RPC_LSA_H */ #define _RPC_LSA_H -#include "rpc_misc.h" - /* Opcodes available on PIPE_LSARPC */ #if 0 /* UNIMPLEMENTED */ diff --git a/source3/include/rpc_misc.h b/source3/include/rpc_misc.h index 9f35450d952..e5d91c1b630 100644 --- a/source3/include/rpc_misc.h +++ b/source3/include/rpc_misc.h @@ -21,9 +21,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "ntdomain.h" -#include "rpc_dce.h" - #ifndef _RPC_MISC_H /* _RPC_MISC_H */ #define _RPC_MISC_H @@ -302,8 +299,7 @@ typedef struct { **********************************************************************/ /* DOM_CLNT_SRV - client / server names */ -typedef struct clnt_srv_info -{ +typedef struct clnt_srv_info { uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */ UNISTR2 uni_logon_srv; /* logon server name */ uint32 undoc_buffer2; /* undocumented 32 bit buffer pointer */ @@ -311,8 +307,7 @@ typedef struct clnt_srv_info } DOM_CLNT_SRV; /* DOM_LOG_INFO - login info */ -typedef struct log_info -{ +typedef struct log_info { uint32 undoc_buffer; /* undocumented 32 bit buffer pointer */ UNISTR2 uni_logon_srv; /* logon server name */ UNISTR2 uni_acct_name; /* account name */ @@ -321,89 +316,44 @@ typedef struct log_info } DOM_LOG_INFO; /* DOM_CHAL - challenge info */ -typedef struct chal_info -{ +typedef struct chal_info { uchar data[8]; /* credentials */ } DOM_CHAL; /* DOM_CREDs - timestamped client or server credentials */ -typedef struct cred_info -{ +typedef struct cred_info { DOM_CHAL challenge; /* credentials */ UTIME timestamp; /* credential time-stamp */ } DOM_CRED; /* DOM_CLNT_INFO - client info */ -typedef struct clnt_info -{ +typedef struct clnt_info { DOM_LOG_INFO login; DOM_CRED cred; } DOM_CLNT_INFO; /* DOM_CLNT_INFO2 - client info */ -typedef struct clnt_info2 -{ +typedef struct clnt_info2 { DOM_CLNT_SRV login; uint32 ptr_cred; DOM_CRED cred; } DOM_CLNT_INFO2; /* DOM_LOGON_ID - logon id */ -typedef struct logon_info -{ +typedef struct logon_info { uint32 low; uint32 high; } DOM_LOGON_ID; /* OWF INFO */ -typedef struct owf_info -{ +typedef struct owf_info { uint8 data[16]; } OWF_INFO; - - - - -/* - * A client connection's state, pipe name, - * user credentials, etc... - */ -typedef struct _cli_auth_fns cli_auth_fns; -struct user_creds; -struct cli_connection { - - char *srv_name; - char *pipe_name; - struct user_creds usr_creds; - - struct cli_state *pCli_state; - - cli_auth_fns *auth; - - void *auth_info; - void *auth_creds; -}; - - -/* - * Associate a POLICY_HND with a cli_connection - */ -typedef struct rpc_hnd_node { - - POLICY_HND hnd; - struct cli_connection *cli; - -} RPC_HND_NODE; - typedef struct uint64_s { uint32 low; uint32 high; } UINT64_S; - - - - #endif /* _RPC_MISC_H */ diff --git a/source3/include/rpc_netlogon.h b/source3/include/rpc_netlogon.h index b3fe16ba2b3..b004e26397e 100644 --- a/source3/include/rpc_netlogon.h +++ b/source3/include/rpc_netlogon.h @@ -84,11 +84,22 @@ #define NL_CTRL_REPL_IN_PROGRESS 0x0002 #define NL_CTRL_FULL_SYNC 0x0004 +#define LOGON_EXTRA_SIDS 0x0020 +#define LOGON_RESOURCE_GROUPS 0x0200 + +#define SE_GROUP_MANDATORY 0x00000001 +#define SE_GROUP_ENABLED_BY_DEFAULT 0x00000002 +#define SE_GROUP_ENABLED 0x00000004 +#define SE_GROUP_OWNER 0x00000008 +#define SE_GROUP_USE_FOR_DENY_ONLY 0x00000010 +#define SE_GROUP_LOGON_ID 0xC0000000 +#define SE_GROUP_RESOURCE 0x20000000 + + #if 0 /* I think this is correct - it's what gets parsed on the wire. JRA. */ /* NET_USER_INFO_2 */ -typedef struct net_user_info_2 -{ +typedef struct net_user_info_2 { uint32 ptr_user_info; NTTIME logon_time; /* logon time */ @@ -145,8 +156,7 @@ typedef struct net_user_info_2 #endif /* NET_USER_INFO_3 */ -typedef struct net_user_info_3 -{ +typedef struct net_user_info_3 { uint32 ptr_user_info; NTTIME logon_time; /* logon time */ @@ -186,6 +196,13 @@ typedef struct net_user_info_3 uint32 num_other_sids; /* number of foreign/trusted domain sids */ uint32 buffer_other_sids; + /* The next three uint32 are not really part of user_info_3 but here + * for parsing convenience. They are only valid in Kerberos PAC + * parsing - Guenther */ + uint32 ptr_res_group_dom_sid; + uint32 res_group_count; + uint32 ptr_res_groups; + UNISTR2 uni_user_name; /* username unicode string */ UNISTR2 uni_full_name; /* user's full name unicode string */ UNISTR2 uni_logon_script; /* logon script unicode string */ @@ -203,32 +220,26 @@ typedef struct net_user_info_3 DOM_SID2 *other_sids; /* foreign/trusted domain SIDs */ uint32 *other_sids_attrib; - } NET_USER_INFO_3; /* NETLOGON_INFO_1 - pdc status info, i presume */ -typedef struct netlogon_1_info -{ +typedef struct netlogon_1_info { uint32 flags; /* 0x0 - undocumented */ uint32 pdc_status; /* 0x0 - undocumented */ - } NETLOGON_INFO_1; /* NETLOGON_INFO_2 - pdc status info, plus trusted domain info */ -typedef struct netlogon_2_info -{ +typedef struct netlogon_2_info { uint32 flags; /* 0x0 - undocumented */ uint32 pdc_status; /* 0x0 - undocumented */ uint32 ptr_trusted_dc_name; /* pointer to trusted domain controller name */ uint32 tc_status; UNISTR2 uni_trusted_dc_name; /* unicode string - trusted dc name */ - } NETLOGON_INFO_2; /* NETLOGON_INFO_3 - logon status info, i presume */ -typedef struct netlogon_3_info -{ +typedef struct netlogon_3_info { uint32 flags; /* 0x0 - undocumented */ uint32 logon_attempts; /* number of logon attempts */ uint32 reserved_1; /* 0x0 - undocumented */ @@ -236,7 +247,6 @@ typedef struct netlogon_3_info uint32 reserved_3; /* 0x0 - undocumented */ uint32 reserved_4; /* 0x0 - undocumented */ uint32 reserved_5; /* 0x0 - undocumented */ - } NETLOGON_INFO_3; /******************************************************** @@ -250,8 +260,7 @@ typedef struct netlogon_3_info /* NET_Q_LOGON_CTRL - LSA Netr Logon Control */ -typedef struct net_q_logon_ctrl_info -{ +typedef struct net_q_logon_ctrl_info { uint32 ptr; UNISTR2 uni_server_name; uint32 function_code; @@ -260,8 +269,7 @@ typedef struct net_q_logon_ctrl_info /* NET_R_LOGON_CTRL - LSA Netr Logon Control */ -typedef struct net_r_logon_ctrl_info -{ +typedef struct net_r_logon_ctrl_info { uint32 switch_value; uint32 ptr; @@ -273,22 +281,18 @@ typedef struct net_r_logon_ctrl_info } NET_R_LOGON_CTRL; -typedef struct ctrl_data_info_5 -{ +typedef struct ctrl_data_info_5 { uint32 function_code; uint32 ptr_domain; UNISTR2 domain; - } CTRL_DATA_INFO_5; -typedef struct ctrl_data_info_6 -{ +typedef struct ctrl_data_info_6 { uint32 function_code; uint32 ptr_domain; UNISTR2 domain; - } CTRL_DATA_INFO_6; @@ -301,8 +305,7 @@ typedef struct ctrl_data_info_6 ********************************************************/ /* NET_Q_LOGON_CTRL2 - LSA Netr Logon Control 2 */ -typedef struct net_q_logon_ctrl2_info -{ +typedef struct net_q_logon_ctrl2_info { uint32 ptr; /* undocumented buffer pointer */ UNISTR2 uni_server_name; /* server name, starting with two '\'s */ @@ -312,7 +315,6 @@ typedef struct net_q_logon_ctrl2_info CTRL_DATA_INFO_5 info5; CTRL_DATA_INFO_6 info6; } info; - } NET_Q_LOGON_CTRL2; /******************************************************* @@ -322,8 +324,7 @@ typedef struct net_q_logon_ctrl2_info *******************************************************/ /* NET_R_LOGON_CTRL2 - response to LSA Logon Control2 */ -typedef struct net_r_logon_ctrl2_info -{ +typedef struct net_r_logon_ctrl2_info { uint32 switch_value; /* 0x1, 0x3 */ uint32 ptr; @@ -336,13 +337,11 @@ typedef struct net_r_logon_ctrl2_info } logon; NTSTATUS status; /* return code */ - } NET_R_LOGON_CTRL2; /* NET_Q_GETDCNAME - Ask a DC for a trusted DC name */ -typedef struct net_q_getdcname -{ +typedef struct net_q_getdcname { uint32 ptr_logon_server; UNISTR2 uni_logon_server; uint32 ptr_domainname; @@ -351,103 +350,86 @@ typedef struct net_q_getdcname /* NET_R_GETDCNAME - Ask a DC for a trusted DC name */ -typedef struct net_r_getdcname -{ +typedef struct net_r_getdcname { uint32 ptr_dcname; UNISTR2 uni_dcname; NTSTATUS status; } NET_R_GETDCNAME; /* NET_Q_TRUST_DOM_LIST - LSA Query Trusted Domains */ -typedef struct net_q_trust_dom_info -{ +typedef struct net_q_trust_dom_info { uint32 ptr; /* undocumented buffer pointer */ UNISTR2 uni_server_name; /* server name, starting with two '\'s */ - } NET_Q_TRUST_DOM_LIST; #define MAX_TRUST_DOMS 1 /* NET_R_TRUST_DOM_LIST - response to LSA Trusted Domains */ -typedef struct net_r_trust_dom_info -{ +typedef struct net_r_trust_dom_info { UNISTR2 uni_trust_dom_name[MAX_TRUST_DOMS]; NTSTATUS status; /* return code */ - } NET_R_TRUST_DOM_LIST; /* NEG_FLAGS */ -typedef struct neg_flags_info -{ - uint32 neg_flags; /* negotiated flags */ - +typedef struct neg_flags_info { + uint32 neg_flags; /* negotiated flags */ } NEG_FLAGS; /* NET_Q_REQ_CHAL */ -typedef struct net_q_req_chal_info -{ - uint32 undoc_buffer; /* undocumented buffer pointer */ - UNISTR2 uni_logon_srv; /* logon server unicode string */ - UNISTR2 uni_logon_clnt; /* logon client unicode string */ - DOM_CHAL clnt_chal; /* client challenge */ - +typedef struct net_q_req_chal_info { + uint32 undoc_buffer; /* undocumented buffer pointer */ + UNISTR2 uni_logon_srv; /* logon server unicode string */ + UNISTR2 uni_logon_clnt; /* logon client unicode string */ + DOM_CHAL clnt_chal; /* client challenge */ } NET_Q_REQ_CHAL; /* NET_R_REQ_CHAL */ -typedef struct net_r_req_chal_info -{ +typedef struct net_r_req_chal_info { DOM_CHAL srv_chal; /* server challenge */ NTSTATUS status; /* return code */ } NET_R_REQ_CHAL; /* NET_Q_AUTH */ -typedef struct net_q_auth_info -{ +typedef struct net_q_auth_info { DOM_LOG_INFO clnt_id; /* client identification info */ DOM_CHAL clnt_chal; /* client-calculated credentials */ } NET_Q_AUTH; /* NET_R_AUTH */ -typedef struct net_r_auth_info -{ +typedef struct net_r_auth_info { DOM_CHAL srv_chal; /* server-calculated credentials */ NTSTATUS status; /* return code */ } NET_R_AUTH; /* NET_Q_AUTH_2 */ -typedef struct net_q_auth2_info -{ - DOM_LOG_INFO clnt_id; /* client identification info */ - DOM_CHAL clnt_chal; /* client-calculated credentials */ - - NEG_FLAGS clnt_flgs; /* usually 0x0000 01ff */ +typedef struct net_q_auth2_info { + DOM_LOG_INFO clnt_id; /* client identification info */ + DOM_CHAL clnt_chal; /* client-calculated credentials */ + NEG_FLAGS clnt_flgs; /* usually 0x0000 01ff */ } NET_Q_AUTH_2; /* NET_R_AUTH_2 */ -typedef struct net_r_auth2_info -{ +typedef struct net_r_auth2_info { DOM_CHAL srv_chal; /* server-calculated credentials */ NEG_FLAGS srv_flgs; /* usually 0x0000 01ff */ NTSTATUS status; /* return code */ } NET_R_AUTH_2; /* NET_Q_AUTH_3 */ -typedef struct net_q_auth3_info -{ - DOM_LOG_INFO clnt_id; /* client identification info */ - DOM_CHAL clnt_chal; /* client-calculated credentials */ - NEG_FLAGS clnt_flgs; /* usually 0x6007 ffff */ +typedef struct net_q_auth3_info { + DOM_LOG_INFO clnt_id; /* client identification info */ + DOM_CHAL clnt_chal; /* client-calculated credentials */ + NEG_FLAGS clnt_flgs; /* usually 0x6007 ffff */ } NET_Q_AUTH_3; /* NET_R_AUTH_3 */ -typedef struct net_r_auth3_info -{ +typedef struct net_r_auth3_info { DOM_CHAL srv_chal; /* server-calculated credentials */ NEG_FLAGS srv_flgs; /* usually 0x6007 ffff */ uint32 unknown; /* 0x0000045b */ @@ -456,25 +438,20 @@ typedef struct net_r_auth3_info /* NET_Q_SRV_PWSET */ -typedef struct net_q_srv_pwset_info -{ - DOM_CLNT_INFO clnt_id; /* client identification/authentication info */ - uint8 pwd[16]; /* new password - undocumented. */ - +typedef struct net_q_srv_pwset_info { + DOM_CLNT_INFO clnt_id; /* client identification/authentication info */ + uint8 pwd[16]; /* new password - undocumented. */ } NET_Q_SRV_PWSET; /* NET_R_SRV_PWSET */ -typedef struct net_r_srv_pwset_info -{ - DOM_CRED srv_cred; /* server-calculated credentials */ - - NTSTATUS status; /* return code */ +typedef struct net_r_srv_pwset_info { + DOM_CRED srv_cred; /* server-calculated credentials */ + NTSTATUS status; /* return code */ } NET_R_SRV_PWSET; /* NET_ID_INFO_2 */ -typedef struct net_network_info_2 -{ +typedef struct net_network_info_2 { uint32 ptr_id_info2; /* pointer to id_info_2 */ UNIHDR hdr_domain_name; /* domain name unicode header */ uint32 param_ctrl; /* param control (0x2) */ @@ -490,12 +467,10 @@ typedef struct net_network_info_2 UNISTR2 uni_wksta_name; /* workgroup name unicode string */ STRING2 nt_chal_resp; /* nt challenge response */ STRING2 lm_chal_resp; /* lm challenge response */ - } NET_ID_INFO_2; /* NET_ID_INFO_1 */ -typedef struct id_info_1 -{ +typedef struct id_info_1 { uint32 ptr_id_info1; /* pointer to id_info_1 */ UNIHDR hdr_domain_name; /* domain name unicode header */ uint32 param_ctrl; /* param control */ @@ -507,81 +482,64 @@ typedef struct id_info_1 UNISTR2 uni_domain_name; /* domain name unicode string */ UNISTR2 uni_user_name; /* user name unicode string */ UNISTR2 uni_wksta_name; /* workgroup name unicode string */ - } NET_ID_INFO_1; #define INTERACTIVE_LOGON_TYPE 1 #define NET_LOGON_TYPE 2 /* NET_ID_INFO_CTR */ -typedef struct net_id_info_ctr_info -{ - uint16 switch_value; - - union - { - NET_ID_INFO_1 id1; /* auth-level 1 - interactive user login */ - NET_ID_INFO_2 id2; /* auth-level 2 - workstation referred login */ - - } auth; +typedef struct net_id_info_ctr_info { + uint16 switch_value; + union { + NET_ID_INFO_1 id1; /* auth-level 1 - interactive user login */ + NET_ID_INFO_2 id2; /* auth-level 2 - workstation referred login */ + } auth; } NET_ID_INFO_CTR; /* SAM_INFO - sam logon/off id structure */ -typedef struct sam_info -{ - DOM_CLNT_INFO2 client; - uint32 ptr_rtn_cred; /* pointer to return credentials */ - DOM_CRED rtn_cred; /* return credentials */ - uint16 logon_level; - NET_ID_INFO_CTR *ctr; - +typedef struct sam_info { + DOM_CLNT_INFO2 client; + uint32 ptr_rtn_cred; /* pointer to return credentials */ + DOM_CRED rtn_cred; /* return credentials */ + uint16 logon_level; + NET_ID_INFO_CTR *ctr; } DOM_SAM_INFO; /* NET_Q_SAM_LOGON */ -typedef struct net_q_sam_logon_info -{ - DOM_SAM_INFO sam_id; +typedef struct net_q_sam_logon_info { + DOM_SAM_INFO sam_id; uint16 validation_level; - } NET_Q_SAM_LOGON; /* NET_R_SAM_LOGON */ -typedef struct net_r_sam_logon_info -{ - uint32 buffer_creds; /* undocumented buffer pointer */ - DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ +typedef struct net_r_sam_logon_info { + uint32 buffer_creds; /* undocumented buffer pointer */ + DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ uint16 switch_value; /* 3 - indicates type of USER INFO */ - NET_USER_INFO_3 *user; - - uint32 auth_resp; /* 1 - Authoritative response; 0 - Non-Auth? */ + NET_USER_INFO_3 *user; - NTSTATUS status; /* return code */ + uint32 auth_resp; /* 1 - Authoritative response; 0 - Non-Auth? */ + NTSTATUS status; /* return code */ } NET_R_SAM_LOGON; /* NET_Q_SAM_LOGOFF */ -typedef struct net_q_sam_logoff_info -{ - DOM_SAM_INFO sam_id; - +typedef struct net_q_sam_logoff_info { + DOM_SAM_INFO sam_id; } NET_Q_SAM_LOGOFF; /* NET_R_SAM_LOGOFF */ -typedef struct net_r_sam_logoff_info -{ - uint32 buffer_creds; /* undocumented buffer pointer */ - DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ - - NTSTATUS status; /* return code */ - +typedef struct net_r_sam_logoff_info { + uint32 buffer_creds; /* undocumented buffer pointer */ + DOM_CRED srv_creds; /* server credentials. server time stamp appears to be ignored. */ + NTSTATUS status; /* return code */ } NET_R_SAM_LOGOFF; /* NET_Q_SAM_SYNC */ -typedef struct net_q_sam_sync_info -{ +typedef struct net_q_sam_sync_info { UNISTR2 uni_srv_name; /* \\PDC */ UNISTR2 uni_cli_name; /* BDC */ DOM_CRED cli_creds; @@ -592,19 +550,16 @@ typedef struct net_q_sam_sync_info uint32 sync_context; uint32 max_size; /* preferred maximum length */ - } NET_Q_SAM_SYNC; /* SAM_DELTA_HDR */ -typedef struct sam_delta_hdr_info -{ +typedef struct sam_delta_hdr_info { uint16 type; /* type of structure attached */ uint16 type2; uint32 target_rid; uint32 type3; uint32 ptr_delta; - } SAM_DELTA_HDR; /* LOCKOUT_STRING */ @@ -617,7 +572,6 @@ typedef struct account_lockout_string { UINT64_S reset_count; uint32 bad_attempt_lockout; uint32 dummy; - } LOCKOUT_STRING; /* HDR_LOCKOUT_STRING */ @@ -625,12 +579,10 @@ typedef struct hdr_account_lockout_string { uint16 size; uint16 length; uint32 buffer; - } HDR_LOCKOUT_STRING; /* SAM_DOMAIN_INFO (0x1) */ -typedef struct sam_domain_info_info -{ +typedef struct sam_domain_info_info { UNIHDR hdr_dom_name; UNIHDR hdr_oem_info; @@ -666,13 +618,10 @@ typedef struct sam_domain_info_info uint32 unknown6; uint32 unknown7; uint32 unknown8; - - } SAM_DOMAIN_INFO; /* SAM_GROUP_INFO (0x2) */ -typedef struct sam_group_info_info -{ +typedef struct sam_group_info_info { UNIHDR hdr_grp_name; DOM_GID gid; UNIHDR hdr_grp_desc; @@ -682,12 +631,10 @@ typedef struct sam_group_info_info UNISTR2 uni_grp_name; UNISTR2 uni_grp_desc; RPC_DATA_BLOB buf_sec_desc; - } SAM_GROUP_INFO; /* SAM_PWD */ -typedef struct sam_passwd_info -{ +typedef struct sam_passwd_info { /* this structure probably contains password history */ /* this is probably a count of lm/nt pairs */ uint32 unk_0; /* 0x0000 0002 */ @@ -700,12 +647,10 @@ typedef struct sam_passwd_info UNIHDR hdr_empty_lm; UNIHDR hdr_empty_nt; - } SAM_PWD; /* SAM_ACCOUNT_INFO (0x5) */ -typedef struct sam_account_info_info -{ +typedef struct sam_account_info_info { UNIHDR hdr_acct_name; UNIHDR hdr_full_name; @@ -765,12 +710,10 @@ typedef struct sam_account_info_info SAM_PWD pass; RPC_DATA_BLOB buf_sec_desc; UNISTR2 uni_profile; - } SAM_ACCOUNT_INFO; /* SAM_GROUP_MEM_INFO (0x8) */ -typedef struct sam_group_mem_info_info -{ +typedef struct sam_group_mem_info_info { uint32 ptr_rids; uint32 ptr_attribs; uint32 num_members; @@ -785,8 +728,7 @@ typedef struct sam_group_mem_info_info } SAM_GROUP_MEM_INFO; /* SAM_ALIAS_INFO (0x9) */ -typedef struct sam_alias_info_info -{ +typedef struct sam_alias_info_info { UNIHDR hdr_als_name; uint32 als_rid; BUFHDR2 hdr_sec_desc; /* security descriptor */ @@ -796,12 +738,10 @@ typedef struct sam_alias_info_info UNISTR2 uni_als_name; RPC_DATA_BLOB buf_sec_desc; UNISTR2 uni_als_desc; - } SAM_ALIAS_INFO; /* SAM_ALIAS_MEM_INFO (0xC) */ -typedef struct sam_alias_mem_info_info -{ +typedef struct sam_alias_mem_info_info { uint32 num_members; uint32 ptr_members; uint8 unknown[16]; @@ -809,13 +749,11 @@ typedef struct sam_alias_mem_info_info uint32 num_sids; uint32 *ptr_sids; DOM_SID2 *sids; - } SAM_ALIAS_MEM_INFO; /* SAM_DELTA_POLICY (0x0D) */ -typedef struct -{ +typedef struct { uint32 max_log_size; /* 0x5000 */ UINT64_S audit_retention_period; /* 0 */ uint32 auditing_mode; /* 0 */ @@ -844,8 +782,7 @@ typedef struct } SAM_DELTA_POLICY; /* SAM_DELTA_TRUST_DOMS */ -typedef struct -{ +typedef struct { uint32 buf_size; SEC_DESC *sec_desc; DOM_SID2 sid; @@ -860,12 +797,10 @@ typedef struct uint32 unknown3; UNISTR2 domain; - } SAM_DELTA_TRUSTDOMS; /* SAM_DELTA_PRIVS (0x10) */ -typedef struct -{ +typedef struct { DOM_SID2 sid; uint32 priv_count; @@ -896,8 +831,7 @@ typedef struct } SAM_DELTA_PRIVS; /* SAM_DELTA_SECRET */ -typedef struct -{ +typedef struct { uint32 buf_size; SEC_DESC *sec_desc; UNISTR2 secret; @@ -928,19 +862,16 @@ typedef struct uint32 buf_size3; SEC_DESC *sec_desc2; - } SAM_DELTA_SECRET; /* SAM_DELTA_MOD_COUNT (0x16) */ -typedef struct -{ +typedef struct { uint32 seqnum; uint32 dom_mod_count_ptr; UINT64_S dom_mod_count; /* domain mod count at last sync */ } SAM_DELTA_MOD_COUNT; -typedef union sam_delta_ctr_info -{ +typedef union sam_delta_ctr_info { SAM_DOMAIN_INFO domain_info ; SAM_GROUP_INFO group_info ; SAM_ACCOUNT_INFO account_info; @@ -955,8 +886,7 @@ typedef union sam_delta_ctr_info } SAM_DELTA_CTR; /* NET_R_SAM_SYNC */ -typedef struct net_r_sam_sync_info -{ +typedef struct net_r_sam_sync_info { DOM_CRED srv_creds; uint32 sync_context; @@ -973,8 +903,7 @@ typedef struct net_r_sam_sync_info } NET_R_SAM_SYNC; /* NET_Q_SAM_DELTAS */ -typedef struct net_q_sam_deltas_info -{ +typedef struct net_q_sam_deltas_info { UNISTR2 uni_srv_name; UNISTR2 uni_cli_name; DOM_CRED cli_creds; @@ -984,12 +913,10 @@ typedef struct net_q_sam_deltas_info UINT64_S dom_mod_count; /* domain mod count at last sync */ uint32 max_size; /* preferred maximum length */ - } NET_Q_SAM_DELTAS; /* NET_R_SAM_DELTAS */ -typedef struct net_r_sam_deltas_info -{ +typedef struct net_r_sam_deltas_info { DOM_CRED srv_creds; UINT64_S dom_mod_count; /* new domain mod count */ diff --git a/source3/include/rpc_ntsvcs.h b/source3/include/rpc_ntsvcs.h new file mode 100644 index 00000000000..947794bba11 --- /dev/null +++ b/source3/include/rpc_ntsvcs.h @@ -0,0 +1,147 @@ +/* + Unix SMB/CIFS implementation. + SMB parameters and setup + Copyright (C) Gerald (Jerry) Carter 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. +*/ + +#ifndef _RPC_NTSVCS_H /* _RPC_NTSVCS_H */ +#define _RPC_NTSVCS_H + +/* ntsvcs pipe */ + +#define NTSVCS_GET_VERSION 0x02 +#define NTSVCS_VALIDATE_DEVICE_INSTANCE 0x06 +#define NTSVCS_GET_ROOT_DEVICE_INSTANCE 0x07 +#define NTSVCS_GET_DEVICE_LIST 0x0a +#define NTSVCS_GET_DEVICE_LIST_SIZE 0x0b +#define NTSVCS_GET_DEVICE_REG_PROPERTY 0x0d +#define NTSVCS_HW_PROFILE_FLAGS 0x28 +#define NTSVCS_GET_HW_PROFILE_INFO 0x29 +#define NTSVCS_GET_VERSION_INTERNAL 0x3e + + +/**************************/ + +typedef struct { + /* nothing in the request */ + uint32 dummy; +} NTSVCS_Q_GET_VERSION; + +typedef struct { + uint32 version; + WERROR status; +} NTSVCS_R_GET_VERSION; + + +/**************************/ + +typedef struct { + UNISTR2 *devicename; + uint32 flags; +} NTSVCS_Q_GET_DEVICE_LIST_SIZE; + +typedef struct { + uint32 size; + WERROR status; +} NTSVCS_R_GET_DEVICE_LIST_SIZE; + + +/**************************/ + +typedef struct { + UNISTR2 *devicename; + uint32 buffer_size; + uint32 flags; +} NTSVCS_Q_GET_DEVICE_LIST; + +typedef struct { + UNISTR2 devicepath; + uint32 needed; + WERROR status; +} NTSVCS_R_GET_DEVICE_LIST; + +/**************************/ + +typedef struct { + UNISTR2 devicepath; + uint32 flags; +} NTSVCS_Q_VALIDATE_DEVICE_INSTANCE; + +typedef struct { + WERROR status; +} NTSVCS_R_VALIDATE_DEVICE_INSTANCE; + +/**************************/ + +#define DEV_REGPROP_DESC 1 + +typedef struct { + UNISTR2 devicepath; + uint32 property; + uint32 unknown2; + uint32 buffer_size1; + uint32 buffer_size2; + uint32 unknown5; +} NTSVCS_Q_GET_DEVICE_REG_PROPERTY; + +typedef struct { + uint32 unknown1; + REGVAL_BUFFER value; + uint32 size; + uint32 needed; + WERROR status; +} NTSVCS_R_GET_DEVICE_REG_PROPERTY; + + +/**************************/ + +typedef struct { + uint32 index; + uint8 *buffer; + uint32 buffer_size; + uint32 unknown1; +} NTSVCS_Q_GET_HW_PROFILE_INFO; + +typedef struct { + uint32 buffer_size; /* the size (not included in the reply) + if just matched from the request */ + uint8 *buffer; + WERROR status; +} NTSVCS_R_GET_HW_PROFILE_INFO; + + +/**************************/ + +typedef struct { + uint32 unknown1; + UNISTR2 devicepath; + uint32 unknown2; + uint32 unknown3; + uint32 unknown4; + uint32 unknown5; + uint32 unknown6; + uint32 unknown7; +} NTSVCS_Q_HW_PROFILE_FLAGS; + +typedef struct { + uint32 unknown1; + uint32 unknown2; + uint32 unknown3; + WERROR status; +} NTSVCS_R_HW_PROFILE_FLAGS; + +#endif /* _RPC_NTSVCS_H */ diff --git a/source3/include/rpc_perfcount.h b/source3/include/rpc_perfcount.h new file mode 100644 index 00000000000..0e3a6eb0181 --- /dev/null +++ b/source3/include/rpc_perfcount.h @@ -0,0 +1,106 @@ +#ifndef _RPC_PERFCOUNT_H +#define _RPC_PERFCOUNT_H + +typedef struct perf_counter_definition +{ + /* sizeof(PERF_COUNTER_DEFINITION) */ + uint32 ByteLength; + uint32 CounterNameTitleIndex; + uint32 CounterNameTitlePointer; + uint32 CounterHelpTitleIndex; + uint32 CounterHelpTitlePointer; + uint32 DefaultScale; + uint32 DetailLevel; + uint32 CounterType; + uint32 CounterSize; + uint32 CounterOffset; +} +PERF_COUNTER_DEFINITION; + +typedef struct perf_counter_block +{ + /* Total size of the data block, including all data plus this header */ + uint32 ByteLength; + uint8 *data; +} +PERF_COUNTER_BLOCK; + +typedef struct perf_instance_definition +{ + /* Total size of the instance definition, including the length of the terminated Name string */ + uint32 ByteLength; + uint32 ParentObjectTitleIndex; + uint32 ParentObjectTitlePointer; + uint32 UniqueID; + /* From the start of the PERF_INSTANCE_DEFINITION, the byte offset to the start of the Name string */ + uint32 NameOffset; + uint32 NameLength; + /* Unicode string containing the name for the instance */ + uint8 *data; + PERF_COUNTER_BLOCK counter_data; +} +PERF_INSTANCE_DEFINITION; + +typedef struct perf_object_type +{ + /* Total size of the object block, including all PERF_INSTANCE_DEFINITIONs, + PERF_COUNTER_DEFINITIONs and PERF_COUNTER_BLOCKs in bytes */ + uint32 TotalByteLength; + /* Size of this PERF_OBJECT_TYPE plus all PERF_COUNTER_DEFINITIONs in bytes */ + uint32 DefinitionLength; + /* Size of this PERF_OBJECT_TYPE */ + uint32 HeaderLength; + uint32 ObjectNameTitleIndex; + uint32 ObjectNameTitlePointer; + uint32 ObjectHelpTitleIndex; + uint32 ObjectHelpTitlePointer; + uint32 DetailLevel; + uint32 NumCounters; + uint32 DefaultCounter; + uint32 NumInstances; + uint32 CodePage; + UINT64_S PerfTime; + UINT64_S PerfFreq; + PERF_COUNTER_DEFINITION *counters; + PERF_INSTANCE_DEFINITION *instances; + PERF_COUNTER_BLOCK counter_data; +} +PERF_OBJECT_TYPE; + +/* PerfCounter Inner Buffer structs */ +typedef struct perf_data_block +{ + /* hardcoded to read "P.E.R.F" */ + uint16 Signature[4]; + uint32 LittleEndian; + /* both currently hardcoded to 1 */ + uint32 Version; + uint32 Revision; + /* bytes of PERF_OBJECT_TYPE data, does NOT include the PERF_DATA_BLOCK */ + uint32 TotalByteLength; + /* size of PERF_DATA_BLOCK including the uint8 *data */ + uint32 HeaderLength; + /* number of PERF_OBJECT_TYPE structures encoded */ + uint32 NumObjectTypes; + uint32 DefaultObject; + SYSTEMTIME SystemTime; + /* This will guarantee that we're on a 64-bit boundary before we encode + PerfTime, and having it there will make my offset math much easier. */ + uint32 Padding; + /* Now when I'm marshalling this, I'll need to call prs_align_uint64() + before I start encodint the UINT64_S structs */ + /* clock rate * seconds uptime */ + UINT64_S PerfTime; + /* The clock rate of the CPU */ + UINT64_S PerfFreq; + /* used for high-res timers -- for now PerfTime * 10e7 */ + UINT64_S PerfTime100nSec; + uint32 SystemNameLength; + uint32 SystemNameOffset; + /* The SystemName, in unicode, terminated */ + uint8* data; + PERF_OBJECT_TYPE *objects; +} +PERF_DATA_BLOCK; + +#endif /* _RPC_PERFCOUNT_H */ diff --git a/source3/include/rpc_perfcount_defs.h b/source3/include/rpc_perfcount_defs.h new file mode 100644 index 00000000000..3999a6864d8 --- /dev/null +++ b/source3/include/rpc_perfcount_defs.h @@ -0,0 +1,73 @@ +#ifndef _RPC_PERFCOUNT_DEFS_H +#define _RPC_PERFCOUNT_DEFS_H + +/* + * The following #defines match what is in winperf.h. + * See that include file for more details, or look up + * "Performance Data Format" on MSDN + * + * Rather than including them in rpc_perfcount.h, they + * were broken out into a separate .h file so that they + * can be included by other programs that need this info + * without pulling in everything else samba-related. + */ + +#define PERF_NO_INSTANCES -1 +#define PERF_NO_UNIQUE_ID -1 + +/* These determine the data size */ +#define PERF_SIZE_DWORD 0x00000000 +#define PERF_SIZE_LARGE 0x00000100 +#define PERF_SIZE_ZERO 0x00000200 +#define PERF_SIZE_VARIABLE_LEN 0x00000300 + +/* These determine the usage of the counter */ +#define PERF_TYPE_NUMBER 0x00000000 +#define PERF_TYPE_COUNTER 0x00000400 +#define PERF_TYPE_TEXT 0x00000800 +#define PERF_TYPE_ZERO 0x00000C00 + +/* If PERF_TYPE_NUMBER was selected, these provide display information */ +#define PERF_NUMBER_HEX 0x00000000 +#define PERF_NUMBER_DECIMAL 0x00010000 +#define PERF_NUMBER_DEC_1000 0x00020000 + +/* If PERF_TYPE_COUNTER was selected, these provide display information */ +#define PERF_COUNTER_VALUE 0x00000000 +#define PERF_COUNTER_RATE 0x00010000 +#define PERF_COUNTER_FRACTION 0x00020000 +#define PERF_COUNTER_BASE 0x00030000 +#define PERF_COUNTER_ELAPSED 0x00040000 +#define PERF_COUNTER_QUEUELEN 0x00050000 +#define PERF_COUNTER_HISTOGRAM 0x00060000 +#define PERF_COUNTER_PRECISION 0x00070000 + +/* If PERF_TYPE_TEXT was selected, these provide display information */ +#define PERF_TEXT_UNICODE 0x00000000 +#define PERF_TEXT_ASCII 0x00010000 + +/* These provide information for which tick count to use when computing elapsed interval */ +#define PERF_TIMER_TICK 0x00000000 +#define PERF_TIMER_100NS 0x00100000 +#define PERF_OBJECT_TIMER 0x00200000 + +/* These affect how the data is manipulated prior to being displayed */ +#define PERF_DELTA_COUNTER 0x00400000 +#define PERF_DELTA_BASE 0x00800000 +#define PERF_INVERSE_COUNTER 0x01000000 +#define PERF_MULTI_COUNTER 0x02000000 + +/* These determine if any text gets added when the value is displayed */ +#define PERF_DISPLAY_NO_SUFFIX 0x00000000 +#define PERF_DISPLAY_PER_SEC 0x10000000 +#define PERF_DISPLAY_PERCENT 0x20000000 +#define PERF_DISPLAY_SECONDS 0x30000000 +#define PERF_DISPLAY_NOSHOW 0x40000000 + +/* These determine the DetailLevel of the counter */ +#define PERF_DETAIL_NOVICE 100 +#define PERF_DETAIL_ADVANCED 200 +#define PERF_DETAIL_EXPERT 300 +#define PERF_DETAIL_WIZARD 400 + +#endif /* _RPC_PERFCOUNT_DEFS_H */ diff --git a/source3/include/rpc_reg.h b/source3/include/rpc_reg.h index f6ddf5b9adf..b24b640237f 100644 --- a/source3/include/rpc_reg.h +++ b/source3/include/rpc_reg.h @@ -25,8 +25,6 @@ #ifndef _RPC_REG_H /* _RPC_REG_H */ #define _RPC_REG_H -#include "reg_objects.h" - /* RPC opnum */ #define REG_OPEN_HKCR 0x00 @@ -50,6 +48,7 @@ #define REG_SET_VALUE 0x16 #define REG_SHUTDOWN 0x18 #define REG_ABORT_SHUTDOWN 0x19 +#define REG_OPEN_HKPT 0x20 #define REG_GETVERSION 0x1a #define REG_SHUTDOWN_EX 0x1e @@ -63,6 +62,9 @@ #define KEY_HKLM "HKLM" #define KEY_HKU "HKU" #define KEY_HKCR "HKCR" +#define KEY_HKPD "HKPD" +#define KEY_HKPT "HKPT" +#define KEY_SERVICES "HKLM\\SYSTEM\\CurrentControlSet\\Services" #define KEY_PRINTING "HKLM\\SYSTEM\\CurrentControlSet\\Control\\Print" #define KEY_PRINTING_2K "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Print\\Printers" #define KEY_PRINTING_PORTS "HKLM\\SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Ports" @@ -85,6 +87,16 @@ #define REG_FULL_RESOURCE_DESCRIPTOR 9 #define REG_RESOURCE_REQUIREMENTS_LIST 10 +/* + * Registry key types + * Most keys are going to be GENERIC -- may need a better name? + * HKPD and HKPT are used by reg_perfcount.c + * they are special keys that congtain performance data + */ +#define REG_KEY_GENERIC 0 +#define REG_KEY_HKPD 1 +#define REG_KEY_HKPT 2 + /* * container for function pointers to enumeration routines * for vitural registry view @@ -108,9 +120,8 @@ typedef struct { /* structure to store the registry handles */ typedef struct _RegistryKey { - struct _RegistryKey *prev, *next; - - pstring name; /* full name of registry key */ + uint32 type; + char *name; /* full name of registry key */ uint32 access_granted; REGISTRY_HOOK *hook; } REGISTRY_KEY; diff --git a/source3/include/rpc_samr.h b/source3/include/rpc_samr.h index fb829558d44..6067587654e 100644 --- a/source3/include/rpc_samr.h +++ b/source3/include/rpc_samr.h @@ -26,8 +26,6 @@ #ifndef _RPC_SAMR_H /* _RPC_SAMR_H */ #define _RPC_SAMR_H -#include "rpc_misc.h" - /******************************************************************* the following information comes from a QuickView on samsrv.dll, and gives an idea of exactly what is needed: diff --git a/source3/include/rpc_secdes.h b/source3/include/rpc_secdes.h index b2b97e391e0..c385e41fd30 100644 --- a/source3/include/rpc_secdes.h +++ b/source3/include/rpc_secdes.h @@ -481,13 +481,16 @@ typedef struct standard_mapping { SC_RIGHT_MGR_ENUMERATE_SERVICE | \ SC_RIGHT_MGR_QUERY_LOCK_STATUS ) -#define SC_MANAGER_ALL_ACCESS \ +#define SC_MANAGER_EXECUTE_ACCESS SC_MANAGER_READ_ACCESS + +#define SC_MANAGER_WRITE_ACCESS \ ( STANDARD_RIGHTS_REQUIRED_ACCESS | \ SC_MANAGER_READ_ACCESS | \ SC_RIGHT_MGR_CREATE_SERVICE | \ SC_RIGHT_MGR_LOCK | \ SC_RIGHT_MGR_MODIFY_BOOT_CONFIG ) +#define SC_MANAGER_ALL_ACCESS SC_MANAGER_WRITE_ACCESS /* Service Object Bits */ @@ -515,12 +518,14 @@ typedef struct standard_mapping { SC_RIGHT_SVC_STOP | \ SC_RIGHT_SVC_PAUSE_CONTINUE ) -#define SERVICE_ALL_ACCESS \ +#define SERVICE_WRITE_ACCESS \ ( STANDARD_RIGHTS_REQUIRED_ACCESS | \ SERVICE_READ_ACCESS | \ SERVICE_EXECUTE_ACCESS | \ SC_RIGHT_SVC_CHANGE_CONFIG ) +#define SERVICE_ALL_ACCESS SERVICE_WRITE_ACCESS + /* diff --git a/source3/include/rpc_svcctl.h b/source3/include/rpc_svcctl.h index 77dd004fed4..443a6588a66 100644 --- a/source3/include/rpc_svcctl.h +++ b/source3/include/rpc_svcctl.h @@ -22,12 +22,15 @@ #ifndef _RPC_SVCCTL_H /* _RPC_SVCCTL_H */ #define _RPC_SVCCTL_H - /* svcctl pipe */ #define SVCCTL_CLOSE_SERVICE 0x00 #define SVCCTL_CONTROL_SERVICE 0x01 +#define SVCCTL_LOCK_SERVICE_DB 0x03 +#define SVCCTL_QUERY_SERVICE_SEC 0x04 /* not impmenented */ +#define SVCCTL_SET_SEVICE_SEC 0x05 /* not implemented */ #define SVCCTL_QUERY_STATUS 0x06 +#define SVCCTL_UNLOCK_SERVICE_DB 0x08 #define SVCCTL_ENUM_DEPENDENT_SERVICES_W 0x0d #define SVCCTL_ENUM_SERVICES_STATUS_W 0x0e #define SVCCTL_OPEN_SCMANAGER_W 0x0f @@ -105,14 +108,17 @@ #define SVCCTL_CONTROL_STOP 0x00000001 #define SVCCTL_CONTROL_PAUSE 0x00000002 #define SVCCTL_CONTROL_CONTINUE 0x00000003 -#define SVCCTL_CONTROL_SHUTDOWN 0x00000004 +#define SVCCTL_CONTROL_INTERROGATE 0x00000004 +#define SVCCTL_CONTROL_SHUTDOWN 0x00000005 #define SVC_HANDLE_IS_SCM 0x0000001 #define SVC_HANDLE_IS_SERVICE 0x0000002 +#define SVC_HANDLE_IS_DBLOCK 0x0000003 -#define SVC_STATUS_PROCESS_INFO 0x00000001 +#define SVC_STATUS_PROCESS_INFO 0x00000000 -#define SVCCTL_SCRIPT_DIR "/svcctl/" +/* where we assume the location of the service control scripts */ +#define SVCCTL_SCRIPT_DIR "svcctl" /* utility structures for RPCs */ @@ -127,13 +133,7 @@ typedef struct { } SERVICE_STATUS; typedef struct { - uint32 type; - uint32 state; - uint32 controls_accepted; - uint32 win32_exit_code; - uint32 service_exit_code; - uint32 check_point; - uint32 wait_hint; + SERVICE_STATUS status; uint32 process_id; uint32 service_flags; } SERVICE_STATUS_PROCESS; @@ -158,7 +158,8 @@ typedef struct { } SERVICE_CONFIG; typedef struct { - UNISTR2 *description; + uint32 unknown; + UNISTR description; } SERVICE_DESCRIPTION; typedef struct { @@ -168,20 +169,12 @@ typedef struct { typedef struct { uint32 reset_period; - UNISTR2 *rebootmsg; + UNISTR2 *rebootmsg; /* i have no idea if these are UNISTR2's. I can't get a good trace */ UNISTR2 *command; - uint32 nActions; - SC_ACTION *saActions; - UNISTR2 *description; + uint32 num_actions; + SC_ACTION *actions; } SERVICE_FAILURE_ACTIONS; - -typedef struct SCM_info_struct { - uint32 type; /* should be SVC_HANDLE_IS_SCM */ - pstring target_server_name; /* name of the server on which the operation is taking place */ - pstring target_db_name; /* name of the database that we're opening */ -} SCM_info; - typedef struct Service_info_struct { uint32 type; /* should be SVC_HANDLE_IS_SERVICE */ pstring servicename; /* the name of the service */ @@ -205,9 +198,9 @@ typedef struct Service_info_struct { typedef struct { /* functions for enumerating subkeys and values */ - WERROR (*stop_service)( SERVICE_STATUS *status ); - WERROR (*start_service) ( void ); - WERROR (*service_status)( SERVICE_STATUS *status ); + WERROR (*stop_service)( const char *service, SERVICE_STATUS *status ); + WERROR (*start_service) ( const char *service ); + WERROR (*service_status)( const char *service, SERVICE_STATUS *status ); } SERVICE_CONTROL_OPS; /* structure to store the service handle information */ @@ -341,6 +334,7 @@ typedef struct { WERROR status; } SVCCTL_R_ENUM_DEPENDENT_SERVICES; + /**************************/ typedef struct { @@ -354,32 +348,58 @@ typedef struct { WERROR status; } SVCCTL_R_QUERY_SERVICE_CONFIG; + +/**************************/ + typedef struct { POLICY_HND handle; - uint32 info_level; + uint32 level; uint32 buffer_size; } SVCCTL_Q_QUERY_SERVICE_CONFIG2; typedef struct { - UNISTR2 *description; - uint32 returned; + RPC_BUFFER buffer; uint32 needed; - uint32 offset; WERROR status; } SVCCTL_R_QUERY_SERVICE_CONFIG2; + +/**************************/ + typedef struct { POLICY_HND handle; - uint32 info_level; + uint32 level; uint32 buffer_size; } SVCCTL_Q_QUERY_SERVICE_STATUSEX; typedef struct { RPC_BUFFER buffer; - uint32 returned; uint32 needed; WERROR status; } SVCCTL_R_QUERY_SERVICE_STATUSEX; + +/**************************/ + +typedef struct { + POLICY_HND handle; +} SVCCTL_Q_LOCK_SERVICE_DB; + +typedef struct { + POLICY_HND h_lock; + WERROR status; +} SVCCTL_R_LOCK_SERVICE_DB; + + +/**************************/ + +typedef struct { + POLICY_HND h_lock; +} SVCCTL_Q_UNLOCK_SERVICE_DB; + +typedef struct { + WERROR status; +} SVCCTL_R_UNLOCK_SERVICE_DB; + #endif /* _RPC_SVCCTL_H */ diff --git a/source3/include/smb.h b/source3/include/smb.h index c0778383c65..61d2237b2dd 100644 --- a/source3/include/smb.h +++ b/source3/include/smb.h @@ -206,13 +206,13 @@ typedef smb_ucs2_t wfstring[FSTRING_LEN]; #define PI_SHUTDOWN 10 #define PI_SVCCTL 11 #define PI_EVENTLOG 12 -#define PI_MAX_PIPES 13 +#define PI_NTSVCS 13 +#define PI_MAX_PIPES 14 /* 64 bit time (100usec) since ????? - cifs6.txt, section 3.5, page 30 */ -typedef struct nttime_info -{ - uint32 low; - uint32 high; +typedef struct nttime_info { + uint32 low; + uint32 high; } NTTIME; @@ -414,6 +414,10 @@ struct fd_handle { */ }; +struct timed_event; +struct idle_event; +struct share_mode_entry; + typedef struct files_struct { struct files_struct *next, *prev; int fnum; @@ -437,6 +441,11 @@ typedef struct files_struct { time_t last_write_time; int oplock_type; int sent_oplock_break; + struct timed_event *oplock_timeout; + + struct share_mode_entry *pending_break_messages; + int num_pending_break_messages; + unsigned long file_id; BOOL can_lock; BOOL can_read; @@ -564,6 +573,7 @@ struct current_user #define NO_BREAK_SENT 0 #define BREAK_TO_NONE_SENT 1 #define LEVEL_II_BREAK_SENT 2 +#define ASYNC_LEVEL_II_BREAK_SENT 3 typedef struct { fstring smb_name; /* user name from the client */ @@ -619,28 +629,19 @@ struct interface struct in_addr nmask; }; -/* struct used by share mode violation error processing */ -typedef struct { - pid_t pid; - uint16 mid; - struct timeval time; - SMB_DEV_T dev; - SMB_INO_T inode; - uint16 port; -} deferred_open_entry; - /* Internal message queue for deferred opens. */ struct pending_message_list { struct pending_message_list *next, *prev; - struct timeval msg_time; /* The timeout time */ + struct timeval request_time; /* When was this first issued? */ + struct timeval end_time; /* When does this time out? */ DATA_BLOB buf; DATA_BLOB private_data; }; /* struct returned by get_share_modes */ -typedef struct { - pid_t pid; - uint16 op_port; +struct share_mode_entry { + struct process_id pid; + uint16 op_mid; uint16 op_type; uint32 access_mask; /* NTCreateX access bits (FILE_READ_DATA etc.) */ uint32 share_access; /* NTCreateX share constants (FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE). */ @@ -652,14 +653,18 @@ typedef struct { SMB_DEV_T dev; SMB_INO_T inode; unsigned long share_file_id; -} share_mode_entry; - - -#define SHAREMODE_FN_CAST() \ - void (*)(share_mode_entry *, char*) +}; -#define SHAREMODE_FN(fn) \ - void (*fn)(share_mode_entry *, char*) +struct share_mode_lock { + const char *filename; + SMB_DEV_T dev; + SMB_INO_T ino; + int num_share_modes; + struct share_mode_entry *share_modes; + BOOL delete_on_close; + BOOL fresh; + BOOL modified; +}; #define NT_HASH_LEN 16 #define LM_HASH_LEN 16 @@ -700,14 +705,14 @@ typedef struct { /* key and data in the connections database - used in smbstatus and smbd */ struct connections_key { - pid_t pid; + struct process_id pid; int cnum; fstring name; }; struct connections_data { int magic; - pid_t pid; + struct process_id pid; int cnum; uid_t uid; gid_t gid; @@ -719,12 +724,6 @@ struct connections_data { }; -/* key and data records in the tdb locking database */ -struct locking_key { - SMB_DEV_T dev; - SMB_INO_T inode; -}; - /* the following are used by loadparm for option lists */ typedef enum { P_BOOL,P_BOOLREV,P_CHAR,P_INTEGER,P_OCTAL,P_LIST, @@ -744,11 +743,11 @@ struct enum_list { }; #define BRLOCK_FN_CAST() \ - void (*)(SMB_DEV_T dev, SMB_INO_T ino, int pid, \ + void (*)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \ enum brl_type lock_type, \ br_off start, br_off size) #define BRLOCK_FN(fn) \ - void (*fn)(SMB_DEV_T dev, SMB_INO_T ino, int pid, \ + void (*fn)(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, \ enum brl_type lock_type, \ br_off start, br_off size) struct parm_struct @@ -1462,10 +1461,29 @@ extern int chain_size; #define BATCH_OPLOCK 2 #define LEVEL_II_OPLOCK 4 #define INTERNAL_OPEN_ONLY 8 +#define FAKE_LEVEL_II_OPLOCK 16 /* Client requested no_oplock, but we have to + * inform potential level2 holders on + * write. */ +#define DEFERRED_OPEN_ENTRY 32 +#define UNUSED_SHARE_MODE_ENTRY 64 #define EXCLUSIVE_OPLOCK_TYPE(lck) ((lck) & ((unsigned int)EXCLUSIVE_OPLOCK|(unsigned int)BATCH_OPLOCK)) #define BATCH_OPLOCK_TYPE(lck) ((lck) & (unsigned int)BATCH_OPLOCK) -#define LEVEL_II_OPLOCK_TYPE(lck) ((lck) & (unsigned int)LEVEL_II_OPLOCK) +#define LEVEL_II_OPLOCK_TYPE(lck) ((lck) & ((unsigned int)LEVEL_II_OPLOCK|(unsigned int)FAKE_LEVEL_II_OPLOCK)) + +struct inform_level2_message { + SMB_DEV_T dev; + SMB_INO_T inode; + uint16 mid; + unsigned long target_file_id; + unsigned long source_file_id; +}; + +struct kernel_oplock_message { + SMB_DEV_T dev; + SMB_INO_T inode; + unsigned long file_id; +}; /* * On the wire return values for oplock types. @@ -1483,95 +1501,23 @@ extern int chain_size; #define OPLOCKLEVEL_NONE 0 #define OPLOCKLEVEL_II 1 -/* - * Loopback command offsets. - */ - -#define OPBRK_CMD_LEN_OFFSET 0 -#define OPBRK_CMD_PORT_OFFSET 4 -#define OPBRK_CMD_HEADER_LEN 6 - -#define OPBRK_MESSAGE_CMD_OFFSET 0 - -/* - * Oplock break command code to send over the udp socket. - * The same message is sent for both exlusive and level II breaks. - * - * The form of this is : - * - * 0 2 2+pid 2+pid+dev 2+pid+dev+ino - * +----+--------+-------+--------+---------+ - * | cmd| pid | dev | inode | fileid | - * +----+--------+-------+--------+---------+ - */ - -#define OPLOCK_BREAK_PID_OFFSET 2 -#define OPLOCK_BREAK_DEV_OFFSET (OPLOCK_BREAK_PID_OFFSET + sizeof(pid_t)) -#define OPLOCK_BREAK_INODE_OFFSET (OPLOCK_BREAK_DEV_OFFSET + sizeof(SMB_DEV_T)) -#define OPLOCK_BREAK_FILEID_OFFSET (OPLOCK_BREAK_INODE_OFFSET + sizeof(SMB_INO_T)) -#define OPLOCK_BREAK_MSG_LEN (OPLOCK_BREAK_FILEID_OFFSET + sizeof(unsigned long)) - -/* Message types */ -#define OPLOCK_BREAK_CMD 0x1 -#define KERNEL_OPLOCK_BREAK_CMD 0x2 -#define LEVEL_II_OPLOCK_BREAK_CMD 0x3 -#define ASYNC_LEVEL_II_OPLOCK_BREAK_CMD 0x4 - -/* Add the "deferred open" message. */ -#define RETRY_DEFERRED_OPEN_CMD 0x5 - -/* - * And the message format for it. Keep the same message length. - * - * 0 2 2+pid 2+pid+dev 2+pid+dev+ino - * +----+--------+-------+--------+---------+ - * | cmd| pid | dev | inode | mid | - * +----+--------+-------+--------+---------+ - */ - -#define DEFERRED_OPEN_CMD_OFFSET 0 -#define DEFERRED_OPEN_PID_OFFSET 2 /* pid we're *sending* from. */ -#define DEFERRED_OPEN_DEV_OFFSET (DEFERRED_OPEN_PID_OFFSET + sizeof(pid_t)) -#define DEFERRED_OPEN_INODE_OFFSET (DEFERRED_OPEN_DEV_OFFSET + sizeof(SMB_DEV_T)) -#define DEFERRED_OPEN_MID_OFFSET (DEFERRED_OPEN_INODE_OFFSET + sizeof(SMB_INO_T)) -#define DEFERRED_OPEN_MSG_LEN OPLOCK_BREAK_MSG_LEN - /* * Capabilities abstracted for different systems. */ #define KERNEL_OPLOCK_CAPABILITY 0x1 -/* - * Oplock break command code sent via the kernel interface (if it exists). - * - * Form of this is : - * - * 0 2 2+devsize 2+devsize+inodesize - * +----+--------+--------+----------+ - * | cmd| dev | inode | fileid | - * +----+--------+--------+----------+ - */ -#define KERNEL_OPLOCK_BREAK_DEV_OFFSET 2 -#define KERNEL_OPLOCK_BREAK_INODE_OFFSET (KERNEL_OPLOCK_BREAK_DEV_OFFSET + sizeof(SMB_DEV_T)) -#define KERNEL_OPLOCK_BREAK_FILEID_OFFSET (KERNEL_OPLOCK_BREAK_INODE_OFFSET + sizeof(SMB_INO_T)) -#define KERNEL_OPLOCK_BREAK_MSG_LEN (KERNEL_OPLOCK_BREAK_FILEID_OFFSET + sizeof(unsigned long)) - - /* if a kernel does support oplocks then a structure of the following typee is used to describe how to interact with the kernel */ struct kernel_oplocks { - BOOL (*receive_message)(fd_set *fds, char *buffer, int buffer_len); + files_struct * (*receive_message)(fd_set *fds); BOOL (*set_oplock)(files_struct *fsp, int oplock_type); void (*release_oplock)(files_struct *fsp); - BOOL (*parse_message)(char *msg_start, int msg_len, SMB_INO_T *inode, SMB_DEV_T *dev, unsigned long *file_id); BOOL (*msg_waiting)(fd_set *fds); int notification_fd; }; -#define CMD_REPLY 0x8000 - /* this structure defines the functions for doing change notify in various implementations */ struct cnotify_fns { @@ -1759,4 +1705,18 @@ struct ea_list { /* EA to use for DOS attributes */ #define SAMBA_XATTR_DOS_ATTRIB "user.DOSATTRIB" +struct uuid { + uint32 time_low; + uint16 time_mid; + uint16 time_hi_and_version; + uint8 clock_seq[2]; + uint8 node[6]; +}; +#define UUID_SIZE 16 + +#define UUID_FLAT_SIZE 16 +typedef struct uuid_flat { + uint8 info[UUID_FLAT_SIZE]; +} UUID_FLAT; + #endif /* _SMB_H */ diff --git a/source3/include/smb_ldap.h b/source3/include/smb_ldap.h new file mode 100644 index 00000000000..144317cc1eb --- /dev/null +++ b/source3/include/smb_ldap.h @@ -0,0 +1,256 @@ +/* + Unix SMB/CIFS Implementation. + LDAP protocol helper functions for SAMBA + Copyright (C) Volker Lendecke 2004 + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. + +*/ + +#ifndef _SMB_LDAP_H +#define _SMB_LDAP_H + +enum ldap_request_tag { + LDAP_TAG_BindRequest = 0, + LDAP_TAG_BindResponse = 1, + LDAP_TAG_UnbindRequest = 2, + LDAP_TAG_SearchRequest = 3, + LDAP_TAG_SearchResultEntry = 4, + LDAP_TAG_SearchResultDone = 5, + LDAP_TAG_ModifyRequest = 6, + LDAP_TAG_ModifyResponse = 7, + LDAP_TAG_AddRequest = 8, + LDAP_TAG_AddResponse = 9, + LDAP_TAG_DelRequest = 10, + LDAP_TAG_DelResponse = 11, + LDAP_TAG_ModifyDNRequest = 12, + LDAP_TAG_ModifyDNResponse = 13, + LDAP_TAG_CompareRequest = 14, + LDAP_TAG_CompareResponse = 15, + LDAP_TAG_AbandonRequest = 16, + LDAP_TAG_SearchResultReference = 19, + LDAP_TAG_ExtendedRequest = 23, + LDAP_TAG_ExtendedResponse = 24 +}; + +enum ldap_auth_mechanism { + LDAP_AUTH_MECH_SIMPLE = 0, + LDAP_AUTH_MECH_SASL = 3 +}; + +#ifndef LDAP_SUCCESS +enum ldap_result_code { + LDAP_SUCCESS = 0, + LDAP_SASL_BIND_IN_PROGRESS = 0x0e, + LDAP_INVALID_CREDENTIALS = 0x31, + LDAP_OTHER = 0x50 +}; +#endif /* LDAP_SUCCESS */ + +struct ldap_Result { + int resultcode; + const char *dn; + const char *errormessage; + const char *referral; +}; + +struct ldap_attribute { + const char *name; + int num_values; + DATA_BLOB *values; +}; + +struct ldap_BindRequest { + int version; + const char *dn; + enum ldap_auth_mechanism mechanism; + union { + const char *password; + struct { + const char *mechanism; + DATA_BLOB secblob; + } SASL; + } creds; +}; + +struct ldap_BindResponse { + struct ldap_Result response; + union { + DATA_BLOB secblob; + } SASL; +}; + +struct ldap_UnbindRequest { + uint8 __dummy; +}; + +enum ldap_scope { + LDAP_SEARCH_SCOPE_BASE = 0, + LDAP_SEARCH_SCOPE_SINGLE = 1, + LDAP_SEARCH_SCOPE_SUB = 2 +}; + +enum ldap_deref { + LDAP_DEREFERENCE_NEVER = 0, + LDAP_DEREFERENCE_IN_SEARCHING = 1, + LDAP_DEREFERENCE_FINDING_BASE = 2, + LDAP_DEREFERENCE_ALWAYS +}; + +struct ldap_SearchRequest { + const char *basedn; + enum ldap_scope scope; + enum ldap_deref deref; + uint32 timelimit; + uint32 sizelimit; + BOOL attributesonly; + char *filter; + int num_attributes; + const char **attributes; +}; + +struct ldap_SearchResEntry { + const char *dn; + int num_attributes; + struct ldap_attribute *attributes; +}; + +struct ldap_SearchResRef { + int num_referrals; + const char **referrals; +}; + +enum ldap_modify_type { + LDAP_MODIFY_NONE = -1, + LDAP_MODIFY_ADD = 0, + LDAP_MODIFY_DELETE = 1, + LDAP_MODIFY_REPLACE = 2 +}; + +struct ldap_mod { + enum ldap_modify_type type; + struct ldap_attribute attrib; +}; + +struct ldap_ModifyRequest { + const char *dn; + int num_mods; + struct ldap_mod *mods; +}; + +struct ldap_AddRequest { + const char *dn; + int num_attributes; + struct ldap_attribute *attributes; +}; + +struct ldap_DelRequest { + const char *dn; +}; + +struct ldap_ModifyDNRequest { + const char *dn; + const char *newrdn; + BOOL deleteolddn; + const char *newsuperior; +}; + +struct ldap_CompareRequest { + const char *dn; + const char *attribute; + const char *value; +}; + +struct ldap_AbandonRequest { + uint32 messageid; +}; + +struct ldap_ExtendedRequest { + const char *oid; + DATA_BLOB value; +}; + +struct ldap_ExtendedResponse { + struct ldap_Result response; + const char *name; + DATA_BLOB value; +}; + +union ldap_Request { + struct ldap_BindRequest BindRequest; + struct ldap_BindResponse BindResponse; + struct ldap_UnbindRequest UnbindRequest; + struct ldap_SearchRequest SearchRequest; + struct ldap_SearchResEntry SearchResultEntry; + struct ldap_Result SearchResultDone; + struct ldap_SearchResRef SearchResultReference; + struct ldap_ModifyRequest ModifyRequest; + struct ldap_Result ModifyResponse; + struct ldap_AddRequest AddRequest; + struct ldap_Result AddResponse; + struct ldap_DelRequest DelRequest; + struct ldap_Result DelResponse; + struct ldap_ModifyDNRequest ModifyDNRequest; + struct ldap_Result ModifyDNResponse; + struct ldap_CompareRequest CompareRequest; + struct ldap_Result CompareResponse; + struct ldap_AbandonRequest AbandonRequest; + struct ldap_ExtendedRequest ExtendedRequest; + struct ldap_ExtendedResponse ExtendedResponse; +}; + +struct ldap_Control { + const char *oid; + BOOL critical; + DATA_BLOB value; +}; + +struct ldap_message { + TALLOC_CTX *mem_ctx; + uint32 messageid; + uint8 type; + union ldap_Request r; + int num_controls; + struct ldap_Control *controls; +}; + +struct ldap_queue_entry { + struct ldap_queue_entry *next, *prev; + int msgid; + struct ldap_message *msg; +}; + +struct ldap_connection { + TALLOC_CTX *mem_ctx; + int sock; + int next_msgid; + char *host; + uint16 port; + BOOL ldaps; + + const char *auth_dn; + const char *simple_pw; + + /* Current outstanding search entry */ + int searchid; + + /* List for incoming search entries */ + struct ldap_queue_entry *search_entries; + + /* Outstanding LDAP requests that have not yet been replied to */ + struct ldap_queue_entry *outstanding; +}; + +#endif diff --git a/source3/include/smb_share_modes.h b/source3/include/smb_share_modes.h index f61ba624c69..1e04ea496de 100644 --- a/source3/include/smb_share_modes.h +++ b/source3/include/smb_share_modes.h @@ -55,7 +55,7 @@ struct smb_share_mode_entry { uint32_t access_mask; struct timeval open_time; uint32_t file_id; - pid_t pid; + struct process_id pid; }; /* diff --git a/source3/include/smbldap.h b/source3/include/smbldap.h index df56f60bf39..bea1a6d84a3 100644 --- a/source3/include/smbldap.h +++ b/source3/include/smbldap.h @@ -1,5 +1,5 @@ /* - Unix SMB/CIFS implementation. + Unix SMB/CIFS mplementation. LDAP protocol helper functions for SAMBA Copyright (C) Gerald Carter 2001-2003 @@ -40,6 +40,7 @@ struct smbldap_state; #define LDAP_OBJ_IDPOOL "sambaUnixIdPool" #define LDAP_OBJ_IDMAP_ENTRY "sambaIdmapEntry" #define LDAP_OBJ_SID_ENTRY "sambaSidEntry" +#define LDAP_OBJ_TRUST_PASSWORD "sambaTrustPassword" #define LDAP_OBJ_ACCOUNT "account" #define LDAP_OBJ_POSIXACCOUNT "posixAccount" @@ -95,10 +96,12 @@ struct smbldap_state; #define LDAP_ATTR_LOGON_COUNT 36 #define LDAP_ATTR_MUNGED_DIAL 37 #define LDAP_ATTR_BAD_PASSWORD_TIME 38 -#define LDAP_ATTR_PWD_HISTORY 39 +#define LDAP_ATTR_PWD_HISTORY 39 #define LDAP_ATTR_SID_LIST 40 -#define LDAP_ATTR_MOD_TIMESTAMP 41 -#define LDAP_ATTR_LOGON_HOURS 42 +#define LDAP_ATTR_MOD_TIMESTAMP 41 +#define LDAP_ATTR_LOGON_HOURS 42 +#define LDAP_ATTR_TRUST_PASSWD_FLAGS 43 + typedef struct _attrib_map_entry { int attrib; @@ -117,6 +120,8 @@ extern ATTRIB_MAP_ENTRY groupmap_attr_list[]; extern ATTRIB_MAP_ENTRY groupmap_attr_list_to_delete[]; extern ATTRIB_MAP_ENTRY idpool_attr_list[]; extern ATTRIB_MAP_ENTRY sidmap_attr_list[]; +extern ATTRIB_MAP_ENTRY trustpw_attr_list[]; + /* Function declarations -- not included in proto.h so we don't have to worry about LDAP structure types */ diff --git a/source3/include/spnego.h b/source3/include/spnego.h index 8bb13bd354a..66abe317053 100644 --- a/source3/include/spnego.h +++ b/source3/include/spnego.h @@ -43,7 +43,7 @@ typedef enum _spnego_negResult { } negResult_t; typedef struct spnego_negTokenInit { - char **mechTypes; + const char **mechTypes; int reqFlags; DATA_BLOB mechToken; DATA_BLOB mechListMIC; diff --git a/source3/include/srvstr.h b/source3/include/srvstr.h index 04db59cf012..1029df53aee 100644 --- a/source3/include/srvstr.h +++ b/source3/include/srvstr.h @@ -18,8 +18,6 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -#include "includes.h" - #define srvstr_pull(base_ptr, dest, src, dest_len, src_len, flags) \ pull_string(base_ptr, dest, src, dest_len, src_len, flags) diff --git a/source3/lib/account_pol.c b/source3/lib/account_pol.c index 423dc1675a6..b02edc5b401 100644 --- a/source3/lib/account_pol.c +++ b/source3/lib/account_pol.c @@ -3,6 +3,7 @@ * account policy storage * Copyright (C) Jean François Micouleau 1998-2001. * Copyright (C) Andrew Bartlett 2002 + * Copyright (C) Guenther Deschner 2004-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 @@ -22,102 +23,65 @@ #include "includes.h" static TDB_CONTEXT *tdb; -#define DATABASE_VERSION 2 +/* cache all entries for 60 seconds for to save ldap-queries (cache is updated + * after this period if admins do not use pdbedit or usermanager but manipulate + * ldap directly) - gd */ -/**************************************************************************** - Set default for a field if it is empty -****************************************************************************/ - -static void set_default_on_empty(int field, uint32 value) -{ - if (account_policy_get(field, NULL)) - return; - account_policy_set(field, value); - return; -} +#define DATABASE_VERSION 3 +#define AP_LASTSET "LAST_CACHE_UPDATE" +#define AP_TTL 60 -/**************************************************************************** - Open the account policy tdb. -****************************************************************************/ -BOOL init_account_policy(void) -{ - const char *vstring = "INFO/version"; - uint32 version; +struct ap_table { + int field; + const char *string; + uint32 default_val; + const char *description; + const char *ldap_attr; +}; - if (tdb) - return True; - tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); - if (!tdb) { - DEBUG(0,("Failed to open account policy database\n")); - return False; - } +static const struct ap_table account_policy_names[] = { + {AP_MIN_PASSWORD_LEN, "min password length", MINPASSWDLENGTH, + "Minimal password length (default: 5)", + "sambaMinPwdLength" }, - /* handle a Samba upgrade */ - tdb_lock_bystring(tdb, vstring,0); - if (!tdb_fetch_uint32(tdb, vstring, &version) || version != DATABASE_VERSION) { - tdb_store_uint32(tdb, vstring, DATABASE_VERSION); + {AP_PASSWORD_HISTORY, "password history", 0, + "Length of Password History Entries (default: 0 => off)", + "sambaPwdHistoryLength" }, - set_default_on_empty( - AP_MIN_PASSWORD_LEN, - MINPASSWDLENGTH);/* 5 chars minimum */ - set_default_on_empty( - AP_PASSWORD_HISTORY, - 0); /* don't keep any old password */ - set_default_on_empty( - AP_USER_MUST_LOGON_TO_CHG_PASS, - 0); /* don't force user to logon */ - set_default_on_empty( - AP_MAX_PASSWORD_AGE, - (uint32)-1); /* don't expire */ - set_default_on_empty( - AP_MIN_PASSWORD_AGE, - 0); /* 0 days */ - set_default_on_empty( - AP_LOCK_ACCOUNT_DURATION, - 30); /* lockout for 30 minutes */ - set_default_on_empty( - AP_RESET_COUNT_TIME, - 30); /* reset after 30 minutes */ - set_default_on_empty( - AP_BAD_ATTEMPT_LOCKOUT, - 0); /* don't lockout */ - set_default_on_empty( - AP_TIME_TO_LOGOUT, - -1); /* don't force logout */ - set_default_on_empty( - AP_REFUSE_MACHINE_PW_CHANGE, - 0); /* allow machine pw changes */ - } - tdb_unlock_bystring(tdb, vstring); - - /* These exist by default on NT4 in [HKLM\SECURITY\Policy\Accounts] */ - - privilege_create_account( &global_sid_World ); - privilege_create_account( &global_sid_Builtin_Administrators ); - privilege_create_account( &global_sid_Builtin_Account_Operators ); - privilege_create_account( &global_sid_Builtin_Server_Operators ); - privilege_create_account( &global_sid_Builtin_Print_Operators ); - privilege_create_account( &global_sid_Builtin_Backup_Operators ); + {AP_USER_MUST_LOGON_TO_CHG_PASS, "user must logon to change password", 0, + "Force Users to logon for password change (default: 0 => off, 2 => on)", + "sambaLogonToChgPwd" }, - return True; -} - -static const struct { - int field; - const char *string; -} account_policy_names[] = { - {AP_MIN_PASSWORD_LEN, "min password length"}, - {AP_PASSWORD_HISTORY, "password history"}, - {AP_USER_MUST_LOGON_TO_CHG_PASS, "user must logon to change password"}, - {AP_MAX_PASSWORD_AGE, "maximum password age"}, - {AP_MIN_PASSWORD_AGE,"minimum password age"}, - {AP_LOCK_ACCOUNT_DURATION, "lockout duration"}, - {AP_RESET_COUNT_TIME, "reset count minutes"}, - {AP_BAD_ATTEMPT_LOCKOUT, "bad lockout attempt"}, - {AP_TIME_TO_LOGOUT, "disconnect time"}, - {AP_REFUSE_MACHINE_PW_CHANGE, "refuse machine password change"}, - {0, NULL} + {AP_MAX_PASSWORD_AGE, "maximum password age", (uint32) -1, + "Maximum password age, in seconds (default: -1 => never expire passwords)", + "sambaMaxPwdAge" }, + + {AP_MIN_PASSWORD_AGE,"minimum password age", 0, + "Minimal password age, in seconds (default: 0 => allow immediate password change)", + "sambaMinPwdAge" }, + + {AP_LOCK_ACCOUNT_DURATION, "lockout duration", 30, + "Lockout duration in minutes (default: 30, -1 => forever)", + "sambaLockoutDuration" }, + + {AP_RESET_COUNT_TIME, "reset count minutes", 30, + "Reset time after lockout in minutes (default: 30)", + "sambaLockoutObservationWindow" }, + + {AP_BAD_ATTEMPT_LOCKOUT, "bad lockout attempt", 0, + "Lockout users after bad logon attempts (default: 0 => off)", + "sambaLockoutThreshold" }, + + {AP_TIME_TO_LOGOUT, "disconnect time", -1, + "Disconnect Users outside logon hours (default: -1 => off, 0 => on)", + "sambaForceLogoff" }, + + {AP_REFUSE_MACHINE_PW_CHANGE, "refuse machine password change", 0, + "Allow Machine Password changes (default: 0 => off)", + "sambaRefuseMachinePwdChange" }, + + {0, NULL, 0, "", NULL} }; char *account_policy_names_list(void) @@ -148,7 +112,7 @@ char *account_policy_names_list(void) Get the account policy name as a string from its #define'ed number ****************************************************************************/ -static const char *decode_account_policy_name(int field) +const char *decode_account_policy_name(int field) { int i; for (i=0; account_policy_names[i].string; i++) { @@ -156,7 +120,34 @@ static const char *decode_account_policy_name(int field) return account_policy_names[i].string; } return NULL; +} + +/**************************************************************************** +Get the account policy LDAP attribute as a string from its #define'ed number +****************************************************************************/ +const char *get_account_policy_attr(int field) +{ + int i; + for (i=0; account_policy_names[i].field; i++) { + if (field == account_policy_names[i].field) + return account_policy_names[i].ldap_attr; + } + return NULL; +} + +/**************************************************************************** +Get the account policy description as a string from its #define'ed number +****************************************************************************/ + +const char *account_policy_get_desc(int field) +{ + int i; + for (i=0; account_policy_names[i].string; i++) { + if (field == account_policy_names[i].field) + return account_policy_names[i].description; + } + return NULL; } /**************************************************************************** @@ -171,18 +162,146 @@ int account_policy_name_to_fieldnum(const char *name) return account_policy_names[i].field; } return 0; +} + +/***************************************************************************** +Update LAST-Set counter inside the cache +*****************************************************************************/ + +static BOOL account_policy_cache_timestamp(uint32 *value, BOOL update, + const char *ap_name) +{ + pstring key; + uint32 val = 0; + time_t now; + + if (ap_name == NULL) + return False; + + slprintf(key, sizeof(key)-1, "%s/%s", ap_name, AP_LASTSET); + + if (!init_account_policy()) + return False; + + if (!tdb_fetch_uint32(tdb, key, &val) && !update) { + DEBUG(10,("failed to get last set timestamp of cache\n")); + return False; + } + + *value = val; + + DEBUG(10, ("account policy cache lastset was: %s\n", http_timestring(val))); + + if (update) { + + now = time(NULL); + if (!tdb_store_uint32(tdb, key, (uint32)now)) { + DEBUG(1, ("tdb_store_uint32 failed for %s\n", key)); + return False; + } + DEBUG(10, ("account policy cache lastset now: %s\n", http_timestring(now))); + *value = now; + } + + return True; } -/**************************************************************************** -****************************************************************************/ +/***************************************************************************** +Get default value for account policy +*****************************************************************************/ + +BOOL account_policy_get_default(int account_policy, uint32 *val) +{ + int i; + for (i=0; account_policy_names[i].field; i++) { + if (account_policy_names[i].field == account_policy) { + *val = account_policy_names[i].default_val; + return True; + } + } + DEBUG(0,("no default for account_policy index %d found. This should never happen\n", + account_policy)); + return False; +} + +/***************************************************************************** + Set default for a field if it is empty +*****************************************************************************/ + +static BOOL account_policy_set_default_on_empty(int account_policy) +{ + + uint32 value; + + if (!account_policy_get(account_policy, &value) && + !account_policy_get_default(account_policy, &value)) { + return False; + } + + return account_policy_set(account_policy, value); +} + +/***************************************************************************** + Open the account policy tdb. +***`*************************************************************************/ + +BOOL init_account_policy(void) +{ + + const char *vstring = "INFO/version"; + uint32 version; + int i; + + if (tdb) + return True; + + tdb = tdb_open_log(lock_path("account_policy.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); + if (!tdb) { + DEBUG(0,("Failed to open account policy database\n")); + return False; + } + + /* handle a Samba upgrade */ + tdb_lock_bystring(tdb, vstring,0); + if (!tdb_fetch_uint32(tdb, vstring, &version) || version != DATABASE_VERSION) { + + tdb_store_uint32(tdb, vstring, DATABASE_VERSION); + + for (i=0; account_policy_names[i].field; i++) { + + if (!account_policy_set_default_on_empty(account_policy_names[i].field)) { + DEBUG(0,("failed to set default value in account policy tdb\n")); + return False; + } + } + } + + tdb_unlock_bystring(tdb, vstring); + + /* These exist by default on NT4 in [HKLM\SECURITY\Policy\Accounts] */ + + privilege_create_account( &global_sid_World ); + privilege_create_account( &global_sid_Builtin_Administrators ); + privilege_create_account( &global_sid_Builtin_Account_Operators ); + privilege_create_account( &global_sid_Builtin_Server_Operators ); + privilege_create_account( &global_sid_Builtin_Print_Operators ); + privilege_create_account( &global_sid_Builtin_Backup_Operators ); + + return True; +} + +/***************************************************************************** +Get an account policy (from tdb) +*****************************************************************************/ BOOL account_policy_get(int field, uint32 *value) { fstring name; uint32 regval; - if(!init_account_policy())return False; + if (!init_account_policy()) + return False; if (value) *value = 0; @@ -199,18 +318,21 @@ BOOL account_policy_get(int field, uint32 *value) if (value) *value = regval; - DEBUG(10,("account_policy_get: %s:%d\n", name, regval)); + DEBUG(10,("account_policy_get: name: %s, val: %d\n", name, regval)); return True; } /**************************************************************************** +Set an account policy (in tdb) ****************************************************************************/ + BOOL account_policy_set(int field, uint32 value) { fstring name; - if(!init_account_policy())return False; + if (!init_account_policy()) + return False; fstrcpy(name, decode_account_policy_name(field)); if (!*name) { @@ -219,15 +341,71 @@ BOOL account_policy_set(int field, uint32 value) } if (!tdb_store_uint32(tdb, name, value)) { - DEBUG(1, ("tdb_store_uint32 failed for field %d (%s) on value %u", field, name, value)); + DEBUG(1, ("tdb_store_uint32 failed for field %d (%s) on value %u\n", field, name, value)); return False; } - DEBUG(10,("account_policy_set: %s:%d\n", name, value)); + DEBUG(10,("account_policy_set: name: %s, value: %d\n", name, value)); return True; } +/**************************************************************************** +Set an account policy in the cache +****************************************************************************/ + +BOOL cache_account_policy_set(int field, uint32 value) +{ + uint32 lastset; + const char *policy_name = NULL; + + policy_name = decode_account_policy_name(field); + if (policy_name == NULL) { + DEBUG(0,("cache_account_policy_set: no policy found\n")); + return False; + } + + DEBUG(10,("cache_account_policy_set: updating account pol cache\n")); + + if (!account_policy_set(field, value)) { + return False; + } + + if (!account_policy_cache_timestamp(&lastset, True, policy_name)) + { + DEBUG(10,("cache_account_policy_set: failed to get lastest cache update timestamp\n")); + return False; + } + + DEBUG(10,("cache_account_policy_set: cache valid until: %s\n", http_timestring(lastset+AP_TTL))); + + return True; +} + +/***************************************************************************** +Get an account policy from the cache +*****************************************************************************/ + +BOOL cache_account_policy_get(int field, uint32 *value) +{ + uint32 lastset; + + if (!account_policy_cache_timestamp(&lastset, False, + decode_account_policy_name(field))) + { + DEBUG(10,("cache_account_policy_get: failed to get latest cache update timestamp\n")); + return False; + } + + if ((lastset + AP_TTL) < (uint32)time(NULL) ) { + DEBUG(10,("cache_account_policy_get: no valid cache entry (cache expired)\n")); + return False; + } + + return account_policy_get(field, value); +} + + /**************************************************************************** ****************************************************************************/ diff --git a/source3/lib/arc4.c b/source3/lib/arc4.c new file mode 100644 index 00000000000..03ca54c324b --- /dev/null +++ b/source3/lib/arc4.c @@ -0,0 +1,80 @@ +/* + Unix SMB/CIFS implementation. + + An implementation of arc4. + + Copyright (C) Jeremy Allison 2005. + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with this program; if not, write to the Free Software + Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. +*/ + +#include "includes.h" + +/***************************************************************** + Initialize state for an arc4 crypt/decrpyt. + arc4 state is 258 bytes - last 2 bytes are the index bytes. +*****************************************************************/ + +void smb_arc4_init(unsigned char arc4_state_out[258], const unsigned char *key, size_t keylen) +{ + size_t ind; + unsigned char j = 0; + + for (ind = 0; ind < 256; ind++) { + arc4_state_out[ind] = (unsigned char)ind; + } + + for( ind = 0; ind < 256; ind++) { + unsigned char tc; + + j += (arc4_state_out[ind] + key[ind%keylen]); + + tc = arc4_state_out[ind]; + arc4_state_out[ind] = arc4_state_out[j]; + arc4_state_out[j] = tc; + } + arc4_state_out[256] = 0; + arc4_state_out[257] = 0; +} + +/***************************************************************** + Do the arc4 crypt/decrpyt. + arc4 state is 258 bytes - last 2 bytes are the index bytes. +*****************************************************************/ + +void smb_arc4_crypt(unsigned char arc4_state_inout[258], unsigned char *data, size_t len) +{ + unsigned char index_i = arc4_state_inout[256]; + unsigned char index_j = arc4_state_inout[257]; + size_t ind; + + for( ind = 0; ind < len; ind++) { + unsigned char tc; + unsigned char t; + + index_i++; + index_j += arc4_state_inout[index_i]; + + tc = arc4_state_inout[index_i]; + arc4_state_inout[index_i] = arc4_state_inout[index_j]; + arc4_state_inout[index_j] = tc; + + t = arc4_state_inout[index_i] + arc4_state_inout[index_j]; + data[ind] = data[ind] ^ arc4_state_inout[t]; + } + + arc4_state_inout[256] = index_i; + arc4_state_inout[257] = index_j; +} diff --git a/source3/lib/data_blob.c b/source3/lib/data_blob.c index 161f46a9417..ccd0d27f47b 100644 --- a/source3/lib/data_blob.c +++ b/source3/lib/data_blob.c @@ -22,8 +22,9 @@ #include "includes.h" /******************************************************************* - free() a data blob + Free() a data blob. *******************************************************************/ + static void free_data_blob(DATA_BLOB *d) { if ((d) && (d->free)) { @@ -32,8 +33,8 @@ static void free_data_blob(DATA_BLOB *d) } /******************************************************************* - construct a data blob, must be freed with data_blob_free() - you can pass NULL for p and get a blank data blob + Construct a data blob, must be freed with data_blob_free(). + You can pass NULL for p and get a blank data blob *******************************************************************/ DATA_BLOB data_blob(const void *p, size_t length) @@ -56,8 +57,9 @@ DATA_BLOB data_blob(const void *p, size_t length) } /******************************************************************* - construct a data blob, using supplied TALLOC_CTX + Construct a data blob, using supplied TALLOC_CTX. *******************************************************************/ + DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length) { DATA_BLOB ret; @@ -83,8 +85,9 @@ DATA_BLOB data_blob_talloc(TALLOC_CTX *mem_ctx, const void *p, size_t length) } /******************************************************************* -free a data blob + Free a data blob. *******************************************************************/ + void data_blob_free(DATA_BLOB *d) { if (d) { @@ -96,8 +99,9 @@ void data_blob_free(DATA_BLOB *d) } /******************************************************************* -clear a DATA_BLOB's contents + Clear a DATA_BLOB's contents *******************************************************************/ + static void data_blob_clear(DATA_BLOB *d) { if (d->data) { @@ -106,11 +110,11 @@ static void data_blob_clear(DATA_BLOB *d) } /******************************************************************* -free a data blob and clear its contents + Free a data blob and clear its contents *******************************************************************/ + void data_blob_clear_free(DATA_BLOB *d) { data_blob_clear(d); data_blob_free(d); } - diff --git a/source3/lib/debug.c b/source3/lib/debug.c index f877d540fb4..f3676070dcb 100644 --- a/source3/lib/debug.c +++ b/source3/lib/debug.c @@ -448,19 +448,22 @@ BOOL debug_parse_levels(const char *params_str) Receive a "set debug level" message. ****************************************************************************/ -static void debug_message(int msg_type, pid_t src, void *buf, size_t len) +static void debug_message(int msg_type, struct process_id src, + void *buf, size_t len) { const char *params_str = buf; /* Check, it's a proper string! */ if (params_str[len-1] != '\0') { DEBUG(1, ("Invalid debug message from pid %u to pid %u\n", - (unsigned int)src, (unsigned int)getpid())); + (unsigned int)procid_to_pid(&src), + (unsigned int)getpid())); return; } DEBUG(3, ("INFO: Remote set of debug to `%s' (pid %u from pid %u)\n", - params_str, (unsigned int)getpid(), (unsigned int)src)); + params_str, (unsigned int)getpid(), + (unsigned int)procid_to_pid(&src))); debug_parse_levels(params_str); } @@ -473,7 +476,8 @@ void debug_message_send(pid_t pid, const char *params_str) { if (!params_str) return; - message_send_pid(pid, MSG_DEBUG, params_str, strlen(params_str) + 1, + message_send_pid(pid_to_procid(pid), MSG_DEBUG, + params_str, strlen(params_str) + 1, False); } @@ -481,11 +485,13 @@ void debug_message_send(pid_t pid, const char *params_str) Return current debug level. ****************************************************************************/ -static void debuglevel_message(int msg_type, pid_t src, void *buf, size_t len) +static void debuglevel_message(int msg_type, struct process_id src, + void *buf, size_t len) { char *message = debug_list_class_names_and_levels(); - DEBUG(1,("INFO: Received REQ_DEBUGLEVEL message from PID %u\n",(unsigned int)src)); + DEBUG(1,("INFO: Received REQ_DEBUGLEVEL message from PID %u\n", + (unsigned int)procid_to_pid(&src))); message_send_pid(src, MSG_DEBUGLEVEL, message, strlen(message) + 1, True); SAFE_FREE(message); diff --git a/source3/lib/dmallocmsg.c b/source3/lib/dmallocmsg.c index a83ed518d7c..1b2308ecba6 100644 --- a/source3/lib/dmallocmsg.c +++ b/source3/lib/dmallocmsg.c @@ -35,7 +35,7 @@ static unsigned long our_dm_mark = 0; * Respond to a POOL_USAGE message by sending back string form of memory * usage stats. **/ -static void msg_req_dmalloc_mark(int UNUSED(msg_type), pid_t UNUSED(src_pid), +static void msg_req_dmalloc_mark(int UNUSED(msg_type), struct process_id UNUSED(src_pid), void *UNUSED(buf), size_t UNUSED(len)) { #ifdef ENABLE_DMALLOC @@ -49,7 +49,7 @@ static void msg_req_dmalloc_mark(int UNUSED(msg_type), pid_t UNUSED(src_pid), static void msg_req_dmalloc_log_changed(int UNUSED(msg_type), - pid_t UNUSED(src_pid), + struct process_id UNUSED(src_pid), void *UNUSED(buf), size_t UNUSED(len)) { #ifdef ENABLE_DMALLOC diff --git a/source3/lib/gencache.c b/source3/lib/gencache.c index f2e267c9d44..85599c92d33 100644 --- a/source3/lib/gencache.c +++ b/source3/lib/gencache.c @@ -251,11 +251,17 @@ BOOL gencache_get(const char *keystr, char **valstr, time_t *timeout) char* entry_buf = SMB_STRNDUP(databuf.dptr, databuf.dsize); char *v; time_t t; + unsigned u; + int status; v = SMB_MALLOC(databuf.dsize - TIMEOUT_LEN); SAFE_FREE(databuf.dptr); - sscanf(entry_buf, CACHE_DATA_FMT, (int*)&t, v); + status = sscanf(entry_buf, CACHE_DATA_FMT, &u, v); + if ( status != 2 ) { + DEBUG(0, ("gencache_get: Invalid return %d from sscanf\n", status )); + } + t = u; SAFE_FREE(entry_buf); DEBUG(10, ("Returning %s cache entry: key = %s, value = %s, " @@ -307,6 +313,8 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time TDB_DATA databuf; char *keystr = NULL, *valstr = NULL, *entry = NULL; time_t timeout = 0; + int status; + unsigned u; /* fail completely if get null pointers passed */ SMB_ASSERT(fn && keystr_pattern); @@ -335,7 +343,11 @@ void gencache_iterate(void (*fn)(const char* key, const char *value, time_t time entry = SMB_STRNDUP(databuf.dptr, databuf.dsize); SAFE_FREE(databuf.dptr); valstr = SMB_MALLOC(databuf.dsize - TIMEOUT_LEN); - sscanf(entry, CACHE_DATA_FMT, (int*)(&timeout), valstr); + status = sscanf(entry, CACHE_DATA_FMT, &u, valstr); + if ( status != 2 ) { + DEBUG(0,("gencache_iterate: invalid return from sscanf %d\n",status)); + } + timeout = u; DEBUG(10, ("Calling function with arguments (key = %s, value = %s, timeout = %s)\n", keystr, valstr, ctime(&timeout))); diff --git a/source3/lib/genrand.c b/source3/lib/genrand.c index 9ccddfa4c53..f37bbc9c2fd 100644 --- a/source3/lib/genrand.c +++ b/source3/lib/genrand.c @@ -22,7 +22,7 @@ #include "includes.h" -static unsigned char hash[258]; +static unsigned char smb_arc4_state[258]; static uint32 counter; static BOOL done_reseed = False; @@ -52,61 +52,6 @@ static void get_rand_reseed_data(int *reseed_data) } } -/**************************************************************** - Setup the seed. -*****************************************************************/ - -static void seed_random_stream(unsigned char *seedval, size_t seedlen) -{ - unsigned char j = 0; - size_t ind; - - for (ind = 0; ind < 256; ind++) - hash[ind] = (unsigned char)ind; - - for( ind = 0; ind < 256; ind++) { - unsigned char tc; - - j += (hash[ind] + seedval[ind%seedlen]); - - tc = hash[ind]; - hash[ind] = hash[j]; - hash[j] = tc; - } - - hash[256] = 0; - hash[257] = 0; -} - -/**************************************************************** - Get datasize bytes worth of random data. -*****************************************************************/ - -static void get_random_stream(unsigned char *data, size_t datasize) -{ - unsigned char index_i = hash[256]; - unsigned char index_j = hash[257]; - size_t ind; - - for( ind = 0; ind < datasize; ind++) { - unsigned char tc; - unsigned char t; - - index_i++; - index_j += hash[index_i]; - - tc = hash[index_i]; - hash[index_i] = hash[index_j]; - hash[index_j] = tc; - - t = hash[index_i] + hash[index_j]; - data[ind] = hash[t]; - } - - hash[256] = index_i; - hash[257] = index_j; -} - /**************************************************************** Get a 16 byte hash from the contents of a file. Note that the hash is not initialised. @@ -202,7 +147,7 @@ static int do_reseed(BOOL use_fd, int fd) seed_inbuf[i] ^= ((char *)(&reseed_data))[i % sizeof(reseed_data)]; } - seed_random_stream(seed_inbuf, sizeof(seed_inbuf)); + smb_arc4_init(smb_arc4_state, seed_inbuf, sizeof(seed_inbuf)); return -1; } @@ -246,7 +191,7 @@ void generate_random_buffer( unsigned char *out, int len) while(len > 0) { int copy_len = len > 16 ? 16 : len; - get_random_stream(md4_buf, sizeof(md4_buf)); + smb_arc4_crypt(smb_arc4_state, md4_buf, sizeof(md4_buf)); mdfour(tmp_buf, md4_buf, sizeof(md4_buf)); memcpy(p, tmp_buf, copy_len); p += copy_len; diff --git a/source3/lib/messages.c b/source3/lib/messages.c index 7d3addd86a4..058bbc99b0b 100644 --- a/source3/lib/messages.c +++ b/source3/lib/messages.c @@ -57,8 +57,8 @@ static int received_signal; struct message_rec { int msg_version; int msg_type; - pid_t dest; - pid_t src; + struct process_id dest; + struct process_id src; size_t len; }; @@ -66,7 +66,7 @@ struct message_rec { static struct dispatch_fns { struct dispatch_fns *next, *prev; int msg_type; - void (*fn)(int msg_type, pid_t pid, void *buf, size_t len); + void (*fn)(int msg_type, struct process_id pid, void *buf, size_t len); } *dispatch_fns; /**************************************************************************** @@ -83,10 +83,12 @@ static void sig_usr1(void) A useful function for testing the message system. ****************************************************************************/ -static void ping_message(int msg_type, pid_t src, void *buf, size_t len) +static void ping_message(int msg_type, struct process_id src, + void *buf, size_t len) { const char *msg = buf ? buf : "none"; - DEBUG(1,("INFO: Received PING message from PID %u [%s]\n",(unsigned int)src, msg)); + DEBUG(1,("INFO: Received PING message from PID %s [%s]\n", + procid_str_static(&src), msg)); message_send_pid(src, MSG_PONG, buf, len, True); } @@ -123,12 +125,12 @@ BOOL message_init(void) Form a static tdb key from a pid. ******************************************************************/ -static TDB_DATA message_key_pid(pid_t pid) +static TDB_DATA message_key_pid(struct process_id pid) { static char key[20]; TDB_DATA kbuf; - slprintf(key, sizeof(key)-1, "PID/%d", (int)pid); + slprintf(key, sizeof(key)-1, "PID/%s", procid_str_static(&pid)); kbuf.dptr = (char *)key; kbuf.dsize = strlen(key)+1; @@ -140,8 +142,9 @@ static TDB_DATA message_key_pid(pid_t pid) then delete its record in the database. ****************************************************************************/ -static BOOL message_notify(pid_t pid) +static BOOL message_notify(struct process_id procid) { + pid_t pid = procid.pid; /* * Doing kill with a non-positive pid causes messages to be * sent to places we don't want. @@ -152,7 +155,7 @@ static BOOL message_notify(pid_t pid) if (kill(pid, SIGUSR1) == -1) { if (errno == ESRCH) { DEBUG(2,("pid %d doesn't exist - deleting messages record\n", (int)pid)); - tdb_delete(tdb, message_key_pid(pid)); + tdb_delete(tdb, message_key_pid(procid)); } else { DEBUG(2,("message to process %d failed - %s\n", (int)pid, strerror(errno))); } @@ -165,8 +168,10 @@ static BOOL message_notify(pid_t pid) Send a message to a particular pid. ****************************************************************************/ -static BOOL message_send_pid_internal(pid_t pid, int msg_type, const void *buf, size_t len, - BOOL duplicates_allowed, unsigned int timeout) +static BOOL message_send_pid_internal(struct process_id pid, int msg_type, + const void *buf, size_t len, + BOOL duplicates_allowed, + unsigned int timeout) { TDB_DATA kbuf; TDB_DATA dbuf; @@ -180,12 +185,12 @@ static BOOL message_send_pid_internal(pid_t pid, int msg_type, const void *buf, * sent to places we don't want. */ - SMB_ASSERT(pid > 0); + SMB_ASSERT(procid_to_pid(&pid) > 0); rec.msg_version = MESSAGE_VERSION; rec.msg_type = msg_type; rec.dest = pid; - rec.src = sys_getpid(); + rec.src = procid_self(); rec.len = len; kbuf = message_key_pid(pid); @@ -288,7 +293,7 @@ static BOOL message_send_pid_internal(pid_t pid, int msg_type, const void *buf, Send a message to a particular pid - no timeout. ****************************************************************************/ -BOOL message_send_pid(pid_t pid, int msg_type, const void *buf, size_t len, BOOL duplicates_allowed) +BOOL message_send_pid(struct process_id pid, int msg_type, const void *buf, size_t len, BOOL duplicates_allowed) { return message_send_pid_internal(pid, msg_type, buf, len, duplicates_allowed, 0); } @@ -297,7 +302,7 @@ BOOL message_send_pid(pid_t pid, int msg_type, const void *buf, size_t len, BOOL Send a message to a particular pid, with timeout in seconds. ****************************************************************************/ -BOOL message_send_pid_with_timeout(pid_t pid, int msg_type, const void *buf, size_t len, +BOOL message_send_pid_with_timeout(struct process_id pid, int msg_type, const void *buf, size_t len, BOOL duplicates_allowed, unsigned int timeout) { return message_send_pid_internal(pid, msg_type, buf, len, duplicates_allowed, timeout); @@ -307,7 +312,7 @@ BOOL message_send_pid_with_timeout(pid_t pid, int msg_type, const void *buf, siz Count the messages pending for a particular pid. Expensive.... ****************************************************************************/ -unsigned int messages_pending_for_pid(pid_t pid) +unsigned int messages_pending_for_pid(struct process_id pid) { TDB_DATA kbuf; TDB_DATA dbuf; @@ -349,7 +354,7 @@ static BOOL retrieve_all_messages(char **msgs_buf, size_t *total_len) *msgs_buf = NULL; *total_len = 0; - kbuf = message_key_pid(sys_getpid()); + kbuf = message_key_pid(pid_to_procid(sys_getpid())); if (tdb_chainlock(tdb, kbuf) == -1) return False; @@ -377,7 +382,8 @@ static BOOL retrieve_all_messages(char **msgs_buf, size_t *total_len) Parse out the next message for the current process. ****************************************************************************/ -static BOOL message_recv(char *msgs_buf, size_t total_len, int *msg_type, pid_t *src, char **buf, size_t *len) +static BOOL message_recv(char *msgs_buf, size_t total_len, int *msg_type, + struct process_id *src, char **buf, size_t *len) { struct message_rec rec; char *ret_buf = *buf; @@ -420,7 +426,7 @@ static BOOL message_recv(char *msgs_buf, size_t total_len, int *msg_type, pid_t void message_dispatch(void) { int msg_type; - pid_t src; + struct process_id src; char *buf; char *msgs_buf; size_t len, total_len; @@ -438,8 +444,9 @@ void message_dispatch(void) return; for (buf = msgs_buf; message_recv(msgs_buf, total_len, &msg_type, &src, &buf, &len); buf += len) { - DEBUG(10,("message_dispatch: received msg_type=%d src_pid=%u\n", - msg_type, (unsigned int) src)); + DEBUG(10,("message_dispatch: received msg_type=%d " + "src_pid=%u\n", msg_type, + (unsigned int) procid_to_pid(&src))); n_handled = 0; for (dfn = dispatch_fns; dfn; dfn = dfn->next) { if (dfn->msg_type == msg_type) { @@ -464,7 +471,8 @@ void message_dispatch(void) ****************************************************************************/ void message_register(int msg_type, - void (*fn)(int msg_type, pid_t pid, void *buf, size_t len)) + void (*fn)(int msg_type, struct process_id pid, + void *buf, size_t len)) { struct dispatch_fns *dfn; @@ -543,8 +551,9 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void /* If the pid was not found delete the entry from connections.tdb */ if (errno == ESRCH) { - DEBUG(2,("pid %u doesn't exist - deleting connections %d [%s]\n", - (unsigned int)crec.pid, crec.cnum, crec.name)); + DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n", + procid_str_static(&crec.pid), + crec.cnum, crec.name)); tdb_delete(the_tdb, kbuf); } } diff --git a/source3/lib/module.c b/source3/lib/module.c index 49121d12ca1..885faf8d80e 100644 --- a/source3/lib/module.c +++ b/source3/lib/module.c @@ -231,77 +231,3 @@ void smb_run_idle_events(time_t now) return; } - -/*************************************************************************** - * This Function registers a exit event - * - * the registered functions are run on exit() - * and maybe shutdown idle connections (e.g. to an LDAP server) - ***************************************************************************/ - -struct smb_exit_list_ent { - struct smb_exit_list_ent *prev,*next; - smb_event_id_t id; - smb_exit_event_fn *fn; - void *data; -}; - -static struct smb_exit_list_ent *smb_exit_event_list = NULL; - -smb_event_id_t smb_register_exit_event(smb_exit_event_fn *fn, void *data) -{ - struct smb_exit_list_ent *event; - static smb_event_id_t smb_exit_event_id = 1; - - if (!fn) { - return SMB_EVENT_ID_INVALID; - } - - event = SMB_MALLOC_P(struct smb_exit_list_ent); - if (!event) { - DEBUG(0,("malloc() failed!\n")); - return SMB_EVENT_ID_INVALID; - } - event->fn = fn; - event->data = data; - event->id = smb_exit_event_id++; - - DLIST_ADD(smb_exit_event_list,event); - - return event->id; -} - -BOOL smb_unregister_exit_event(smb_event_id_t id) -{ - struct smb_exit_list_ent *event = smb_exit_event_list; - - while(event) { - if (event->id == id) { - DLIST_REMOVE(smb_exit_event_list,event); - SAFE_FREE(event); - return True; - } - event = event->next; - } - - return False; -} - -void smb_run_exit_events(void) -{ - struct smb_exit_list_ent *event = smb_exit_event_list; - struct smb_exit_list_ent *tmp = NULL; - - while (event) { - event->fn(&event->data); - tmp = event; - event = event->next; - /* exit event should only run one time :-)*/ - SAFE_FREE(tmp); - } - - /* the list is empty now...*/ - smb_exit_event_list = NULL; - - return; -} diff --git a/source3/lib/pidfile.c b/source3/lib/pidfile.c index 20a8e82ce23..b041eb7f1b2 100644 --- a/source3/lib/pidfile.c +++ b/source3/lib/pidfile.c @@ -57,7 +57,7 @@ pid_t pidfile_pid(const char *name) goto noproc; } - if (!process_exists((pid_t)ret)) { + if (!process_exists_by_pid(ret)) { goto noproc; } diff --git a/source3/lib/privileges.c b/source3/lib/privileges.c index d95c1ba4c13..ff0631b82f1 100644 --- a/source3/lib/privileges.c +++ b/source3/lib/privileges.c @@ -397,6 +397,8 @@ static BOOL privilege_set_add(PRIVILEGE_SET *priv_set, LUID_ATTR set) /********************************************************************* Generate the LUID_ATTR structure based on a bitmask + The assumption here is that the privilege has already been validated + so we are guaranteed to find it in the list. *********************************************************************/ LUID_ATTR get_privilege_luid( SE_PRIV *mask ) @@ -404,8 +406,7 @@ LUID_ATTR get_privilege_luid( SE_PRIV *mask ) LUID_ATTR priv_luid; int i; - priv_luid.attr = 0; - priv_luid.luid.high = 0; + ZERO_STRUCT( priv_luid ); for ( i=0; !se_priv_equal(&privs[i].se_priv, &se_priv_end); i++ ) { diff --git a/source3/lib/smbldap.c b/source3/lib/smbldap.c index cf7c8fc87f2..f08a67a22c8 100644 --- a/source3/lib/smbldap.c +++ b/source3/lib/smbldap.c @@ -267,7 +267,11 @@ ATTRIB_MAP_ENTRY sidmap_attr_list[] = { return; while ( list[i] ) { - SAFE_FREE( 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; } diff --git a/source3/lib/smbldap_util.c b/source3/lib/smbldap_util.c index 798cb3fff74..4679b864874 100644 --- a/source3/lib/smbldap_util.c +++ b/source3/lib/smbldap_util.c @@ -26,6 +26,65 @@ #include "includes.h" #include "smbldap.h" +/********************************************************************** + Add the account-policies below the sambaDomain object to LDAP, +*********************************************************************/ +static NTSTATUS add_new_domain_account_policies(struct smbldap_state *ldap_state, + const char *domain_name) +{ + NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL; + int i, rc; + uint32 policy_default; + const char *policy_attr = NULL; + pstring dn; + LDAPMod **mods = NULL; + + DEBUG(3,("Adding new account policies for domain\n")); + + pstr_sprintf(dn, "%s=%s,%s", + get_attr_key2string(dominfo_attr_list, LDAP_ATTR_DOMAIN), + domain_name, lp_ldap_suffix()); + + for (i=1; decode_account_policy_name(i) != NULL; i++) { + + pstring val; + + policy_attr = get_account_policy_attr(i); + if (!policy_attr) { + DEBUG(0,("add_new_domain_account_policies: ops. no policy!\n")); + continue; + } + + if (!account_policy_get_default(i, &policy_default)) { + DEBUG(0,("add_new_domain_account_policies: failed to get default account policy\n")); + return ntstatus; + } + + DEBUG(10,("add_new_domain_account_policies: adding \"%s\" with value: %d\n", policy_attr, policy_default)); + + pstr_sprintf(val, "%d", policy_default); + + smbldap_set_mod( &mods, LDAP_MOD_REPLACE, policy_attr, val); + + rc = smbldap_modify(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 add account policies to 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); + return ntstatus; + } + } + + ldap_mods_free(mods, True); + + return NT_STATUS_OK; +} + /********************************************************************** Add the sambaDomain to LDAP, so we don't have to search for this stuff again. This is a once-add operation for now. @@ -200,6 +259,13 @@ NTSTATUS smbldap_search_domain_info(struct smbldap_state *ldap_state, goto failed; } + status = add_new_domain_account_policies(ldap_state, domain_name); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0, ("Adding domain account policies for %s failed with %s\n", + domain_name, nt_errstr(status))); + goto failed; + } + return smbldap_search_domain_info(ldap_state, result, domain_name, False); } diff --git a/source3/lib/smbrun.c b/source3/lib/smbrun.c index 13e330dd97a..6d6d7817f1a 100644 --- a/source3/lib/smbrun.c +++ b/source3/lib/smbrun.c @@ -225,10 +225,16 @@ int smbrunsecret(const char *cmd, const char *secret) */ int status = 0; pid_t wpid; + size_t towrite; + ssize_t wrote; close(ifd[0]); /* send the secret */ - write(ifd[1], secret, strlen(secret)); + towrite = strlen(secret); + wrote = write(ifd[1], secret, towrite); + if ( wrote != towrite ) { + DEBUG(0,("smbrunsecret: wrote %ld of %lu bytes\n",(long)wrote,(unsigned long)towrite)); + } fsync(ifd[1]); close(ifd[1]); diff --git a/source3/lib/tallocmsg.c b/source3/lib/tallocmsg.c index 8ee3c257f6b..8f03fd66ff1 100644 --- a/source3/lib/tallocmsg.c +++ b/source3/lib/tallocmsg.c @@ -30,7 +30,7 @@ * Respond to a POOL_USAGE message by sending back string form of memory * usage stats. **/ -void msg_pool_usage(int msg_type, pid_t src_pid, +void msg_pool_usage(int msg_type, struct process_id src_pid, void *UNUSED(buf), size_t UNUSED(len)) { off_t reply; @@ -41,7 +41,7 @@ void msg_pool_usage(int msg_type, pid_t src_pid, DEBUG(2,("Got POOL_USAGE\n")); reply = talloc_total_size(NULL); - fstr_sprintf(reply_str, "%lld", reply); + fstr_sprintf(reply_str, "%ld", (long)reply); message_send_pid(src_pid, MSG_POOL_USAGE, reply_str, strlen(reply_str)+1, True); diff --git a/source3/lib/time.c b/source3/lib/time.c index 5e0f5646fca..385762e82c2 100644 --- a/source3/lib/time.c +++ b/source3/lib/time.c @@ -782,6 +782,15 @@ BOOL nt_time_is_zero(NTTIME *nt) return False; } +/**************************************************************************** + Check if two NTTIMEs are the same. +****************************************************************************/ + +BOOL nt_time_equals(NTTIME *nt1, NTTIME *nt2) +{ + return (nt1->high == nt2->high && nt1->low == nt2->low); +} + /**************************************************************************** Return a timeval difference in usec. ****************************************************************************/ @@ -792,6 +801,135 @@ SMB_BIG_INT usec_time_diff(const struct timeval *larget, const struct timeval *s return (sec_diff * 1000000) + (SMB_BIG_INT)(larget->tv_usec - smallt->tv_usec); } +/* + return a timeval struct with the given elements +*/ +struct timeval timeval_set(uint32_t secs, uint32_t usecs) +{ + struct timeval tv; + tv.tv_sec = secs; + tv.tv_usec = usecs; + return tv; +} + +/* + return a zero timeval +*/ +struct timeval timeval_zero(void) +{ + return timeval_set(0,0); +} + +/* + return True if a timeval is zero +*/ +BOOL timeval_is_zero(const struct timeval *tv) +{ + return tv->tv_sec == 0 && tv->tv_usec == 0; +} + +/* + return a timeval for the current time +*/ +struct timeval timeval_current(void) +{ + struct timeval tv; + GetTimeOfDay(&tv); + return tv; +} + +/* + return a timeval ofs microseconds after tv +*/ +struct timeval timeval_add(const struct timeval *tv, + uint32_t secs, uint32_t usecs) +{ + struct timeval tv2 = *tv; + tv2.tv_sec += secs; + tv2.tv_usec += usecs; + tv2.tv_sec += tv2.tv_usec / 1000000; + tv2.tv_usec = tv2.tv_usec % 1000000; + return tv2; +} + +/* + return the sum of two timeval structures +*/ +struct timeval timeval_sum(const struct timeval *tv1, + const struct timeval *tv2) +{ + return timeval_add(tv1, tv2->tv_sec, tv2->tv_usec); +} + +/* + return a timeval secs/usecs into the future +*/ +struct timeval timeval_current_ofs(uint32_t secs, uint32_t usecs) +{ + struct timeval tv = timeval_current(); + return timeval_add(&tv, secs, usecs); +} + +/* + compare two timeval structures. + Return -1 if tv1 < tv2 + Return 0 if tv1 == tv2 + Return 1 if tv1 > tv2 +*/ +int timeval_compare(const struct timeval *tv1, const struct timeval *tv2) +{ + if (tv1->tv_sec > tv2->tv_sec) return 1; + if (tv1->tv_sec < tv2->tv_sec) return -1; + if (tv1->tv_usec > tv2->tv_usec) return 1; + if (tv1->tv_usec < tv2->tv_usec) return -1; + return 0; +} + +/* + return the difference between two timevals as a timeval + if tv1 comes after tv2, then return a zero timeval + (this is *tv2 - *tv1) +*/ +struct timeval timeval_until(const struct timeval *tv1, + const struct timeval *tv2) +{ + struct timeval t; + if (timeval_compare(tv1, tv2) >= 0) { + return timeval_zero(); + } + t.tv_sec = tv2->tv_sec - tv1->tv_sec; + if (tv1->tv_usec > tv2->tv_usec) { + t.tv_sec--; + t.tv_usec = 1000000 - (tv1->tv_usec - tv2->tv_usec); + } else { + t.tv_usec = tv2->tv_usec - tv1->tv_usec; + } + return t; +} + +/* + return the lesser of two timevals +*/ +struct timeval timeval_min(const struct timeval *tv1, + const struct timeval *tv2) +{ + if (tv1->tv_sec < tv2->tv_sec) return *tv1; + if (tv1->tv_sec > tv2->tv_sec) return *tv2; + if (tv1->tv_usec < tv2->tv_usec) return *tv1; + return *tv2; +} + +/* + return the greater of two timevals +*/ +struct timeval timeval_max(const struct timeval *tv1, + const struct timeval *tv2) +{ + if (tv1->tv_sec > tv2->tv_sec) return *tv1; + if (tv1->tv_sec < tv2->tv_sec) return *tv2; + if (tv1->tv_usec > tv2->tv_usec) return *tv1; + return *tv2; +} /**************************************************************************** convert ASN.1 GeneralizedTime string to unix-time diff --git a/source3/lib/util.c b/source3/lib/util.c index 39938921968..a5cfe95b660 100644 --- a/source3/lib/util.c +++ b/source3/lib/util.c @@ -1404,12 +1404,22 @@ BOOL same_net(struct in_addr ip1,struct in_addr ip2,struct in_addr mask) Check if a process exists. Does this work on all unixes? ****************************************************************************/ -BOOL process_exists(pid_t pid) +BOOL process_exists(const struct process_id pid) { + if (!procid_is_local(&pid)) { + /* This *SEVERELY* needs fixing. */ + return True; + } + /* Doing kill with a non-positive pid causes messages to be * sent to places we don't want. */ - SMB_ASSERT(pid > 0); - return(kill(pid,0) == 0 || errno != ESRCH); + SMB_ASSERT(pid.pid > 0); + return(kill(pid.pid,0) == 0 || errno != ESRCH); +} + +BOOL process_exists_by_pid(pid_t pid) +{ + return process_exists(pid_to_procid(pid)); } /******************************************************************* @@ -2756,3 +2766,57 @@ uint32 map_share_mode_to_deny_mode(uint32 share_access, uint32 private_options) return (uint32)-1; } + +pid_t procid_to_pid(const struct process_id *proc) +{ + return proc->pid; +} + +struct process_id pid_to_procid(pid_t pid) +{ + struct process_id result; + result.pid = pid; + return result; +} + +struct process_id procid_self(void) +{ + return pid_to_procid(sys_getpid()); +} + +BOOL procid_equal(const struct process_id *p1, const struct process_id *p2) +{ + return (p1->pid == p2->pid); +} + +BOOL procid_is_me(const struct process_id *pid) +{ + return (pid->pid == sys_getpid()); +} + +struct process_id interpret_pid(const char *pid_string) +{ + return pid_to_procid(atoi(pid_string)); +} + +char *procid_str_static(const struct process_id *pid) +{ + static fstring str; + fstr_sprintf(str, "%d", pid->pid); + return str; +} + +char *procid_str(TALLOC_CTX *mem_ctx, const struct process_id *pid) +{ + return talloc_strdup(mem_ctx, procid_str_static(pid)); +} + +BOOL procid_valid(const struct process_id *pid) +{ + return (pid->pid != -1); +} + +BOOL procid_is_local(const struct process_id *pid) +{ + return True; +} diff --git a/source3/libads/authdata.c b/source3/libads/authdata.c index 2cc6c6ebae4..2e7866c0559 100644 --- a/source3/libads/authdata.c +++ b/source3/libads/authdata.c @@ -2,6 +2,11 @@ Unix SMB/CIFS implementation. kerberos authorization data (PAC) utility library Copyright (C) Jim McDonough 2003 + Copyright (C) Andrew Bartlett 2004-2005 + Copyright (C) Andrew Tridgell 2001 + Copyright (C) Luke Howard 2002-2003 + Copyright (C) Stefan Metzmacher 2004-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 @@ -22,27 +27,6 @@ #ifdef HAVE_KRB5 -static DATA_BLOB unwrap_pac(DATA_BLOB *auth_data) -{ - DATA_BLOB pac_contents; - ASN1_DATA data; - int data_type; - - asn1_load(&data, *auth_data); - asn1_start_tag(&data, ASN1_SEQUENCE(0)); - asn1_start_tag(&data, ASN1_SEQUENCE(0)); - asn1_start_tag(&data, ASN1_CONTEXT(0)); - asn1_read_Integer(&data, &data_type); - asn1_end_tag(&data); - asn1_start_tag(&data, ASN1_CONTEXT(1)); - asn1_read_OctetString(&data, &pac_contents); - asn1_end_tag(&data); - asn1_end_tag(&data); - asn1_end_tag(&data); - asn1_free(&data); - return pac_contents; -} - static BOOL pac_io_logon_name(const char *desc, PAC_LOGON_NAME *logon_name, prs_struct *ps, int depth) { @@ -75,6 +59,8 @@ static BOOL pac_io_logon_name(const char *desc, PAC_LOGON_NAME *logon_name, } + +#if 0 /* Unused (handled now in net_io_user_info3()) - Guenther */ static BOOL pac_io_krb_sids(const char *desc, KRB_SID_AND_ATTRS *sid_and_attr, prs_struct *ps, int depth) { @@ -159,6 +145,7 @@ static BOOL pac_io_krb_sid_and_attr_array(const char *desc, return True; } +#endif static BOOL pac_io_group_membership(const char *desc, GROUP_MEMBERSHIP *membership, @@ -216,27 +203,34 @@ static BOOL pac_io_group_membership_array(const char *desc, } +#if 0 /* Unused, replaced using an expanded net_io_user_info3() now - Guenther */ static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info, prs_struct *ps, int depth) { - uint32 garbage; + uint32 garbage, i; + if (NULL == info) return False; prs_debug(ps, depth, desc, "pac_io_pac_logon_info"); depth++; - if (!prs_uint32("unknown", ps, depth, &garbage)) + if (!prs_align(ps)) return False; - if (!prs_uint32("unknown", ps, depth, &garbage)) + if (!prs_uint32("unknown", ps, depth, &garbage)) /* 00081001 */ + return False; + if (!prs_uint32("unknown", ps, depth, &garbage)) /* cccccccc */ return False; if (!prs_uint32("bufferlen", ps, depth, &garbage)) return False; - if (!prs_uint32("bufferlenhi", ps, depth, &garbage)) + if (!prs_uint32("bufferlenhi", ps, depth, &garbage)) /* 00000000 */ return False; + if (!prs_uint32("pointer", ps, depth, &garbage)) return False; + if (!prs_align(ps)) + return False; if (!smb_io_time("logon_time", &info->logon_time, ps, depth)) return False; if (!smb_io_time("logoff_time", &info->logoff_time, ps, depth)) @@ -270,7 +264,7 @@ static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info, if (!prs_uint16("logon_count", ps, depth, &info->logon_count)) return False; - if (!prs_uint16("reserved12", ps, depth, &info->reserved12)) + if (!prs_uint16("bad_password_count", ps, depth, &info->bad_password_count)) return False; if (!prs_uint32("user_rid", ps, depth, &info->user_rid)) return False; @@ -287,13 +281,7 @@ static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info, if (!prs_uint32("user_flags", ps, depth, &info->user_flags)) return False; - if (!prs_uint32("reserved13.0", ps, depth, &info->reserved13[0])) - return False; - if (!prs_uint32("reserved13.1", ps, depth, &info->reserved13[1])) - return False; - if (!prs_uint32("reserved13.2", ps, depth, &info->reserved13[2])) - return False; - if (!prs_uint32("reserved13.3", ps, depth, &info->reserved13[3])) + if (!prs_uint8s(False, "session_key", ps, depth, info->session_key, 16)) return False; if (!smb_io_unihdr("hdr_dom_controller", @@ -306,30 +294,17 @@ static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info, if (!prs_uint32("ptr_dom_sid", ps, depth, &info->ptr_dom_sid)) return False; - if (!prs_uint32("reserved16.0", ps, depth, &info->reserved16[0])) - return False; - if (!prs_uint32("reserved16.1", ps, depth, &info->reserved16[1])) + if (!prs_uint8s(False, "lm_session_key", ps, depth, info->lm_session_key, 8)) return False; - /* might be acb_info */ - if (!prs_uint32("reserved17", ps, depth, &info->reserved17)) + if (!prs_uint32("acct_flags", ps, depth, &info->acct_flags)) return False; - - if (!prs_uint32("reserved18.0", ps, depth, &info->reserved18[0])) - return False; - if (!prs_uint32("reserved18.1", ps, depth, &info->reserved18[1])) - return False; - if (!prs_uint32("reserved18.2", ps, depth, &info->reserved18[2])) - return False; - if (!prs_uint32("reserved18.3", ps, depth, &info->reserved18[3])) - return False; - if (!prs_uint32("reserved18.4", ps, depth, &info->reserved18[4])) - return False; - if (!prs_uint32("reserved18.5", ps, depth, &info->reserved18[5])) - return False; - if (!prs_uint32("reserved18.6", ps, depth, &info->reserved18[6])) - return False; + for (i = 0; i < 7; i++) + { + if (!prs_uint32("unkown", ps, depth, &info->unknown[i])) /* unknown */ + return False; + } if (!prs_uint32("sid_count", ps, depth, &info->sid_count)) return False; @@ -395,44 +370,109 @@ static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info, &info->res_group_dom_sid, ps, depth)) return False; - if (info->ptr_res_groups) + if (info->ptr_res_groups) { + + if (!(info->user_flgs & LOGON_RESOURCE_GROUPS)) { + DEBUG(0,("user_flgs attribute does not have LOGON_RESOURCE_GROUPS\n")); + /* return False; */ + } + if (!pac_io_group_membership_array("res group membership", &info->res_groups, info->res_group_count, ps, depth)) return False; + } + + return True; +} +#endif + +static BOOL pac_io_pac_logon_info(const char *desc, PAC_LOGON_INFO *info, + prs_struct *ps, int depth) +{ + uint32 garbage; + BOOL kerb_validation_info = True; + + if (NULL == info) + return False; + + prs_debug(ps, depth, desc, "pac_io_pac_logon_info"); + depth++; + + if (!prs_align(ps)) + return False; + if (!prs_uint32("unknown", ps, depth, &garbage)) /* 00081001 */ + return False; + if (!prs_uint32("unknown", ps, depth, &garbage)) /* cccccccc */ + return False; + if (!prs_uint32("bufferlen", ps, depth, &garbage)) + return False; + if (!prs_uint32("bufferlenhi", ps, depth, &garbage)) /* 00000000 */ + return False; + + if(!net_io_user_info3("", &info->info3, ps, depth, 3, kerb_validation_info)) + return False; + + if (info->info3.ptr_res_group_dom_sid) { + if (!smb_io_dom_sid2("res_group_dom_sid", + &info->res_group_dom_sid, ps, depth)) + return False; + } + + if (info->info3.ptr_res_groups) { + + if (!(info->info3.user_flgs & LOGON_RESOURCE_GROUPS)) { + DEBUG(0,("user_flgs attribute does not have LOGON_RESOURCE_GROUPS\n")); + /* return False; */ + } + + if (!pac_io_group_membership_array("res group membership", + &info->res_groups, + info->info3.res_group_count, + ps, depth)) + return False; + } return True; } + static BOOL pac_io_pac_signature_data(const char *desc, PAC_SIGNATURE_DATA *data, uint32 length, prs_struct *ps, int depth) { uint32 siglen = length - sizeof(uint32); - if (NULL == data) - return False; - prs_debug(ps, depth, desc, "pac_io_pac_signature_data"); depth++; + + if (data == NULL) + return False; + if (!prs_align(ps)) + return False; if (!prs_uint32("type", ps, depth, &data->type)) return False; - if (UNMARSHALLING(ps)) { - data->signature = PRS_ALLOC_MEM(ps, unsigned char, siglen); - if (!data->signature) { + + if (UNMARSHALLING(ps) && length) { + data->signature.buffer = PRS_ALLOC_MEM(ps, uint8, siglen); + if (!data->signature.buffer) { DEBUG(3, ("No memory available\n")); return False; } } - if (!prs_uint8s(False, "signature", ps, depth, data->signature,siglen)) + + data->signature.buf_len = siglen; + + if (!prs_uint8s(False, "signature", ps, depth, data->signature.buffer, data->signature.buf_len)) return False; + return True; } -static BOOL pac_io_pac_info_hdr_ctr(const char *desc, PAC_INFO_HDR *hdr, +static BOOL pac_io_pac_info_hdr_ctr(const char *desc, PAC_BUFFER *hdr, prs_struct *ps, int depth) { if (NULL == hdr) @@ -445,8 +485,8 @@ static BOOL pac_io_pac_info_hdr_ctr(const char *desc, PAC_INFO_HDR *hdr, return False; if (hdr->offset != prs_offset(ps)) { - DEBUG(5, ("offset in header(x%x) and data(x%x) do not match\n", - hdr->offset, prs_offset(ps))); + DEBUG(5,("offset in header(x%x) and data(x%x) do not match, correcting\n", + hdr->offset, prs_offset(ps))); prs_set_offset(ps, hdr->offset); } @@ -518,10 +558,15 @@ static BOOL pac_io_pac_info_hdr_ctr(const char *desc, PAC_INFO_HDR *hdr, prs_set_offset(ps, prs_offset(ps) + hdr->size); } +#if 0 + /* obscure pad */ + if (!prs_uint32("pad", ps, depth, &hdr->pad)) + return False; +#endif return True; } -static BOOL pac_io_pac_info_hdr(const char *desc, PAC_INFO_HDR *hdr, +static BOOL pac_io_pac_info_hdr(const char *desc, PAC_BUFFER *hdr, prs_struct *ps, int depth) { if (NULL == hdr) @@ -563,19 +608,19 @@ static BOOL pac_io_pac_data(const char *desc, PAC_DATA *data, return False; if (UNMARSHALLING(ps) && data->num_buffers > 0) { - if ((data->pac_info_hdr_ptr = PRS_ALLOC_MEM(ps, PAC_INFO_HDR, data->num_buffers)) == NULL) { + if ((data->pac_buffer = PRS_ALLOC_MEM(ps, PAC_BUFFER, data->num_buffers)) == NULL) { return False; } } for (i=0; inum_buffers; i++) { - if (!pac_io_pac_info_hdr(desc, &data->pac_info_hdr_ptr[i], ps, + if (!pac_io_pac_info_hdr(desc, &data->pac_buffer[i], ps, depth)) return False; } for (i=0; inum_buffers; i++) { - if (!pac_io_pac_info_hdr_ctr(desc, &data->pac_info_hdr_ptr[i], + if (!pac_io_pac_info_hdr_ctr(desc, &data->pac_buffer[i], ps, depth)) return False; } @@ -583,25 +628,300 @@ static BOOL pac_io_pac_data(const char *desc, PAC_DATA *data, return True; } -PAC_DATA *decode_pac_data(DATA_BLOB *auth_data, TALLOC_CTX *ctx) +static NTSTATUS check_pac_checksum(TALLOC_CTX *mem_ctx, + DATA_BLOB pac_data, + PAC_SIGNATURE_DATA *sig, + krb5_context context, + krb5_keyblock *keyblock) +{ + krb5_error_code ret; + krb5_checksum cksum; + krb5_keyusage usage = 0; + + smb_krb5_checksum_from_pac_sig(&cksum, sig); + +#ifdef HAVE_KRB5_KU_OTHER_CKSUM /* Heimdal */ + usage = KRB5_KU_OTHER_CKSUM; +#elif defined(HAVE_KRB5_KEYUSAGE_APP_DATA_CKSUM) /* MIT */ + usage = KRB5_KEYUSAGE_APP_DATA_CKSUM; +#else +#error UNKNOWN_KRB5_KEYUSAGE +#endif + + ret = smb_krb5_verify_checksum(context, + keyblock, + usage, + &cksum, + pac_data.data, + pac_data.length); + + if (ret) { + DEBUG(2,("check_pac_checksum: PAC Verification failed: %s (%d)\n", + error_message(ret), ret)); + return NT_STATUS_ACCESS_DENIED; + } + + return NT_STATUS_OK; +} + +static NTSTATUS parse_pac_data(TALLOC_CTX *mem_ctx, DATA_BLOB *pac_data_blob, PAC_DATA *pac_data) { - DATA_BLOB pac_data_blob = unwrap_pac(auth_data); prs_struct ps; - PAC_DATA *pac_data; + PAC_DATA *my_pac; - DEBUG(5,("dump_pac_data\n")); - prs_init(&ps, pac_data_blob.length, ctx, UNMARSHALL); - prs_copy_data_in(&ps, (char *)pac_data_blob.data, pac_data_blob.length); - prs_set_offset(&ps, 0); + if (!prs_init(&ps, pac_data_blob->length, mem_ctx, UNMARSHALL)) + return NT_STATUS_NO_MEMORY; - data_blob_free(&pac_data_blob); + if (!prs_copy_data_in(&ps, (char *)pac_data_blob->data, pac_data_blob->length)) + return NT_STATUS_INVALID_PARAMETER; + + prs_set_offset(&ps, 0); - pac_data = TALLOC_ZERO_P(ctx, PAC_DATA); - pac_io_pac_data("pac data", pac_data, &ps, 0); + my_pac = TALLOC_ZERO_P(mem_ctx, PAC_DATA); + if (!pac_io_pac_data("pac data", my_pac, &ps, 0)) + return NT_STATUS_INVALID_PARAMETER; prs_mem_free(&ps); - return pac_data; + *pac_data = *my_pac; + + return NT_STATUS_OK; +} + +/* just for debugging, will be removed later - Guenther */ +char *pac_group_attr_string(uint32 attr) +{ + fstring name = ""; + + if (!attr) + return NULL; + + if (attr & SE_GROUP_MANDATORY) fstrcat(name, "SE_GROUP_MANDATORY "); + if (attr & SE_GROUP_ENABLED_BY_DEFAULT) fstrcat(name, "SE_GROUP_ENABLED_BY_DEFAULT "); + if (attr & SE_GROUP_ENABLED) fstrcat(name, "SE_GROUP_ENABLED "); + if (attr & SE_GROUP_OWNER) fstrcat(name, "SE_GROUP_OWNER "); + if (attr & SE_GROUP_USE_FOR_DENY_ONLY) fstrcat(name, "SE_GROUP_USE_FOR_DENY_ONLY "); + if (attr & SE_GROUP_LOGON_ID) fstrcat(name, "SE_GROUP_LOGON_ID "); + if (attr & SE_GROUP_RESOURCE) fstrcat(name, "SE_GROUP_RESOURCE "); + + return SMB_STRDUP(name); +} + +/* just for debugging, will be removed later - Guenther */ +static void dump_pac_logon_info(PAC_LOGON_INFO *logon_info) { + + DOM_SID dom_sid, res_group_dom_sid; + int i; + char *attr_string; + uint32 user_flgs = logon_info->info3.user_flgs; + + if (logon_info->info3.ptr_res_group_dom_sid) { + sid_copy(&res_group_dom_sid, &logon_info->res_group_dom_sid.sid); + } + sid_copy(&dom_sid, &logon_info->info3.dom_sid.sid); + + DEBUG(10,("The PAC:\n")); + + DEBUGADD(10,("\tUser Flags: 0x%x (%d)\n", user_flgs, user_flgs)); + if (user_flgs & LOGON_EXTRA_SIDS) + DEBUGADD(10,("\tUser Flags: LOGON_EXTRA_SIDS 0x%x (%d)\n", LOGON_EXTRA_SIDS, LOGON_EXTRA_SIDS)); + if (user_flgs & LOGON_RESOURCE_GROUPS) + DEBUGADD(10,("\tUser Flags: LOGON_RESOURCE_GROUPS 0x%x (%d)\n", LOGON_RESOURCE_GROUPS, LOGON_RESOURCE_GROUPS)); + DEBUGADD(10,("\tUser SID: %s-%d\n", sid_string_static(&dom_sid), logon_info->info3.user_rid)); + DEBUGADD(10,("\tGroup SID: %s-%d\n", sid_string_static(&dom_sid), logon_info->info3.group_rid)); + + DEBUGADD(10,("\tGroup Membership (Global and Universal Groups of own domain):\n")); + for (i = 0; i < logon_info->info3.num_groups; i++) { + attr_string = pac_group_attr_string(logon_info->info3.gids[i].attr); + DEBUGADD(10,("\t\t%d: sid: %s-%d\n\t\t attr: 0x%x == %s\n", + i, sid_string_static(&dom_sid), + logon_info->info3.gids[i].g_rid, + logon_info->info3.gids[i].attr, + attr_string)); + SAFE_FREE(attr_string); + } + + DEBUGADD(10,("\tGroup Membership (Domain Local Groups and Groups from Trusted Domains):\n")); + for (i = 0; i < logon_info->info3.num_other_sids; i++) { + attr_string = pac_group_attr_string(logon_info->info3.other_sids_attrib[i]); + DEBUGADD(10,("\t\t%d: sid: %s\n\t\t attr: 0x%x == %s\n", + i, sid_string_static(&logon_info->info3.other_sids[i].sid), + logon_info->info3.other_sids_attrib[i], + attr_string)); + SAFE_FREE(attr_string); + } + + DEBUGADD(10,("\tGroup Membership (Ressource Groups (SID History ?)):\n")); + for (i = 0; i < logon_info->info3.res_group_count; i++) { + attr_string = pac_group_attr_string(logon_info->res_groups.group_membership[i].attrs); + DEBUGADD(10,("\t\t%d: sid: %s-%d\n\t\t attr: 0x%x == %s\n", + i, sid_string_static(&res_group_dom_sid), + logon_info->res_groups.group_membership[i].rid, + logon_info->res_groups.group_membership[i].attrs, + attr_string)); + SAFE_FREE(attr_string); + } +} + +NTSTATUS decode_pac_data(TALLOC_CTX *mem_ctx, + DATA_BLOB *pac_data_blob, + krb5_context context, + krb5_keyblock *service_keyblock, + krb5_const_principal client_principal, + time_t tgs_authtime, + PAC_DATA **pac_data) + +{ + DATA_BLOB modified_pac_blob; + PAC_DATA *my_pac; + NTSTATUS nt_status; + krb5_error_code ret; + PAC_SIGNATURE_DATA *srv_sig = NULL; + PAC_SIGNATURE_DATA *kdc_sig = NULL; + PAC_LOGON_NAME *logon_name = NULL; + PAC_LOGON_INFO *logon_info = NULL; + krb5_principal client_principal_pac; + NTTIME tgs_authtime_nttime; + int i, srv_sig_pos = 0, kdc_sig_pos = 0; + fstring username; + + *pac_data = NULL; + + my_pac = talloc(mem_ctx, PAC_DATA); + if (!my_pac) { + return NT_STATUS_NO_MEMORY; + } + + nt_status = parse_pac_data(mem_ctx, pac_data_blob, my_pac); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0,("decode_pac_data: failed to parse PAC\n")); + return nt_status; + } + + modified_pac_blob = data_blob_talloc(mem_ctx, pac_data_blob->data, pac_data_blob->length); + + if (my_pac->num_buffers < 4) { + nt_status = NT_STATUS_INVALID_PARAMETER; + goto out; + } + + /* store signatures */ + for (i=0; i < my_pac->num_buffers; i++) { + + switch (my_pac->pac_buffer[i].type) { + + case PAC_TYPE_SERVER_CHECKSUM: + if (!my_pac->pac_buffer[i].ctr->pac.srv_cksum) { + break; + } + + srv_sig = my_pac->pac_buffer[i].ctr->pac.srv_cksum; + + /* get position of signature buffer */ + srv_sig_pos = my_pac->pac_buffer[i].offset; + srv_sig_pos += sizeof(uint32); + + break; + + case PAC_TYPE_PRIVSVR_CHECKSUM: + if (!my_pac->pac_buffer[i].ctr->pac.privsrv_cksum) { + break; + } + + kdc_sig = my_pac->pac_buffer[i].ctr->pac.privsrv_cksum; + + /* get position of signature buffer */ + kdc_sig_pos = my_pac->pac_buffer[i].offset; + kdc_sig_pos += sizeof(uint32); + + break; + + case PAC_TYPE_LOGON_NAME: + if (!my_pac->pac_buffer[i].ctr->pac.logon_name) { + break; + } + + logon_name = my_pac->pac_buffer[i].ctr->pac.logon_name; + break; + + case PAC_TYPE_LOGON_INFO: + if (!my_pac->pac_buffer[i].ctr->pac.logon_info) { + break; + } + + logon_info = my_pac->pac_buffer[i].ctr->pac.logon_info; + break; + } + + } + + if (!srv_sig || !kdc_sig || !logon_name || !logon_info) { + nt_status = NT_STATUS_INVALID_PARAMETER; + goto out; + } + + /* zero PAC_SIGNATURE_DATA signature buffer */ + memset(&modified_pac_blob.data[srv_sig_pos], '\0', srv_sig->signature.buf_len); + memset(&modified_pac_blob.data[kdc_sig_pos], '\0', kdc_sig->signature.buf_len); + + /* check server signature */ + nt_status = check_pac_checksum(mem_ctx, modified_pac_blob, srv_sig, context, service_keyblock); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0,("decode_pac_data: failed to verify PAC server signature\n")); + goto out; + } + + /* Convert to NT time, so as not to loose accuracy in comparison */ + unix_to_nt_time(&tgs_authtime_nttime, tgs_authtime); + + if (!nt_time_equals(&tgs_authtime_nttime, &logon_name->logon_time)) { + + DEBUG(2,("decode_pac_data: Logon time mismatch between ticket and PAC!\n")); + DEBUGADD(2, ("decode_pac_data: PAC: %s\n", + http_timestring(nt_time_to_unix(&logon_name->logon_time)))); + DEBUGADD(2, ("decode_pac_data: Ticket: %s\n", + http_timestring(nt_time_to_unix(&tgs_authtime_nttime)))); + + nt_status = NT_STATUS_ACCESS_DENIED; + goto out; + } + + if (!logon_name->len) { + DEBUG(2,("decode_pac_data: No Logon Name available\n")); + nt_status = NT_STATUS_INVALID_PARAMETER; + goto out; + } + rpcstr_pull(username, logon_name->username, sizeof(username), -1, STR_TERMINATE); + + ret = smb_krb5_parse_name_norealm(context, username, &client_principal_pac); + if (ret) { + DEBUG(2,("decode_pac_data: Could not parse name from incoming PAC: [%s]: %s\n", + username, error_message(ret))); + nt_status = NT_STATUS_INVALID_PARAMETER; + goto out; + } + + if (!smb_krb5_principal_compare_any_realm(context, client_principal, client_principal_pac)) { + DEBUG(2,("decode_pac_data: Name in PAC [%s] does not match principal name in ticket\n", + username)); + nt_status = NT_STATUS_ACCESS_DENIED; + goto out; + } + + DEBUG(10,("Successfully validated Kerberos PAC\n")); + + dump_pac_logon_info(logon_info); + + *pac_data = my_pac; + + nt_status = NT_STATUS_OK; + +out: + if (client_principal_pac) { + krb5_free_principal(context, client_principal_pac); + } + + return nt_status; } #endif diff --git a/source3/libads/kerberos_verify.c b/source3/libads/kerberos_verify.c index 770d129e5da..6a5c6b6a491 100644 --- a/source3/libads/kerberos_verify.c +++ b/source3/libads/kerberos_verify.c @@ -4,8 +4,9 @@ Copyright (C) Andrew Tridgell 2001 Copyright (C) Remus Koos 2001 Copyright (C) Luke Howard 2003 - Copyright (C) Guenther Deschner 2003 + Copyright (C) Guenther Deschner 2003, 2005 Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003 + Copyright (C) Andrew Bartlett 2004-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 @@ -37,7 +38,8 @@ const krb5_data *krb5_princ_component(krb5_context, krb5_principal, int ); ***********************************************************************************/ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context auth_context, - const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt) + const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt, + krb5_keyblock **keyblock) { krb5_error_code ret = 0; BOOL auth_ok = False; @@ -100,12 +102,18 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut p_packet->length = ticket->length; p_packet->data = (krb5_pointer)ticket->data; *pp_tkt = NULL; - ret = krb5_rd_req(context, &auth_context, p_packet, kt_entry.principal, keytab, NULL, pp_tkt); + + ret = krb5_rd_req_return_keyblock_from_keytab(context, &auth_context, p_packet, + kt_entry.principal, keytab, + NULL, pp_tkt, keyblock); + if (ret) { - DEBUG(10, ("ads_keytab_verify_ticket: krb5_rd_req(%s) failed: %s\n", + DEBUG(10,("ads_keytab_verify_ticket: " + "krb5_rd_req_return_keyblock_from_keytab(%s) failed: %s\n", entry_princ_s, error_message(ret))); } else { - DEBUG(3,("ads_keytab_verify_ticket: krb5_rd_req succeeded for principal %s\n", + DEBUG(3,("ads_keytab_verify_ticket: " + "krb5_rd_req_return_keyblock_from_keytab succeeded for principal %s\n", entry_princ_s)); auth_ok = True; break; @@ -172,8 +180,9 @@ static BOOL ads_keytab_verify_ticket(krb5_context context, krb5_auth_context aut ***********************************************************************************/ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context auth_context, - krb5_principal host_princ, - const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt) + krb5_principal host_princ, + const DATA_BLOB *ticket, krb5_data *p_packet, krb5_ticket **pp_tkt, + krb5_keyblock **keyblock) { krb5_error_code ret = 0; BOOL auth_ok = False; @@ -182,6 +191,8 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au krb5_enctype *enctypes = NULL; int i; + ZERO_STRUCTP(keyblock); + if (!secrets_init()) { DEBUG(1,("ads_secrets_verify_ticket: secrets_init failed\n")); return False; @@ -222,20 +233,23 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au krb5_auth_con_setuseruserkey(context, auth_context, key); - krb5_free_keyblock(context, key); - if (!(ret = krb5_rd_req(context, &auth_context, p_packet, NULL, NULL, NULL, pp_tkt))) { DEBUG(10,("ads_secrets_verify_ticket: enc type [%u] decrypted message !\n", (unsigned int)enctypes[i] )); auth_ok = True; + krb5_copy_keyblock(context, key, keyblock); + krb5_free_keyblock(context, key); break; } DEBUG((ret != KRB5_BAD_ENCTYPE) ? 3 : 10, ("ads_secrets_verify_ticket: enc type [%u] failed to decrypt with error %s\n", (unsigned int)enctypes[i], error_message(ret))); + + krb5_free_keyblock(context, key); + } out: @@ -251,27 +265,33 @@ static BOOL ads_secrets_verify_ticket(krb5_context context, krb5_auth_context au authorization_data if available. ***********************************************************************************/ -NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket, - char **principal, DATA_BLOB *auth_data, +NTSTATUS ads_verify_ticket(TALLOC_CTX *mem_ctx, + const char *realm, const DATA_BLOB *ticket, + char **principal, PAC_DATA **pac_data, DATA_BLOB *ap_rep, DATA_BLOB *session_key) { NTSTATUS sret = NT_STATUS_LOGON_FAILURE; + DATA_BLOB auth_data; krb5_context context = NULL; krb5_auth_context auth_context = NULL; krb5_data packet; krb5_ticket *tkt = NULL; krb5_rcache rcache = NULL; + krb5_keyblock *keyblock = NULL; + time_t authtime; int ret; krb5_principal host_princ = NULL; + krb5_const_principal client_principal = NULL; char *host_princ_s = NULL; BOOL got_replay_mutex = False; BOOL auth_ok = False; + BOOL got_auth_data = False; ZERO_STRUCT(packet); - ZERO_STRUCTP(auth_data); + ZERO_STRUCT(auth_data); ZERO_STRUCTP(ap_rep); ZERO_STRUCTP(session_key); @@ -335,20 +355,30 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket, } if (lp_use_kerberos_keytab()) { - auth_ok = ads_keytab_verify_ticket(context, auth_context, ticket, &packet, &tkt); + auth_ok = ads_keytab_verify_ticket(context, auth_context, ticket, &packet, &tkt, &keyblock); } if (!auth_ok) { auth_ok = ads_secrets_verify_ticket(context, auth_context, host_princ, - ticket, &packet, &tkt); + ticket, &packet, &tkt, &keyblock); } release_server_mutex(); got_replay_mutex = False; +#if 0 + /* Heimdal leaks here, if we fix the leak, MIT crashes */ + if (rcache) { + krb5_rc_close(context, rcache); + } +#endif + if (!auth_ok) { DEBUG(3,("ads_verify_ticket: krb5_rd_req with auth failed (%s)\n", error_message(ret))); goto out; + } else { + authtime = get_authtime_from_tkt(tkt); + client_principal = get_principal_from_tkt(tkt); } ret = krb5_mk_rep(context, auth_context, &packet); @@ -369,20 +399,40 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket, file_save("/tmp/ticket.dat", ticket->data, ticket->length); #endif - get_auth_data_from_tkt(auth_data, tkt); + /* continue when no PAC is retrieved + (like accounts that have the UF_NO_AUTH_DATA_REQUIRED flag set) */ - { - TALLOC_CTX *ctx = talloc_init("pac data"); - decode_pac_data(auth_data, ctx); - talloc_destroy(ctx); + got_auth_data = get_auth_data_from_tkt(mem_ctx, &auth_data, tkt); + if (!got_auth_data) { + DEBUG(3,("ads_verify_ticket: did not retrieve auth data. continuing without PAC\n")); + } + + if (got_auth_data && pac_data != NULL) { + + sret = decode_pac_data(mem_ctx, &auth_data, context, keyblock, client_principal, authtime, pac_data); + if (!NT_STATUS_IS_OK(sret)) { + DEBUG(0,("ads_verify_ticket: failed to decode PAC_DATA: %s\n", nt_errstr(sret))); + goto out; + } + data_blob_free(&auth_data); } #if 0 +#if defined(HAVE_KRB5_TKT_ENC_PART2) + /* MIT */ if (tkt->enc_part2) { file_save("/tmp/authdata.dat", tkt->enc_part2->authorization_data[0]->contents, tkt->enc_part2->authorization_data[0]->length); } +#else + /* Heimdal */ + if (tkt->ticket.authorization_data) { + file_save("/tmp/authdata.dat", + tkt->ticket.authorization_data->val->ad_data.data, + tkt->ticket.authorization_data->val->ad_data.length); + } +#endif #endif if ((ret = krb5_unparse_name(context, get_principal_from_tkt(tkt), @@ -402,7 +452,7 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket, } if (!NT_STATUS_IS_OK(sret)) { - data_blob_free(auth_data); + data_blob_free(&auth_data); } if (!NT_STATUS_IS_OK(sret)) { @@ -413,6 +463,10 @@ NTSTATUS ads_verify_ticket(const char *realm, const DATA_BLOB *ticket, krb5_free_principal(context, host_princ); } + if (keyblock) { + krb5_free_keyblock(context, keyblock); + } + if (tkt != NULL) { krb5_free_ticket(context, tkt); } diff --git a/source3/libads/ldap.c b/source3/libads/ldap.c index 81afd7f49e3..bf402b3499e 100644 --- a/source3/libads/ldap.c +++ b/source3/libads/ldap.c @@ -2104,7 +2104,7 @@ char **ads_pull_strings_range(ADS_STRUCT *ads, if ((*num_strings) != range_start) { DEBUG(1, ("ads_pull_strings_range: Range attribute (%s) doesn't start at %u, but at %lu" " - aborting range retreival\n", - range_attr, *num_strings + 1, range_start)); + range_attr, (unsigned int)(*num_strings) + 1, range_start)); ldap_memfree(range_attr); *more_strings = False; return NULL; @@ -2140,7 +2140,7 @@ char **ads_pull_strings_range(ADS_STRUCT *ads, *next_attribute = talloc_asprintf(mem_ctx, "%s;range=%d-*", field, - *num_strings); + (int)*num_strings); if (!*next_attribute) { DEBUG(1, ("talloc_asprintf for next attribute failed!\n")); diff --git a/source3/libads/ldap_printer.c b/source3/libads/ldap_printer.c index db544fe2092..d6ac09d22bd 100644 --- a/source3/libads/ldap_printer.c +++ b/source3/libads/ldap_printer.c @@ -258,7 +258,7 @@ static void map_regval_to_ads(TALLOC_CTX *ctx, ADS_MODLIST *mods, } -WERROR get_remote_printer_publishing_data(struct cli_state *cli, +WERROR get_remote_printer_publishing_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, ADS_MODLIST *mods, const char *printer) @@ -269,16 +269,16 @@ WERROR get_remote_printer_publishing_data(struct cli_state *cli, uint32 i; POLICY_HND pol; - asprintf(&servername, "\\\\%s", cli->desthost); + asprintf(&servername, "\\\\%s", cli->cli->desthost); asprintf(&printername, "%s\\%s", servername, printer); if (!servername || !printername) { DEBUG(3, ("Insufficient memory\n")); return WERR_NOMEM; } - result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, + result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, - servername, cli->user_name, &pol); + servername, cli->cli->user_name, &pol); if (!W_ERROR_IS_OK(result)) { DEBUG(3, ("Unable to open printer %s, error is %s.\n", printername, dos_errstr(result))); @@ -288,7 +288,7 @@ WERROR get_remote_printer_publishing_data(struct cli_state *cli, if ( !(dsdriver_ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) ) return WERR_NOMEM; - result = cli_spoolss_enumprinterdataex(cli, mem_ctx, &pol, SPOOL_DSDRIVER_KEY, dsdriver_ctr); + result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol, SPOOL_DSDRIVER_KEY, dsdriver_ctr); if (!W_ERROR_IS_OK(result)) { DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n", @@ -305,7 +305,7 @@ WERROR get_remote_printer_publishing_data(struct cli_state *cli, if ( !(dsspooler_ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) ) return WERR_NOMEM; - result = cli_spoolss_enumprinterdataex(cli, mem_ctx, &pol, SPOOL_DSSPOOLER_KEY, dsspooler_ctr); + result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &pol, SPOOL_DSSPOOLER_KEY, dsspooler_ctr); if (!W_ERROR_IS_OK(result)) { DEBUG(3, ("Unable to do enumdataex on %s, error is %s.\n", @@ -323,7 +323,7 @@ WERROR get_remote_printer_publishing_data(struct cli_state *cli, TALLOC_FREE( dsdriver_ctr ); TALLOC_FREE( dsspooler_ctr ); - cli_spoolss_close_printer(cli, mem_ctx, &pol); + rpccli_spoolss_close_printer(cli, mem_ctx, &pol); return result; } diff --git a/source3/libads/sasl.c b/source3/libads/sasl.c index 8fa62a5ade4..72cbf7264ec 100644 --- a/source3/libads/sasl.c +++ b/source3/libads/sasl.c @@ -142,7 +142,7 @@ static ADS_STATUS ads_sasl_spnego_krb5_bind(ADS_STRUCT *ads, const char *princip DATA_BLOB session_key = data_blob(NULL, 0); int rc; - rc = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, &blob, &session_key); + rc = spnego_gen_negTokenTarg(principal, ads->auth.time_offset, &blob, &session_key, 0); if (rc) { return ADS_ERROR_KRB5(rc); diff --git a/source3/libsmb/cliconnect.c b/source3/libsmb/cliconnect.c index 3d8e36c493a..7ecc7695171 100644 --- a/source3/libsmb/cliconnect.c +++ b/source3/libsmb/cliconnect.c @@ -532,7 +532,7 @@ static ADS_STATUS cli_session_setup_kerberos(struct cli_state *cli, const char * DEBUG(2,("Doing kerberos session setup\n")); /* generate the encapsulated kerberos5 ticket */ - rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5); + rc = spnego_gen_negTokenTarg(principal, 0, &negTokenTarg, &session_key_krb5, 0); if (rc) { DEBUG(1, ("spnego_gen_negTokenTarg failed: %s\n", error_message(rc))); @@ -600,7 +600,7 @@ static NTSTATUS cli_session_setup_ntlmssp(struct cli_state *cli, const char *use nt_status = ntlmssp_update(ntlmssp_state, blob_in, &blob_out); data_blob_free(&blob_in); - if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + if (NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(nt_status)) { if (turn == 1) { /* and wrap it in a SPNEGO wrapper */ msg1 = gen_negTokenInit(OID_NTLMSSP, blob_out); @@ -1337,25 +1337,6 @@ BOOL cli_connect(struct cli_state *cli, const char *host, struct in_addr *ip) return True; } -/**************************************************************************** - Initialise client credentials for authenticated pipe access. -****************************************************************************/ - -void init_creds(struct ntuser_creds *creds, const char* username, - const char* domain, const char* password) -{ - ZERO_STRUCTP(creds); - - pwd_set_cleartext(&creds->pwd, password); - - fstrcpy(creds->user_name, username); - fstrcpy(creds->domain, domain); - - if (!*username) { - creds->pwd.null_pwd = True; - } -} - /** establishes a connection to after the negprot. @param output_cli A fully initialised cli structure, non-null only on success @@ -1474,7 +1455,6 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli, int signing_state, BOOL *retry) { - struct ntuser_creds creds; NTSTATUS nt_status; struct cli_state *cli = NULL; @@ -1513,8 +1493,7 @@ NTSTATUS cli_full_connection(struct cli_state **output_cli, } } - init_creds(&creds, user, domain, password); - cli_init_creds(cli, &creds); + cli_init_creds(cli, user, domain, password); *output_cli = cli; return NT_STATUS_OK; diff --git a/source3/libsmb/clidgram.c b/source3/libsmb/clidgram.c index 819616105ed..dfb613238f6 100644 --- a/source3/libsmb/clidgram.c +++ b/source3/libsmb/clidgram.c @@ -101,7 +101,7 @@ BOOL cli_send_mailslot(BOOL unique, const char *mailslot, DEBUGADD(4,("to %s IP %s\n", nmb_namestr(&dgram->dest_name), inet_ntoa(dest_ip))); - return message_send_pid(nmbd_pid, MSG_SEND_PACKET, &p, sizeof(p), + return message_send_pid(pid_to_procid(nmbd_pid), MSG_SEND_PACKET, &p, sizeof(p), False); } diff --git a/source3/libsmb/clientgen.c b/source3/libsmb/clientgen.c index f1794ab5dc8..bc64cc919b7 100644 --- a/source3/libsmb/clientgen.c +++ b/source3/libsmb/clientgen.c @@ -221,15 +221,16 @@ void cli_setup_bcc(struct cli_state *cli, void *p) Initialise credentials of a client structure. ****************************************************************************/ -void cli_init_creds(struct cli_state *cli, const struct ntuser_creds *usr) +void cli_init_creds(struct cli_state *cli, const char *username, const char *domain, const char *password) { - /* copy_nt_creds(&cli->usr, usr); */ - fstrcpy(cli->domain , usr->domain); - fstrcpy(cli->user_name, usr->user_name); - memcpy(&cli->pwd, &usr->pwd, sizeof(usr->pwd)); + fstrcpy(cli->domain, domain); + fstrcpy(cli->user_name, username); + pwd_set_cleartext(&cli->pwd, password); + if (!*username) { + cli->pwd.null_pwd = True; + } - DEBUG(10,("cli_init_creds: user %s domain %s\n", - cli->user_name, cli->domain)); + DEBUG(10,("cli_init_creds: user %s domain %s\n", cli->user_name, cli->domain)); } /**************************************************************************** @@ -260,7 +261,6 @@ void cli_setup_signing_state(struct cli_state *cli, int signing_state) struct cli_state *cli_initialise(struct cli_state *cli) { BOOL alloced_cli = False; - int i; /* Check the effective uid - make sure we are not setuid */ if (is_setuid_root()) { @@ -332,16 +332,9 @@ struct cli_state *cli_initialise(struct cli_state *cli) /* initialise signing */ cli_null_set_signing(cli); - for (i=0; ipipes[i].fnum = 0; - - cli->netlogon_pipe.fnum = 0; - cli->initialised = 1; cli->allocated = alloced_cli; - cli->pipe_idx = -1; - return cli; /* Clean up after malloc() error */ @@ -358,34 +351,42 @@ struct cli_state *cli_initialise(struct cli_state *cli) } /**************************************************************************** -close the session -****************************************************************************/ + External interface. + Close an open named pipe over SMB. Free any authentication data. + ****************************************************************************/ -void cli_nt_session_close(struct cli_state *cli) +void cli_rpc_pipe_close(struct rpc_pipe_client *cli) { - int i; - - for (i=0; ipipes[i].pipe_auth_flags & AUTH_PIPE_NTLMSSP) { - ntlmssp_end(&cli->pipes[i].ntlmssp_pipe_state); - } + if (!cli_close(cli->cli, cli->fnum)) { + DEBUG(0,("cli_rpc_pipe_close: cli_close failed on pipe %s " + "to machine %s. Error was %s\n", + cli->pipe_name, + cli->cli->desthost, + cli_errstr(cli->cli))); + } - if (cli->pipes[i].fnum != 0) - cli_close(cli, cli->pipes[i].fnum); - cli->pipes[i].fnum = 0; + if (cli->auth.cli_auth_data_free_func) { + (*cli->auth.cli_auth_data_free_func)(&cli->auth); } - cli->pipe_idx = -1; + + DEBUG(10,("cli_rpc_pipe_close: closed pipe %s to machine %s\n", + cli->pipe_name, cli->cli->desthost )); + + DLIST_REMOVE(cli->cli->pipe_list, cli); + talloc_destroy(cli->mem_ctx); } /**************************************************************************** -close the NETLOGON session holding the session key for NETSEC + Close all pipes open on this session. ****************************************************************************/ -void cli_nt_netlogon_netsec_session_close(struct cli_state *cli) +void cli_nt_pipes_close(struct cli_state *cli) { - if (cli->netlogon_pipe.fnum != 0) { - cli_close(cli, cli->netlogon_pipe.fnum); - cli->netlogon_pipe.fnum = 0; + struct rpc_pipe_client *cp, *next; + + for (cp = cli->pipe_list; cp; cp = next) { + next = cp->next; + cli_rpc_pipe_close(cp); } } @@ -395,8 +396,7 @@ void cli_nt_netlogon_netsec_session_close(struct cli_state *cli) void cli_close_connection(struct cli_state *cli) { - cli_nt_session_close(cli); - cli_nt_netlogon_netsec_session_close(cli); + cli_nt_pipes_close(cli); /* * tell our peer to free his resources. Wihtout this, when an @@ -410,8 +410,9 @@ void cli_close_connection(struct cli_state *cli) * the only user for this so far is smbmount which passes opened connection * down to kernel's smbfs module. */ - if ( (cli->cnum != (uint16)-1) && (cli->smb_rw_error != DO_NOT_DO_TDIS ) ) + if ( (cli->cnum != (uint16)-1) && (cli->smb_rw_error != DO_NOT_DO_TDIS ) ) { cli_tdis(cli); + } SAFE_FREE(cli->outbuf); SAFE_FREE(cli->inbuf); @@ -420,19 +421,16 @@ void cli_close_connection(struct cli_state *cli) data_blob_free(&cli->secblob); data_blob_free(&cli->user_session_key); - if (cli->pipes[cli->pipe_idx].pipe_auth_flags & AUTH_PIPE_NTLMSSP) - ntlmssp_end(&cli->pipes[cli->pipe_idx].ntlmssp_pipe_state); - if (cli->mem_ctx) { talloc_destroy(cli->mem_ctx); cli->mem_ctx = NULL; } - if (cli->fd != -1) + if (cli->fd != -1) { close(cli->fd); + } cli->fd = -1; cli->smb_rw_error = 0; - } /**************************************************************************** @@ -444,8 +442,9 @@ void cli_shutdown(struct cli_state *cli) BOOL allocated = cli->allocated; cli_close_connection(cli); ZERO_STRUCTP(cli); - if (allocated) + if (allocated) { free(cli); + } } /**************************************************************************** diff --git a/source3/libsmb/clierror.c b/source3/libsmb/clierror.c index 355a2adf34d..6938702e1e0 100644 --- a/source3/libsmb/clierror.c +++ b/source3/libsmb/clierror.c @@ -404,3 +404,20 @@ BOOL cli_is_dos_error(struct cli_state *cli) return cli_is_error(cli) && !(flgs2 & FLAGS2_32_BIT_ERROR_CODES); } + +/* Return the last error always as an NTSTATUS. */ + +NTSTATUS cli_get_nt_error(struct cli_state *cli) +{ + if (cli_is_nt_error(cli)) { + return cli_nt_error(cli); + } else if (cli_is_dos_error(cli)) { + uint32 ecode; + uint8 eclass; + cli_dos_error(cli, &eclass, &ecode); + return dos_to_ntstatus(eclass, ecode); + } else { + /* Something went wrong, we don't know what. */ + return NT_STATUS_UNSUCCESSFUL; + } +} diff --git a/source3/libsmb/clikrb5.c b/source3/libsmb/clikrb5.c index 1741c1db3cd..e3ad5f17cb0 100644 --- a/source3/libsmb/clikrb5.c +++ b/source3/libsmb/clikrb5.c @@ -3,6 +3,8 @@ simple kerberos5 routines for active directory Copyright (C) Andrew Tridgell 2001 Copyright (C) Luke Howard 2002-2003 + Copyright (C) Andrew Bartlett 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 @@ -186,17 +188,107 @@ } #endif - void get_auth_data_from_tkt(DATA_BLOB *auth_data, krb5_ticket *tkt) +BOOL unwrap_pac(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, DATA_BLOB *unwrapped_pac_data) { + DATA_BLOB pac_contents; + ASN1_DATA data; + int data_type; + + if (!auth_data->length) { + return False; + } + + asn1_load(&data, *auth_data); + asn1_start_tag(&data, ASN1_SEQUENCE(0)); + asn1_start_tag(&data, ASN1_SEQUENCE(0)); + asn1_start_tag(&data, ASN1_CONTEXT(0)); + asn1_read_Integer(&data, &data_type); + + if (data_type != KRB5_AUTHDATA_WIN2K_PAC ) { + DEBUG(10,("authorization data is not a Windows PAC (type: %d)\n", data_type)); + asn1_free(&data); + return False; + } + + asn1_end_tag(&data); + asn1_start_tag(&data, ASN1_CONTEXT(1)); + asn1_read_OctetString(&data, &pac_contents); + asn1_end_tag(&data); + asn1_end_tag(&data); + asn1_end_tag(&data); + asn1_free(&data); + + *unwrapped_pac_data = data_blob_talloc(mem_ctx, pac_contents.data, pac_contents.length); + + data_blob_free(&pac_contents); + + return True; +} + + BOOL get_auth_data_from_tkt(TALLOC_CTX *mem_ctx, DATA_BLOB *auth_data, krb5_ticket *tkt) +{ + DATA_BLOB auth_data_wrapped; + BOOL got_auth_data_pac = False; + int i; + #if defined(HAVE_KRB5_TKT_ENC_PART2) - if (tkt->enc_part2 && tkt->enc_part2->authorization_data && tkt->enc_part2->authorization_data[0] && tkt->enc_part2->authorization_data[0]->length) - *auth_data = data_blob(tkt->enc_part2->authorization_data[0]->contents, - tkt->enc_part2->authorization_data[0]->length); + if (tkt->enc_part2 && tkt->enc_part2->authorization_data && + tkt->enc_part2->authorization_data[0] && + tkt->enc_part2->authorization_data[0]->length) + { + for (i = 0; tkt->enc_part2->authorization_data[i] != NULL; i++) { + + if (tkt->enc_part2->authorization_data[i]->ad_type != + KRB5_AUTHDATA_IF_RELEVANT) { + DEBUG(10,("get_auth_data_from_tkt: ad_type is %d\n", + tkt->enc_part2->authorization_data[i]->ad_type)); + continue; + } + + auth_data_wrapped = data_blob(tkt->enc_part2->authorization_data[i]->contents, + tkt->enc_part2->authorization_data[i]->length); + + /* check if it is a PAC */ + got_auth_data_pac = unwrap_pac(mem_ctx, &auth_data_wrapped, auth_data); + data_blob_free(&auth_data_wrapped); + + if (!got_auth_data_pac) { + continue; + } + } + + return got_auth_data_pac; + } + #else - if (tkt->ticket.authorization_data && tkt->ticket.authorization_data->len) - *auth_data = data_blob(tkt->ticket.authorization_data->val->ad_data.data, - tkt->ticket.authorization_data->val->ad_data.length); + if (tkt->ticket.authorization_data && + tkt->ticket.authorization_data->len) + { + for (i = 0; i < tkt->ticket.authorization_data->len; i++) { + + if (tkt->ticket.authorization_data->val[i].ad_type != + KRB5_AUTHDATA_IF_RELEVANT) { + DEBUG(10,("get_auth_data_from_tkt: ad_type is %d\n", + tkt->ticket.authorization_data->val[i].ad_type)); + continue; + } + + auth_data_wrapped = data_blob(tkt->ticket.authorization_data->val[i].ad_data.data, + tkt->ticket.authorization_data->val[i].ad_data.length); + + /* check if it is a PAC */ + got_auth_data_pac = unwrap_pac(mem_ctx, &auth_data_wrapped, auth_data); + data_blob_free(&auth_data_wrapped); + + if (!got_auth_data_pac) { + continue; + } + } + + return got_auth_data_pac; + } #endif + return False; } krb5_const_principal get_principal_from_tkt(krb5_ticket *tkt) @@ -435,7 +527,7 @@ 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) + DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts) { krb5_error_code retval; krb5_data packet; @@ -475,7 +567,7 @@ int cli_krb5_get_ticket(const char *principal, time_t time_offset, if ((retval = ads_krb5_mk_req(context, &auth_context, - AP_OPTS_USE_SUBKEY, + AP_OPTS_USE_SUBKEY | (krb5_flags)extra_ap_opts, principal, ccdef, &packet))) { goto failed; @@ -550,10 +642,349 @@ failed: #endif } +void smb_krb5_checksum_from_pac_sig(krb5_checksum *cksum, + PAC_SIGNATURE_DATA *sig) +{ +#ifdef HAVE_CHECKSUM_IN_KRB5_CHECKSUM + cksum->cksumtype = (krb5_cksumtype)sig->type; + cksum->checksum.length = sig->signature.buf_len; + cksum->checksum.data = sig->signature.buffer; +#else + cksum->checksum_type = (krb5_cksumtype)sig->type; + cksum->length = sig->signature.buf_len; + cksum->contents = sig->signature.buffer; +#endif +} + +krb5_error_code smb_krb5_verify_checksum(krb5_context context, + krb5_keyblock *keyblock, + krb5_keyusage usage, + krb5_checksum *cksum, + uint8 *data, + size_t length) +{ + krb5_error_code ret; + + /* verify the checksum */ + + /* welcome to the wonderful world of samba's kerberos abstraction layer: + * + * function heimdal 0.6.1rc3 heimdal 0.7 MIT krb 1.4.2 + * ----------------------------------------------------------------------------- + * krb5_c_verify_checksum - works works + * krb5_verify_checksum works (6 args) works (6 args) broken (7 args) + */ + +#if defined(HAVE_KRB5_C_VERIFY_CHECKSUM) + { + krb5_boolean checksum_valid = False; + krb5_data input; + + input.data = (char *)data; + input.length = length; + + ret = krb5_c_verify_checksum(context, + keyblock, + usage, + &input, + cksum, + &checksum_valid); + if (!checksum_valid) + ret = KRB5KRB_AP_ERR_BAD_INTEGRITY; + } + +#elif KRB5_VERIFY_CHECKSUM_ARGS == 6 && defined(HAVE_KRB5_CRYPTO_INIT) && defined(HAVE_KRB5_CRYPTO) && defined(HAVE_KRB5_CRYPTO_DESTROY) + + /* Warning: MIT's krb5_verify_checksum cannot be used as it will use a key + * without enctype and it ignores any key_usage types - Guenther */ + + { + + krb5_crypto crypto; + ret = krb5_crypto_init(context, + keyblock, + 0, + &crypto); + if (ret) { + DEBUG(0,("smb_krb5_verify_checksum: krb5_crypto_init() failed: %s\n", + error_message(ret))); + return ret; + } + + ret = krb5_verify_checksum(context, + crypto, + usage, + data, + length, + cksum); + + krb5_crypto_destroy(context, crypto); + } + +#else +#error UNKNOWN_KRB5_VERIFY_CHECKSUM_FUNCTION +#endif + + return ret; +} + +time_t get_authtime_from_tkt(krb5_ticket *tkt) +{ +#if defined(HAVE_KRB5_TKT_ENC_PART2) + return tkt->enc_part2->times.authtime; +#else + return tkt->ticket.authtime; +#endif +} + +static int get_kvno_from_ap_req(krb5_ap_req *ap_req) +{ +#ifdef HAVE_TICKET_POINTER_IN_KRB5_AP_REQ /* MIT */ + if (ap_req->ticket->enc_part.kvno) + return ap_req->ticket->enc_part.kvno; +#else /* Heimdal */ + if (ap_req->ticket.enc_part.kvno) + return *ap_req->ticket.enc_part.kvno; +#endif + return 0; +} + +static krb5_enctype get_enctype_from_ap_req(krb5_ap_req *ap_req) +{ +#ifdef HAVE_ETYPE_IN_ENCRYPTEDDATA /* Heimdal */ + return ap_req->ticket.enc_part.etype; +#else /* MIT */ + return ap_req->ticket->enc_part.enctype; +#endif +} + +static krb5_error_code +get_key_from_keytab(krb5_context context, + krb5_keytab keytab, + krb5_const_principal server, + krb5_enctype enctype, + krb5_kvno kvno, + krb5_keyblock **out_key) +{ + krb5_keytab_entry entry; + krb5_error_code ret; + krb5_keytab real_keytab; + char *name = NULL; + + if (keytab == NULL) { + krb5_kt_default(context, &real_keytab); + } else { + real_keytab = keytab; + } + + if ( DEBUGLEVEL >= 10 ) { + krb5_unparse_name(context, server, &name); + DEBUG(10,("get_key_from_keytab: will look for kvno %d, enctype %d and name: %s\n", + kvno, enctype, name)); + krb5_free_unparsed_name(context, name); + } + + ret = krb5_kt_get_entry(context, + real_keytab, + server, + kvno, + enctype, + &entry); + + if (ret) { + DEBUG(0,("get_key_from_keytab: failed to retrieve key: %s\n", error_message(ret))); + goto out; + } + +#ifdef HAVE_KRB5_KEYTAB_ENTRY_KEYBLOCK /* Heimdal */ + ret = krb5_copy_keyblock(context, &entry.keyblock, out_key); +#elif defined(HAVE_KRB5_KEYTAB_ENTRY_KEY) /* MIT */ + ret = krb5_copy_keyblock(context, &entry.key, out_key); +#else +#error UNKNOWN_KRB5_KEYTAB_ENTRY_FORMAT +#endif + + if (ret) { + DEBUG(0,("get_key_from_keytab: failed to copy key: %s\n", error_message(ret))); + goto out; + } + + smb_krb5_kt_free_entry(context, &entry); + +out: + if (keytab == NULL) { + krb5_kt_close(context, real_keytab); + } + + return ret; +} + +void smb_krb5_free_ap_req(krb5_context context, + krb5_ap_req *ap_req) +{ +#ifdef HAVE_KRB5_FREE_AP_REQ /* MIT */ + krb5_free_ap_req(context, ap_req); +#elif defined(HAVE_FREE_AP_REQ) /* Heimdal */ + free_AP_REQ(ap_req); +#else +#error UNKNOWN_KRB5_AP_REQ_FREE_FUNCTION +#endif +} + +/* Prototypes */ +#if defined(HAVE_DECODE_KRB5_AP_REQ) /* MIT */ +krb5_error_code decode_krb5_ap_req(const krb5_data *code, krb5_ap_req **rep); +#endif + +krb5_error_code smb_krb5_get_keyinfo_from_ap_req(krb5_context context, + const krb5_data *inbuf, + krb5_kvno *kvno, + krb5_enctype *enctype) +{ + krb5_error_code ret; +#ifdef HAVE_KRB5_DECODE_AP_REQ /* Heimdal */ + { + krb5_ap_req ap_req; + + ret = krb5_decode_ap_req(context, inbuf, &ap_req); + if (ret) + return ret; + + *kvno = get_kvno_from_ap_req(&ap_req); + *enctype = get_enctype_from_ap_req(&ap_req); + + smb_krb5_free_ap_req(context, &ap_req); + } +#elif defined(HAVE_DECODE_KRB5_AP_REQ) /* MIT */ + { + krb5_ap_req *ap_req = NULL; + + ret = decode_krb5_ap_req(inbuf, &ap_req); + if (ret) + return ret; + + *kvno = get_kvno_from_ap_req(ap_req); + *enctype = get_enctype_from_ap_req(ap_req); + + smb_krb5_free_ap_req(context, ap_req); + } +#else +#error UNKOWN_KRB5_AP_REQ_DECODING_FUNCTION +#endif + return ret; +} + +krb5_error_code krb5_rd_req_return_keyblock_from_keytab(krb5_context context, + krb5_auth_context *auth_context, + const krb5_data *inbuf, + krb5_const_principal server, + krb5_keytab keytab, + krb5_flags *ap_req_options, + krb5_ticket **ticket, + krb5_keyblock **keyblock) +{ + krb5_error_code ret; + krb5_ap_req *ap_req = NULL; + krb5_kvno kvno; + krb5_enctype enctype; + krb5_keyblock *local_keyblock; + + ret = krb5_rd_req(context, + auth_context, + inbuf, + server, + keytab, + ap_req_options, + ticket); + if (ret) { + return ret; + } + + ret = smb_krb5_get_keyinfo_from_ap_req(context, inbuf, &kvno, &enctype); + if (ret) { + return ret; + } + + ret = get_key_from_keytab(context, + keytab, + server, + enctype, + kvno, + &local_keyblock); + if (ret) { + DEBUG(0,("krb5_rd_req_return_keyblock_from_keytab: failed to call get_key_from_keytab\n")); + goto out; + } + +out: + if (ap_req) { + smb_krb5_free_ap_req(context, ap_req); + } + + if (ret && local_keyblock != NULL) { + krb5_free_keyblock(context, local_keyblock); + } else { + *keyblock = local_keyblock; + } + + return ret; +} + +krb5_error_code smb_krb5_parse_name_norealm(krb5_context context, + const char *name, + krb5_principal *principal) +{ +#ifdef HAVE_KRB5_PARSE_NAME_NOREALM + return krb5_parse_name_norealm(context, name, principal); +#endif + + /* we are cheating here because parse_name will in fact set the realm. + * We don't care as the only caller of smb_krb5_parse_name_norealm + * ignores the realm anyway when calling + * smb_krb5_principal_compare_any_realm later - Guenther */ + + return krb5_parse_name(context, name, principal); +} + +BOOL smb_krb5_principal_compare_any_realm(krb5_context context, + krb5_const_principal princ1, + krb5_const_principal princ2) +{ +#ifdef HAVE_KRB5_PRINCIPAL_COMPARE_ANY_REALM + + return krb5_principal_compare_any_realm(context, princ1, princ2); + +/* krb5_princ_size is a macro in MIT */ +#elif defined(HAVE_KRB5_PRINC_SIZE) || defined(krb5_princ_size) + + int i, len1, len2; + const krb5_data *p1, *p2; + + len1 = krb5_princ_size(context, princ1); + len2 = krb5_princ_size(context, princ2); + + if (len1 != len2) + return False; + + for (i = 0; i < len1; i++) { + + p1 = krb5_princ_component(context, CONST_DISCARD(krb5_principal, princ1), i); + p2 = krb5_princ_component(context, CONST_DISCARD(krb5_principal, princ2), i); + + if (p1->length != p2->length || memcmp(p1->data, p2->data, p1->length)) + return False; + } + + return True; +#else +#error NO_SUITABLE_PRINCIPAL_COMPARE_FUNCTION +#endif +} + #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) + DATA_BLOB *ticket, DATA_BLOB *session_key_krb5, uint32 extra_ap_opts) { DEBUG(0,("NO KERBEROS SUPPORT\n")); return 1; diff --git a/source3/libsmb/clireadwrite.c b/source3/libsmb/clireadwrite.c index 1220907629c..55e36b646b9 100644 --- a/source3/libsmb/clireadwrite.c +++ b/source3/libsmb/clireadwrite.c @@ -323,13 +323,13 @@ static BOOL cli_issue_write(struct cli_state *cli, int fnum, off_t offset, 0x0008 start of message mode named pipe protocol ****************************************************************************/ -size_t cli_write(struct cli_state *cli, +ssize_t cli_write(struct cli_state *cli, int fnum, uint16 write_mode, const char *buf, off_t offset, size_t size) { - int bwritten = 0; - int issued = 0; - int received = 0; + ssize_t bwritten = 0; + unsigned int issued = 0; + unsigned int received = 0; int mpx = 1; int block = cli->max_xmit - (smb_size+32); int blocks = (size + (block-1)) / block; @@ -343,8 +343,8 @@ size_t cli_write(struct cli_state *cli, while (received < blocks) { while ((issued - received < mpx) && (issued < blocks)) { - int bsent = issued * block; - int size1 = MIN(block, size - bsent); + ssize_t bsent = issued * block; + ssize_t size1 = MIN(block, size - bsent); if (!cli_issue_write(cli, fnum, offset + bsent, write_mode, diff --git a/source3/libsmb/clispnego.c b/source3/libsmb/clispnego.c index 85b7bd9e1ee..33fc265f798 100644 --- a/source3/libsmb/clispnego.c +++ b/source3/libsmb/clispnego.c @@ -325,14 +325,15 @@ BOOL spnego_parse_krb5_wrap(DATA_BLOB blob, DATA_BLOB *ticket, uint8 tok_id[2]) */ int spnego_gen_negTokenTarg(const char *principal, int time_offset, DATA_BLOB *targ, - DATA_BLOB *session_key_krb5) + DATA_BLOB *session_key_krb5, uint32 extra_ap_opts) { int retval; DATA_BLOB tkt, tkt_wrapped; const char *krb_mechs[] = {OID_KERBEROS5_OLD, OID_NTLMSSP, NULL}; /* get a kerberos ticket for the service and extract the session key */ - retval = cli_krb5_get_ticket(principal, time_offset, &tkt, session_key_krb5); + retval = cli_krb5_get_ticket(principal, time_offset, + &tkt, session_key_krb5, extra_ap_opts); if (retval) return retval; diff --git a/source3/libsmb/clitrans.c b/source3/libsmb/clitrans.c index c6b1d465ffe..5d3710b92e2 100644 --- a/source3/libsmb/clitrans.c +++ b/source3/libsmb/clitrans.c @@ -464,8 +464,8 @@ BOOL cli_send_nt_trans(struct cli_state *cli, } /**************************************************************************** - receive a SMB nttrans response allocating the necessary memory - ****************************************************************************/ + Receive a SMB nttrans response allocating the necessary memory. +****************************************************************************/ BOOL cli_receive_nt_trans(struct cli_state *cli, char **param, unsigned int *param_len, @@ -503,7 +503,7 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, */ if (cli_is_dos_error(cli)) { cli_dos_error(cli, &eclass, &ecode); - if (cli->pipes[cli->pipe_idx].fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata)) { + if (!(eclass == ERRDOS && ecode == ERRmoredata)) { cli_signing_trans_stop(cli); return(False); } @@ -637,11 +637,22 @@ BOOL cli_receive_nt_trans(struct cli_state *cli, } if (cli_is_dos_error(cli)) { cli_dos_error(cli, &eclass, &ecode); - if(cli->pipes[cli->pipe_idx].fnum == 0 || !(eclass == ERRDOS && ecode == ERRmoredata)) { + if(!(eclass == ERRDOS && ecode == ERRmoredata)) { + cli_signing_trans_stop(cli); + return(False); + } + } + /* + * Likewise for NT_STATUS_BUFFER_TOO_SMALL + */ + if (cli_is_nt_error(cli)) { + if (!NT_STATUS_EQUAL(cli_nt_error(cli), + NT_STATUS_BUFFER_TOO_SMALL)) { cli_signing_trans_stop(cli); return(False); } } + /* parse out the total lengths again - they can shrink! */ if (SVAL(cli->inbuf,smb_ntr_TotalDataCount) < total_data) total_data = SVAL(cli->inbuf,smb_ntr_TotalDataCount); diff --git a/source3/libsmb/credentials.c b/source3/libsmb/credentials.c index 0d521bae8ac..3f2dcd850b3 100644 --- a/source3/libsmb/credentials.c +++ b/source3/libsmb/credentials.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. code to manipulate domain credentials Copyright (C) Andrew Tridgell 1997-1998 + Largely rewritten by Jeremy Allison 2005. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -21,8 +22,9 @@ #include "includes.h" /**************************************************************************** -represent a credential as a string + Represent a credential as a string. ****************************************************************************/ + char *credstr(const uchar *cred) { static fstring buf; @@ -34,182 +36,243 @@ char *credstr(const uchar *cred) /**************************************************************************** - setup the session key. -Input: 8 byte challenge block + Setup the session key. + Input: 8 byte challenge block 8 byte server challenge block 16 byte md4 encrypted password -Output: - 8 byte session key + Output: + 16 byte session key (last 8 bytes zero). ****************************************************************************/ -void cred_session_key(const DOM_CHAL *clnt_chal, const DOM_CHAL *srv_chal, const uchar *pass, - uchar session_key[8]) + +static void cred_create_session_key(const DOM_CHAL *clnt_chal_in, + const DOM_CHAL *srv_chal_in, + const uchar *pass_in, + uchar session_key_out[16]) { uint32 sum[2]; unsigned char sum2[8]; - sum[0] = IVAL(clnt_chal->data, 0) + IVAL(srv_chal->data, 0); - sum[1] = IVAL(clnt_chal->data, 4) + IVAL(srv_chal->data, 4); + sum[0] = IVAL(clnt_chal_in->data, 0) + IVAL(srv_chal_in->data, 0); + sum[1] = IVAL(clnt_chal_in->data, 4) + IVAL(srv_chal_in->data, 4); SIVAL(sum2,0,sum[0]); SIVAL(sum2,4,sum[1]); - cred_hash1(session_key, sum2, pass); + cred_hash1(session_key_out, sum2, pass_in); + memset(&session_key_out[8], '\0', 8); /* debug output */ - DEBUG(4,("cred_session_key\n")); + DEBUG(4,("cred_create_session_key\n")); - DEBUG(5,(" clnt_chal: %s\n", credstr(clnt_chal->data))); - DEBUG(5,(" srv_chal : %s\n", credstr(srv_chal->data))); + DEBUG(5,(" clnt_chal_in: %s\n", credstr(clnt_chal_in->data))); + DEBUG(5,(" srv_chal_in : %s\n", credstr(srv_chal_in->data))); DEBUG(5,(" clnt+srv : %s\n", credstr(sum2))); - DEBUG(5,(" sess_key : %s\n", credstr(session_key))); + DEBUG(5,(" sess_key_out : %s\n", credstr(session_key_out))); } - /**************************************************************************** -create a credential - -Input: - 8 byte sesssion key - 8 byte stored credential - 4 byte timestamp - -Output: - 8 byte credential + Utility function to step credential chain one forward. + Deliberately doesn't update the seed. See reseed comment below. ****************************************************************************/ -void cred_create(uchar session_key[8], DOM_CHAL *stor_cred, UTIME timestamp, - DOM_CHAL *cred) + +static void creds_step(struct dcinfo *dc) { - DOM_CHAL time_cred; + DOM_CHAL time_chal; - SIVAL(time_cred.data, 0, IVAL(stor_cred->data, 0) + timestamp.time); - SIVAL(time_cred.data, 4, IVAL(stor_cred->data, 4)); + DEBUG(5,("\tsequence = 0x%x\n", (unsigned int)dc->sequence )); - cred_hash2(cred->data, time_cred.data, session_key); + DEBUG(5,("\tseed: %s\n", credstr(dc->seed_chal.data) )); - /* debug output*/ - DEBUG(4,("cred_create\n")); + SIVAL(time_chal.data, 0, IVAL(dc->seed_chal.data, 0) + dc->sequence); + SIVAL(time_chal.data, 4, IVAL(dc->seed_chal.data, 4)); + + DEBUG(5,("\tseed+seq %s\n", credstr(time_chal.data) )); - DEBUG(5,(" sess_key : %s\n", credstr(session_key))); - DEBUG(5,(" stor_cred: %s\n", credstr(stor_cred->data))); - DEBUG(5,(" timestamp: %x\n" , timestamp.time)); - DEBUG(5,(" timecred : %s\n", credstr(time_cred.data))); - DEBUG(5,(" calc_cred: %s\n", credstr(cred->data))); -} + cred_hash2(dc->clnt_chal.data, time_chal.data, dc->sess_key); + DEBUG(5,("\tCLIENT %s\n", credstr(dc->clnt_chal.data) )); -/**************************************************************************** - check a supplied credential + SIVAL(time_chal.data, 0, IVAL(dc->seed_chal.data, 0) + dc->sequence + 1); + SIVAL(time_chal.data, 4, IVAL(dc->seed_chal.data, 4)); + + DEBUG(5,("\tseed+seq+1 %s\n", credstr(time_chal.data) )); -Input: - 8 byte received credential - 8 byte sesssion key - 8 byte stored credential - 4 byte timestamp + cred_hash2(dc->srv_chal.data, time_chal.data, dc->sess_key); + + DEBUG(5,("\tSERVER %s\n", credstr(dc->srv_chal.data) )); +} -Output: - returns 1 if computed credential matches received credential - returns 0 otherwise + +/**************************************************************************** + Create a server credential struct. ****************************************************************************/ -int cred_assert(DOM_CHAL *cred, uchar session_key[8], DOM_CHAL *stored_cred, - UTIME timestamp) + +void creds_server_init(struct dcinfo *dc, + DOM_CHAL *clnt_chal, + DOM_CHAL *srv_chal, + const char mach_pw[16], + DOM_CHAL *init_chal_out) { - DOM_CHAL cred2; + DEBUG(10,("creds_server_init: client chal : %s\n", credstr(clnt_chal->data) )); + DEBUG(10,("creds_server_init: server chal : %s\n", credstr(srv_chal->data) )); + dump_data_pw("creds_server_init: machine pass", mach_pw, 16); - cred_create(session_key, stored_cred, timestamp, &cred2); + /* Just in case this isn't already there */ + memcpy(dc->mach_pw, mach_pw, 16); - /* debug output*/ - DEBUG(4,("cred_assert\n")); + /* Generate the session key. */ + cred_create_session_key(clnt_chal, /* Stored client challenge. */ + srv_chal, /* Stored server challenge. */ + dc->mach_pw, /* input machine password. */ + dc->sess_key); /* output session key. */ - DEBUG(5,(" challenge : %s\n", credstr(cred->data))); - DEBUG(5,(" calculated: %s\n", credstr(cred2.data))); + dump_data_pw("creds_server_init: session key", dc->sess_key, 16); - if (memcmp(cred->data, cred2.data, 8) == 0) - { - DEBUG(5, ("credentials check ok\n")); - return True; - } - else - { - DEBUG(5, ("credentials check wrong\n")); + /* Generate the next client and server creds. */ + cred_hash2(dc->clnt_chal.data, /* output */ + clnt_chal->data, /* input */ + dc->sess_key); /* input */ + + cred_hash2(dc->srv_chal.data, /* output */ + srv_chal->data, /* input */ + dc->sess_key); /* input */ + + /* Seed is the client chal. */ + memcpy(dc->seed_chal.data, dc->clnt_chal.data, 8); + + DEBUG(10,("creds_server_init: clnt : %s\n", credstr(dc->clnt_chal.data) )); + DEBUG(10,("creds_server_init: server : %s\n", credstr(dc->srv_chal.data) )); + DEBUG(10,("creds_server_init: seed : %s\n", credstr(dc->seed_chal.data) )); + + memcpy(init_chal_out->data, dc->srv_chal.data, 8); +} + +/**************************************************************************** + Check a credential sent by the client. +****************************************************************************/ + +BOOL creds_server_check(const struct dcinfo *dc, const DOM_CHAL *rcv_cli_chal_in) +{ + if (memcmp(dc->clnt_chal.data, rcv_cli_chal_in->data, 8)) { + DEBUG(5,("creds_server_check: challenge : %s\n", credstr(rcv_cli_chal_in->data))); + DEBUG(5,("calculated: %s\n", credstr(dc->clnt_chal.data))); + DEBUG(0,("creds_server_check: credentials check failed.\n")); return False; } + DEBUG(10,("creds_server_check: credentials check OK.\n")); + return True; } - /**************************************************************************** - checks credentials; generates next step in the credential chain + Replace current seed chal. Internal function - due to split server step below. ****************************************************************************/ -BOOL clnt_deal_with_creds(uchar sess_key[8], - DOM_CRED *sto_clnt_cred, DOM_CRED *rcv_srv_cred) + +static void creds_reseed(struct dcinfo *dc) { - UTIME new_clnt_time; - uint32 new_cred; + DOM_CHAL time_chal; - DEBUG(5,("clnt_deal_with_creds: %d\n", __LINE__)); + SIVAL(time_chal.data, 0, IVAL(dc->seed_chal.data, 0) + dc->sequence + 1); + SIVAL(time_chal.data, 4, IVAL(dc->seed_chal.data, 4)); - /* increment client time by one second */ - new_clnt_time.time = sto_clnt_cred->timestamp.time + 1; + dc->seed_chal = time_chal; - /* check that the received server credentials are valid */ - if (!cred_assert(&rcv_srv_cred->challenge, sess_key, - &sto_clnt_cred->challenge, new_clnt_time)) - { - return False; - } + DEBUG(5,("cred_reseed: seed %s\n", credstr(dc->seed_chal.data) )); +} - /* first 4 bytes of the new seed is old client 4 bytes + clnt time + 1 */ - new_cred = IVAL(sto_clnt_cred->challenge.data, 0); - new_cred += new_clnt_time.time; +/**************************************************************************** + Step the server credential chain one forward. +****************************************************************************/ - /* store new seed in client credentials */ - SIVAL(sto_clnt_cred->challenge.data, 0, new_cred); +BOOL creds_server_step(struct dcinfo *dc, const DOM_CRED *received_cred, DOM_CRED *cred_out) +{ + dc->sequence = received_cred->timestamp.time; - DEBUG(5,(" new clnt cred: %s\n", credstr(sto_clnt_cred->challenge.data))); - return True; -} + creds_step(dc); + + /* Create the outgoing credentials */ + cred_out->timestamp.time = dc->sequence + 1; + cred_out->challenge = dc->srv_chal; + creds_reseed(dc); + + return creds_server_check(dc, &received_cred->challenge); +} /**************************************************************************** - checks credentials; generates next step in the credential chain + Create a client credential struct. ****************************************************************************/ -BOOL deal_with_creds(uchar sess_key[8], - DOM_CRED *sto_clnt_cred, - DOM_CRED *rcv_clnt_cred, DOM_CRED *rtn_srv_cred) + +void creds_client_init(struct dcinfo *dc, + DOM_CHAL *clnt_chal, + DOM_CHAL *srv_chal, + const char mach_pw[16], + DOM_CHAL *init_chal_out) { - UTIME new_clnt_time; - uint32 new_cred; + dc->sequence = time(NULL); - DEBUG(5,("deal_with_creds: %d\n", __LINE__)); + DEBUG(10,("creds_client_init: client chal : %s\n", credstr(clnt_chal->data) )); + DEBUG(10,("creds_client_init: server chal : %s\n", credstr(srv_chal->data) )); + dump_data_pw("creds_client_init: machine pass", mach_pw, 16); - /* check that the received client credentials are valid */ - if (!cred_assert(&rcv_clnt_cred->challenge, sess_key, - &sto_clnt_cred->challenge, rcv_clnt_cred->timestamp)) - { - return False; - } + /* Just in case this isn't already there */ + memcpy(dc->mach_pw, mach_pw, 16); - /* increment client time by one second */ - new_clnt_time.time = rcv_clnt_cred->timestamp.time + 1; + /* Generate the session key. */ + cred_create_session_key(clnt_chal, /* Stored client challenge. */ + srv_chal, /* Stored server challenge. */ + dc->mach_pw, /* input machine password. */ + dc->sess_key); /* output session key. */ - /* first 4 bytes of the new seed is old client 4 bytes + clnt time + 1 */ - new_cred = IVAL(sto_clnt_cred->challenge.data, 0); - new_cred += new_clnt_time.time; + dump_data_pw("creds_client_init: session key", dc->sess_key, 16); - DEBUG(5,("deal_with_creds: new_cred[0]=%x\n", new_cred)); + /* Generate the next client and server creds. */ + cred_hash2(dc->clnt_chal.data, /* output */ + clnt_chal->data, /* input */ + dc->sess_key); /* input */ - /* doesn't matter that server time is 0 */ - rtn_srv_cred->timestamp.time = 0; + cred_hash2(dc->srv_chal.data, /* output */ + srv_chal->data, /* input */ + dc->sess_key); /* input */ - DEBUG(5,("deal_with_creds: new_clnt_time=%x\n", new_clnt_time.time)); + /* Seed is the client cred. */ + memcpy(dc->seed_chal.data, dc->clnt_chal.data, 8); - /* create return credentials for inclusion in the reply */ - cred_create(sess_key, &sto_clnt_cred->challenge, new_clnt_time, - &rtn_srv_cred->challenge); - - DEBUG(5,("deal_with_creds: clnt_cred=%s\n", credstr(sto_clnt_cred->challenge.data))); + DEBUG(10,("creds_client_init: clnt : %s\n", credstr(dc->clnt_chal.data) )); + DEBUG(10,("creds_client_init: server : %s\n", credstr(dc->srv_chal.data) )); + DEBUG(10,("creds_client_init: seed : %s\n", credstr(dc->seed_chal.data) )); - /* store new seed in client credentials */ - SIVAL(sto_clnt_cred->challenge.data, 0, new_cred); + memcpy(init_chal_out->data, dc->clnt_chal.data, 8); +} + +/**************************************************************************** + Check a credential returned by the server. +****************************************************************************/ +BOOL creds_client_check(const struct dcinfo *dc, const DOM_CHAL *rcv_srv_chal_in) +{ + if (memcmp(dc->srv_chal.data, rcv_srv_chal_in->data, 8)) { + DEBUG(5,("creds_client_check: challenge : %s\n", credstr(rcv_srv_chal_in->data))); + DEBUG(5,("calculated: %s\n", credstr(dc->srv_chal.data))); + DEBUG(0,("creds_client_check: credentials check failed.\n")); + return False; + } + DEBUG(10,("creds_client_check: credentials check OK.\n")); return True; } + +/**************************************************************************** + Step the client credentials to the next element in the chain, updating the + current client and server credentials and the seed + produce the next authenticator in the sequence ready to send to + the server +****************************************************************************/ + +void creds_client_step(struct dcinfo *dc, DOM_CRED *next_cred_out) +{ + dc->sequence += 2; + creds_step(dc); + creds_reseed(dc); + + next_cred_out->challenge = dc->clnt_chal; + next_cred_out->timestamp.time = dc->sequence; +} diff --git a/source3/libsmb/errormap.c b/source3/libsmb/errormap.c index 8462fbee877..3c0b13ad6ff 100644 --- a/source3/libsmb/errormap.c +++ b/source3/libsmb/errormap.c @@ -62,7 +62,7 @@ static const struct { {ERRDOS, 193, NT_STATUS_BAD_INITIAL_PC}, {ERRDOS, 87, NT_STATUS_INVALID_CID}, {ERRHRD, ERRgeneral, NT_STATUS_TIMER_NOT_CANCELED}, - {ERRDOS, 87, NT_STATUS_INVALID_PARAMETER}, + {ERRDOS, ERRinvalidparam, NT_STATUS_INVALID_PARAMETER}, {ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_DEVICE}, {ERRDOS, ERRbadfile, NT_STATUS_NO_SUCH_FILE}, {ERRDOS, ERRbadfunc, NT_STATUS_INVALID_DEVICE_REQUEST}, @@ -338,7 +338,7 @@ static const struct { {ERRDOS, 203, NT_STATUS(0xc0000100)}, {ERRDOS, 145, NT_STATUS_DIRECTORY_NOT_EMPTY}, {ERRHRD, ERRgeneral, NT_STATUS_FILE_CORRUPT_ERROR}, - {ERRDOS, 267, NT_STATUS_NOT_A_DIRECTORY}, + {ERRDOS, ERRbaddirectory, NT_STATUS_NOT_A_DIRECTORY}, {ERRHRD, ERRgeneral, NT_STATUS_BAD_LOGON_SESSION_STATE}, {ERRHRD, ERRgeneral, NT_STATUS_LOGON_SESSION_COLLISION}, {ERRDOS, 206, NT_STATUS_NAME_TOO_LONG}, diff --git a/source3/libsmb/libsmb_compat.c b/source3/libsmb/libsmb_compat.c index f9461f93683..5699e153bbd 100644 --- a/source3/libsmb/libsmb_compat.c +++ b/source3/libsmb/libsmb_compat.c @@ -420,7 +420,7 @@ int smbc_open_print_job(const char *fname) { SMBCFILE * file = statcont->open_print_job(statcont, fname); if (!file) return -1; - return (int) file; + return file->cli_fd; } int smbc_list_print_jobs(const char *purl, smbc_list_print_job_fn fn) diff --git a/source3/libsmb/libsmbclient.c b/source3/libsmb/libsmbclient.c index fe8f878aa57..1e729abb221 100644 --- a/source3/libsmb/libsmbclient.c +++ b/source3/libsmb/libsmbclient.c @@ -80,6 +80,23 @@ static int DLIST_CONTAINS(SMBCFILE * list, SMBCFILE *p) { return False; } +/* + * Find an lsa pipe handle associated with a cli struct. + */ + +static struct rpc_pipe_client *find_lsa_pipe_hnd(struct cli_state *ipc_cli) +{ + struct rpc_pipe_client *pipe_hnd; + + for (pipe_hnd = ipc_cli->pipe_list; pipe_hnd; pipe_hnd = pipe_hnd->next) { + if (pipe_hnd->pipe_idx == PI_LSARPC) { + return pipe_hnd; + } + } + + return NULL; +} + static int smbc_close_ctx(SMBCCTX *context, SMBCFILE *file); static off_t smbc_lseek_ctx(SMBCCTX *context, SMBCFILE *file, off_t offset, int whence); @@ -800,6 +817,7 @@ SMBCSRV *smbc_attr_server(SMBCCTX *context, { struct in_addr ip; struct cli_state *ipc_cli; + struct rpc_pipe_client *pipe_hnd; NTSTATUS nt_status; SMBCSRV *ipc_srv=NULL; @@ -835,29 +853,27 @@ SMBCSRV *smbc_attr_server(SMBCCTX *context, return NULL; } - if(pol) { + pipe_hnd = cli_rpc_pipe_open_noauth(ipc_cli, PI_LSARPC, &nt_status); + if (!pipe_hnd) { + DEBUG(1, ("cli_nt_session_open fail!\n")); + errno = ENOTSUP; + cli_shutdown(ipc_cli); + return NULL; + } - if (!cli_nt_session_open(ipc_cli, PI_LSARPC)) { - DEBUG(1, ("cli_nt_session_open fail!\n")); - errno = ENOTSUP; - cli_shutdown(ipc_cli); - return NULL; - } - - /* Some systems don't support SEC_RIGHTS_MAXIMUM_ALLOWED, - but NT sends 0x2000000 so we might as well do it too. */ - - nt_status = cli_lsa_open_policy(ipc_cli, - ipc_cli->mem_ctx, - True, - GENERIC_EXECUTE_ACCESS, - pol); - - if (!NT_STATUS_IS_OK(nt_status)) { - errno = smbc_errno(context, ipc_cli); - cli_shutdown(ipc_cli); - return NULL; - } + /* Some systems don't support SEC_RIGHTS_MAXIMUM_ALLOWED, + but NT sends 0x2000000 so we might as well do it too. */ + + nt_status = rpccli_lsa_open_policy(pipe_hnd, + ipc_cli->mem_ctx, + True, + GENERIC_EXECUTE_ACCESS, + pol); + + if (!NT_STATUS_IS_OK(nt_status)) { + errno = smbc_errno(context, ipc_cli); + cli_shutdown(ipc_cli); + return NULL; } ipc_srv = SMB_MALLOC_P(SMBCSRV); @@ -1782,7 +1798,7 @@ static off_t smbc_lseek_ctx(SMBCCTX *context, SMBCFILE *file, off_t offset, int if (!cli_qfileinfo(targetcli, file->cli_fd, NULL, &size, NULL, NULL, NULL, NULL, NULL)) { - SMB_BIG_UINT b_size = size; + SMB_OFF_T b_size = size; if (!cli_getattrE(targetcli, file->cli_fd, NULL, &b_size, NULL, NULL, NULL)) { @@ -3041,7 +3057,7 @@ static off_t smbc_telldir_ctx(SMBCCTX *context, SMBCFILE *dir) /* * We return the pointer here as the offset */ - ret_val = (int)dir->dir_next; + ret_val = (off_t)(long)dir->dir_next; return ret_val; } @@ -3347,14 +3363,20 @@ static void convert_sid_to_string(struct cli_state *ipc_cli, char **domains = NULL; char **names = NULL; uint32 *types = NULL; - + struct rpc_pipe_client *pipe_hnd = find_lsa_pipe_hnd(ipc_cli); sid_to_string(str, sid); - if (numeric) return; /* no lookup desired */ - + if (numeric) { + return; /* no lookup desired */ + } + + if (!pipe_hnd) { + return; + } + /* Ask LSA to convert the sid to a name */ - if (!NT_STATUS_IS_OK(cli_lsa_lookup_sids(ipc_cli, ipc_cli->mem_ctx, + if (!NT_STATUS_IS_OK(rpccli_lsa_lookup_sids(pipe_hnd, ipc_cli->mem_ctx, pol, 1, sid, &domains, &names, &types)) || !domains || !domains[0] || !names || !names[0]) { @@ -3378,6 +3400,11 @@ static BOOL convert_string_to_sid(struct cli_state *ipc_cli, uint32 *types = NULL; DOM_SID *sids = NULL; BOOL result = True; + struct rpc_pipe_client *pipe_hnd = find_lsa_pipe_hnd(ipc_cli); + + if (!pipe_hnd) { + return False; + } if (numeric) { if (strncmp(str, "S-", 2) == 0) { @@ -3388,7 +3415,7 @@ static BOOL convert_string_to_sid(struct cli_state *ipc_cli, goto done; } - if (!NT_STATUS_IS_OK(cli_lsa_lookup_names(ipc_cli, ipc_cli->mem_ctx, + if (!NT_STATUS_IS_OK(rpccli_lsa_lookup_names(pipe_hnd, ipc_cli->mem_ctx, pol, 1, &str, &sids, &types))) { result = False; @@ -5161,7 +5188,7 @@ static int smbc_print_file_ctx(SMBCCTX *c_file, const char *fname, SMBCCTX *c_pr /* Try to open the file for reading ... */ - if ((int)(fid1 = c_file->open(c_file, fname, O_RDONLY, 0666)) < 0) { + if ((long)(fid1 = c_file->open(c_file, fname, O_RDONLY, 0666)) < 0) { DEBUG(3, ("Error, fname=%s, errno=%i\n", fname, errno)); return -1; /* smbc_open sets errno */ @@ -5170,7 +5197,7 @@ static int smbc_print_file_ctx(SMBCCTX *c_file, const char *fname, SMBCCTX *c_pr /* Now, try to open the printer file for writing */ - if ((int)(fid2 = c_print->open_print_job(c_print, printq)) < 0) { + if ((long)(fid2 = c_print->open_print_job(c_print, printq)) < 0) { saverr = errno; /* Save errno */ c_file->close_fn(c_file, fid1); diff --git a/source3/libsmb/ntlmssp.c b/source3/libsmb/ntlmssp.c index b02c2384a8d..6b551e8774c 100644 --- a/source3/libsmb/ntlmssp.c +++ b/source3/libsmb/ntlmssp.c @@ -5,6 +5,7 @@ Copyright (C) Andrew Tridgell 2001 Copyright (C) Andrew Bartlett 2001-2003 + Copyright (C) Andrew Bartlett 2005 (Updated from gensec). 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 @@ -217,6 +218,12 @@ NTSTATUS ntlmssp_update(NTLMSSP_STATE *ntlmssp_state, uint32 ntlmssp_command; int i; + if (ntlmssp_state->expected_state == NTLMSSP_DONE) { + /* Called update after negotiations finished. */ + DEBUG(1, ("Called NTLMSSP after state machine was 'done'\n")); + return NT_STATUS_INVALID_PARAMETER; + } + *out = data_blob(NULL, 0); if (!in.length && ntlmssp_state->stored_response.length) { @@ -348,6 +355,13 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state, if (!(neg_flags & NTLMSSP_NEGOTIATE_128)) { ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_128; + if (neg_flags & NTLMSSP_NEGOTIATE_56) { + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_56; + } + } + + if (!(neg_flags & NTLMSSP_NEGOTIATE_56)) { + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_56; } if (!(neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) { @@ -360,6 +374,34 @@ static void ntlmssp_handle_neg_flags(struct ntlmssp_state *ntlmssp_state, } +/** + Weaken NTLMSSP keys to cope with down-level clients and servers. + + We probably should have some parameters to control this, but as + it only occours for LM_KEY connections, and this is controlled + by the client lanman auth/lanman auth parameters, it isn't too bad. +*/ + +void ntlmssp_weaken_keys(NTLMSSP_STATE *ntlmssp_state) +{ + /* Key weakening not performed on the master key for NTLM2 + and does not occour for NTLM1. Therefore we only need + to do this for the LM_KEY. + */ + + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) { + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_128) { + ; + } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) { + ntlmssp_state->session_key.data[7] = 0xa0; + } else { /* forty bits */ + ntlmssp_state->session_key.data[5] = 0xe5; + ntlmssp_state->session_key.data[6] = 0x38; + ntlmssp_state->session_key.data[7] = 0xb0; + } + ntlmssp_state->session_key.length = 8; + } +} /** * Next state function for the Negotiate packet @@ -398,6 +440,9 @@ static NTSTATUS ntlmssp_server_negotiate(struct ntlmssp_state *ntlmssp_state, return NT_STATUS_INVALID_PARAMETER; } + DEBUG(10, ("ntlmssp_server_negotiate: client = %s, domain = %s\n", + cliname ? cliname : "", domname ? domname : "")); + SAFE_FREE(cliname); SAFE_FREE(domname); @@ -495,7 +540,7 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, DATA_BLOB lm_session_key = data_blob(NULL, 0); DATA_BLOB session_key = data_blob(NULL, 0); uint32 ntlmssp_command, auth_flags; - NTSTATUS nt_status; + NTSTATUS nt_status = NT_STATUS_OK; /* used by NTLM2 */ BOOL doing_ntlm2 = False; @@ -639,6 +684,9 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, data_blob_free(&encrypted_session_key); return nt_status; } + + /* LM Key is incompatible. */ + ntlmssp_state->neg_flags &= ~NTLMSSP_NEGOTIATE_LM_KEY; } } @@ -710,11 +758,11 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, if (!encrypted_session_key.data || encrypted_session_key.length != 16) { data_blob_free(&encrypted_session_key); DEBUG(1, ("Client-supplied KEY_EXCH session key was of invalid length (%u)!\n", - encrypted_session_key.length)); + (unsigned int)encrypted_session_key.length)); return NT_STATUS_INVALID_PARAMETER; } else if (!session_key.data || session_key.length != 16) { DEBUG(5, ("server session key is invalid (len == %u), cannot do KEY_EXCH!\n", - session_key.length)); + (unsigned int)session_key.length)); ntlmssp_state->session_key = session_key; } else { dump_data_pw("KEY_EXCH session key (enc):\n", encrypted_session_key.data, encrypted_session_key.length); @@ -731,6 +779,9 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, ntlmssp_state->session_key = session_key; } + /* The client might need us to use a partial-strength session key */ + ntlmssp_weaken_keys(ntlmssp_state); + if (!NT_STATUS_IS_OK(nt_status)) { ntlmssp_state->session_key = data_blob(NULL, 0); } else if (ntlmssp_state->session_key.length) { @@ -739,8 +790,8 @@ static NTSTATUS ntlmssp_server_auth(struct ntlmssp_state *ntlmssp_state, data_blob_free(&encrypted_session_key); - /* allow arbitarily many authentications */ - ntlmssp_state->expected_state = NTLMSSP_AUTH; + /* Only one authentication allowed per server state. */ + ntlmssp_state->expected_state = NTLMSSP_DONE; return nt_status; } @@ -784,7 +835,8 @@ NTSTATUS ntlmssp_server_start(NTLMSSP_STATE **ntlmssp_state) NTLMSSP_NEGOTIATE_NTLM | NTLMSSP_NEGOTIATE_NTLM2 | NTLMSSP_NEGOTIATE_KEY_EXCH | - NTLMSSP_NEGOTIATE_SIGN; + NTLMSSP_NEGOTIATE_SIGN | + NTLMSSP_NEGOTIATE_SEAL; return NT_STATUS_OK; } @@ -851,7 +903,7 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, DATA_BLOB nt_response = data_blob(NULL, 0); DATA_BLOB session_key = data_blob(NULL, 0); DATA_BLOB encrypted_session_key = data_blob(NULL, 0); - NTSTATUS nt_status; + NTSTATUS nt_status = NT_STATUS_OK; if (!msrpc_parse(&reply, "CdBd", "NTLMSSP", @@ -977,8 +1029,6 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, hmac_md5(user_session_key, session_nonce, sizeof(session_nonce), session_key.data); dump_data_pw("NTLM2 session key:\n", session_key.data, session_key.length); } else { - - uchar lm_hash[16]; uchar nt_hash[16]; E_deshash(ntlmssp_state->password, lm_hash); @@ -998,8 +1048,8 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, session_key = data_blob_talloc(ntlmssp_state->mem_ctx, NULL, 16); if ((ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) && lp_client_lanman_auth()) { - SMBsesskeygen_lmv1(lm_hash, lm_response.data, - session_key.data); + SMBsesskeygen_lm_sess_key(lm_hash, lm_response.data, + session_key.data); dump_data_pw("LM session key\n", session_key.data, session_key.length); } else { SMBsesskeygen_ntv1(nt_hash, NULL, session_key.data); @@ -1045,19 +1095,22 @@ static NTSTATUS ntlmssp_client_challenge(struct ntlmssp_state *ntlmssp_state, data_blob_free(&ntlmssp_state->chal); + ntlmssp_state->session_key = session_key; + + /* The client might be using 56 or 40 bit weakened keys */ + ntlmssp_weaken_keys(ntlmssp_state); + ntlmssp_state->chal = challenge_blob; ntlmssp_state->lm_resp = lm_response; ntlmssp_state->nt_resp = nt_response; - ntlmssp_state->session_key = session_key; - ntlmssp_state->expected_state = NTLMSSP_UNKNOWN; + ntlmssp_state->expected_state = NTLMSSP_DONE; if (!NT_STATUS_IS_OK(nt_status = ntlmssp_sign_init(ntlmssp_state))) { DEBUG(1, ("Could not setup NTLMSSP signing/sealing system (error was: %s)\n", nt_errstr(nt_status))); - return nt_status; } - return NT_STATUS_MORE_PROCESSING_REQUIRED; + return nt_status; } NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state) @@ -1103,4 +1156,3 @@ NTSTATUS ntlmssp_client_start(NTLMSSP_STATE **ntlmssp_state) return NT_STATUS_OK; } - diff --git a/source3/libsmb/ntlmssp_parse.c b/source3/libsmb/ntlmssp_parse.c index 4b3043aec80..e71504867e9 100644 --- a/source3/libsmb/ntlmssp_parse.c +++ b/source3/libsmb/ntlmssp_parse.c @@ -216,7 +216,7 @@ BOOL msrpc_parse(const DATA_BLOB *blob, /* if odd length and unicode */ return False; } - if (blob->data + ptr < (uint8 *)ptr || blob->data + ptr < blob->data) + if (blob->data + ptr < (uint8 *)(unsigned long)ptr || blob->data + ptr < blob->data) return False; if (0 < len1) { @@ -244,7 +244,7 @@ BOOL msrpc_parse(const DATA_BLOB *blob, return False; } - if (blob->data + ptr < (uint8 *)ptr || blob->data + ptr < blob->data) + if (blob->data + ptr < (uint8 *)(unsigned long)ptr || blob->data + ptr < blob->data) return False; if (0 < len1) { @@ -272,7 +272,7 @@ BOOL msrpc_parse(const DATA_BLOB *blob, return False; } - if (blob->data + ptr < (uint8 *)ptr || blob->data + ptr < blob->data) + if (blob->data + ptr < (uint8 *)(unsigned long)ptr || blob->data + ptr < blob->data) return False; *b = data_blob(blob->data + ptr, len1); diff --git a/source3/libsmb/ntlmssp_sign.c b/source3/libsmb/ntlmssp_sign.c index b8105970762..51023ca3565 100644 --- a/source3/libsmb/ntlmssp_sign.c +++ b/source3/libsmb/ntlmssp_sign.c @@ -2,8 +2,7 @@ * Unix SMB/CIFS implementation. * Version 3.0 * NTLMSSP Signing routines - * Copyright (C) Luke Kenneth Casson Leighton 1996-2001 - * Copyright (C) Andrew Bartlett 2003 + * Copyright (C) Andrew Bartlett 2003-2005 * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,74 +26,25 @@ #define SRV_SIGN "session key to server-to-client signing key magic constant" #define SRV_SEAL "session key to server-to-client sealing key magic constant" -static void NTLMSSPcalc_ap( unsigned char *hash, unsigned char *data, int len) -{ - unsigned char index_i = hash[256]; - unsigned char index_j = hash[257]; - int ind; - - for (ind = 0; ind < len; ind++) - { - unsigned char tc; - unsigned char t; - - index_i++; - index_j += hash[index_i]; - - tc = hash[index_i]; - hash[index_i] = hash[index_j]; - hash[index_j] = tc; - - t = hash[index_i] + hash[index_j]; - data[ind] = data[ind] ^ hash[t]; - } - - hash[256] = index_i; - hash[257] = index_j; -} - -static void calc_hash(unsigned char hash[258], unsigned char *k2, int k2l) -{ - unsigned char j = 0; - int ind; - - for (ind = 0; ind < 256; ind++) - { - hash[ind] = (unsigned char)ind; - } - - for (ind = 0; ind < 256; ind++) - { - unsigned char tc; - - j += (hash[ind] + k2[ind%k2l]); - - tc = hash[ind]; - hash[ind] = hash[j]; - hash[j] = tc; - } - - hash[256] = 0; - hash[257] = 0; -} +/** + * Some notes on then NTLM2 code: + * + * NTLM2 is a AEAD system. This means that the data encrypted is not + * all the data that is signed. In DCE-RPC case, the headers of the + * DCE-RPC packets are also signed. This prevents some of the + * fun-and-games one might have by changing them. + * + */ -static void calc_ntlmv2_hash(unsigned char hash[258], unsigned char digest[16], - DATA_BLOB session_key, - const char *constant) +static void calc_ntlmv2_key(unsigned char subkey[16], + DATA_BLOB session_key, + const char *constant) { struct MD5Context ctx3; - - /* NOTE: This code is currently complate fantasy - it's - got more in common with reality than the previous code - (the LM session key is not the right thing to use) but - it still needs work */ - MD5Init(&ctx3); MD5Update(&ctx3, session_key.data, session_key.length); - MD5Update(&ctx3, (const unsigned char *)constant, strlen(constant)+1); - MD5Final(digest, &ctx3); - - calc_hash(hash, digest, 16); + MD5Update(&ctx3, constant, strlen(constant)+1); + MD5Final(subkey, &ctx3); } enum ntlmssp_direction { @@ -103,64 +53,107 @@ enum ntlmssp_direction { }; static NTSTATUS ntlmssp_make_packet_signature(NTLMSSP_STATE *ntlmssp_state, - const uchar *data, size_t length, - enum ntlmssp_direction direction, - DATA_BLOB *sig) + const uchar *data, size_t length, + const uchar *whole_pdu, size_t pdu_length, + enum ntlmssp_direction direction, + DATA_BLOB *sig, + BOOL encrypt_sig) { if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { HMACMD5Context ctx; uchar seq_num[4]; uchar digest[16]; - SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num); - - hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->send_sign_const), 16, &ctx); - hmac_md5_update(seq_num, 4, &ctx); - hmac_md5_update(data, length, &ctx); - hmac_md5_final(digest, &ctx); - if (!msrpc_gen(sig, "dBd", NTLMSSP_SIGN_VERSION, digest, 8 /* only copy first 8 bytes */ - , ntlmssp_state->ntlmssp_seq_num)) { + *sig = data_blob(NULL, NTLMSSP_SIG_SIZE); + if (!sig->data) { return NT_STATUS_NO_MEMORY; } - if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { + switch (direction) { + case NTLMSSP_SEND: + DEBUG(100,("ntlmssp_make_packet_signature: SEND seq = %u, len = %u, pdu_len = %u\n", + ntlmssp_state->ntlm2_send_seq_num, + (unsigned int)length, + (unsigned int)pdu_length)); + + SIVAL(seq_num, 0, ntlmssp_state->ntlm2_send_seq_num); + ntlmssp_state->ntlm2_send_seq_num++; + hmac_md5_init_limK_to_64(ntlmssp_state->send_sign_key, 16, &ctx); + break; + case NTLMSSP_RECEIVE: + + DEBUG(100,("ntlmssp_make_packet_signature: RECV seq = %u, len = %u, pdu_len = %u\n", + ntlmssp_state->ntlm2_recv_seq_num, + (unsigned int)length, + (unsigned int)pdu_length)); + + SIVAL(seq_num, 0, ntlmssp_state->ntlm2_recv_seq_num); + ntlmssp_state->ntlm2_recv_seq_num++; + hmac_md5_init_limK_to_64(ntlmssp_state->recv_sign_key, 16, &ctx); + break; + } + + dump_data_pw("pdu data ", whole_pdu, pdu_length); + + hmac_md5_update(seq_num, 4, &ctx); + hmac_md5_update(whole_pdu, pdu_length, &ctx); + hmac_md5_final(digest, &ctx); + + if (encrypt_sig && (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH)) { switch (direction) { case NTLMSSP_SEND: - NTLMSSPcalc_ap(ntlmssp_state->send_sign_hash, sig->data+4, sig->length-4); + smb_arc4_crypt(ntlmssp_state->send_seal_arc4_state, digest, 8); break; case NTLMSSP_RECEIVE: - NTLMSSPcalc_ap(ntlmssp_state->recv_sign_hash, sig->data+4, sig->length-4); + smb_arc4_crypt(ntlmssp_state->recv_seal_arc4_state, digest, 8); break; } } + + SIVAL(sig->data, 0, NTLMSSP_SIGN_VERSION); + memcpy(sig->data + 4, digest, 8); + memcpy(sig->data + 12, seq_num, 4); + + dump_data_pw("ntlmssp v2 sig ", sig->data, sig->length); + } else { uint32 crc; crc = crc32_calc_buffer((const char *)data, length); - if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) { + if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmv1_seq_num)) { return NT_STATUS_NO_MEMORY; } - dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash, - sizeof(ntlmssp_state->ntlmssp_hash)); - NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, sig->data+4, sig->length-4); + ntlmssp_state->ntlmv1_seq_num++; + + dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmv1_arc4_state, + sizeof(ntlmssp_state->ntlmv1_arc4_state)); + smb_arc4_crypt(ntlmssp_state->ntlmv1_arc4_state, sig->data+4, sig->length-4); } return NT_STATUS_OK; } NTSTATUS ntlmssp_sign_packet(NTLMSSP_STATE *ntlmssp_state, const uchar *data, size_t length, + const uchar *whole_pdu, size_t pdu_length, DATA_BLOB *sig) { NTSTATUS nt_status; + + if (!ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SIGN) { + DEBUG(3, ("NTLMSSP Signing not negotiated - cannot sign packet!\n")); + return NT_STATUS_INVALID_PARAMETER; + } + if (!ntlmssp_state->session_key.length) { DEBUG(3, ("NO session key, cannot check sign packet\n")); return NT_STATUS_NO_USER_SESSION_KEY; } - nt_status = ntlmssp_make_packet_signature(ntlmssp_state, data, length, NTLMSSP_SEND, sig); + nt_status = ntlmssp_make_packet_signature(ntlmssp_state, + data, length, + whole_pdu, pdu_length, + NTLMSSP_SEND, sig, True); - /* increment counter on send */ - ntlmssp_state->ntlmssp_seq_num++; return nt_status; } @@ -171,8 +164,9 @@ NTSTATUS ntlmssp_sign_packet(NTLMSSP_STATE *ntlmssp_state, */ NTSTATUS ntlmssp_check_packet(NTLMSSP_STATE *ntlmssp_state, - const uchar *data, size_t length, - const DATA_BLOB *sig) + const uchar *data, size_t length, + const uchar *whole_pdu, size_t pdu_length, + const DATA_BLOB *sig) { DATA_BLOB local_sig; NTSTATUS nt_status; @@ -187,32 +181,51 @@ NTSTATUS ntlmssp_check_packet(NTLMSSP_STATE *ntlmssp_state, (unsigned long)sig->length)); } - nt_status = ntlmssp_make_packet_signature(ntlmssp_state, data, - length, NTLMSSP_RECEIVE, &local_sig); + nt_status = ntlmssp_make_packet_signature(ntlmssp_state, + data, length, + whole_pdu, pdu_length, + NTLMSSP_RECEIVE, &local_sig, True); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("NTLMSSP packet check failed with %s\n", nt_errstr(nt_status))); + data_blob_free(&local_sig); return nt_status; } - if (memcmp(sig->data+sig->length - 8, local_sig.data+local_sig.length - 8, 8) != 0) { - DEBUG(5, ("BAD SIG: wanted signature of\n")); - dump_data(5, (const char *)local_sig.data, local_sig.length); - - DEBUG(5, ("BAD SIG: got signature of\n")); - dump_data(5, (const char *)(sig->data), sig->length); + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { + if (local_sig.length != sig->length || + memcmp(local_sig.data, sig->data, sig->length) != 0) { + DEBUG(5, ("BAD SIG NTLM2: wanted signature of\n")); + dump_data(5, local_sig.data, local_sig.length); - DEBUG(0, ("NTLMSSP packet check failed due to invalid signature!\n")); - return NT_STATUS_ACCESS_DENIED; - } + DEBUG(5, ("BAD SIG: got signature of\n")); + dump_data(5, sig->data, sig->length); + + DEBUG(0, ("NTLMSSP NTLM2 packet check failed due to invalid signature!\n")); + data_blob_free(&local_sig); + return NT_STATUS_ACCESS_DENIED; + } + } else { + if (local_sig.length != sig->length || + memcmp(local_sig.data + 8, sig->data + 8, sig->length - 8) != 0) { + DEBUG(5, ("BAD SIG NTLM1: wanted signature of\n")); + dump_data(5, local_sig.data, local_sig.length); + + DEBUG(5, ("BAD SIG: got signature of\n")); + dump_data(5, sig->data, sig->length); - /* increment counter on recieive */ - ntlmssp_state->ntlmssp_seq_num++; + DEBUG(0, ("NTLMSSP NTLM1 packet check failed due to invalid signature!\n")); + data_blob_free(&local_sig); + return NT_STATUS_ACCESS_DENIED; + } + } + dump_data_pw("checked ntlmssp signature\n", sig->data, sig->length); + DEBUG(10,("ntlmssp_check_packet: NTLMSSP signature OK !\n")); + data_blob_free(&local_sig); return NT_STATUS_OK; } - /** * Seal data with the NTLMSSP algorithm * @@ -220,8 +233,16 @@ NTSTATUS ntlmssp_check_packet(NTLMSSP_STATE *ntlmssp_state, NTSTATUS ntlmssp_seal_packet(NTLMSSP_STATE *ntlmssp_state, uchar *data, size_t length, + uchar *whole_pdu, size_t pdu_length, DATA_BLOB *sig) { + NTSTATUS nt_status; + + if (!ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_SEAL) { + DEBUG(3, ("NTLMSSP Sealing not negotiated - cannot seal packet!\n")); + return NT_STATUS_INVALID_PARAMETER; + } + if (!ntlmssp_state->session_key.length) { DEBUG(3, ("NO session key, cannot seal packet\n")); return NT_STATUS_NO_USER_SESSION_KEY; @@ -230,53 +251,44 @@ NTSTATUS ntlmssp_seal_packet(NTLMSSP_STATE *ntlmssp_state, DEBUG(10,("ntlmssp_seal_data: seal\n")); dump_data_pw("ntlmssp clear data\n", data, length); if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { - HMACMD5Context ctx; - char seq_num[4]; - uchar digest[16]; - SIVAL(seq_num, 0, ntlmssp_state->ntlmssp_seq_num); - - hmac_md5_init_limK_to_64((const unsigned char *)(ntlmssp_state->send_sign_const), 16, &ctx); - hmac_md5_update((const unsigned char *)seq_num, 4, &ctx); - hmac_md5_update(data, length, &ctx); - hmac_md5_final(digest, &ctx); - - if (!msrpc_gen(sig, "dBd", NTLMSSP_SIGN_VERSION, digest, 8 /* only copy first 8 bytes */ - , ntlmssp_state->ntlmssp_seq_num)) { - return NT_STATUS_NO_MEMORY; + /* The order of these two operations matters - we must first seal the packet, + then seal the sequence number - this is becouse the send_seal_hash is not + constant, but is is rather updated with each iteration */ + nt_status = ntlmssp_make_packet_signature(ntlmssp_state, + data, length, + whole_pdu, pdu_length, + NTLMSSP_SEND, sig, False); + smb_arc4_crypt(ntlmssp_state->send_seal_arc4_state, data, length); + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_KEY_EXCH) { + smb_arc4_crypt(ntlmssp_state->send_seal_arc4_state, sig->data+4, 8); } - - dump_data_pw("ntlmssp client sealing hash:\n", - ntlmssp_state->send_seal_hash, - sizeof(ntlmssp_state->send_seal_hash)); - NTLMSSPcalc_ap(ntlmssp_state->send_seal_hash, data, length); - dump_data_pw("ntlmssp client signing hash:\n", - ntlmssp_state->send_sign_hash, - sizeof(ntlmssp_state->send_sign_hash)); - NTLMSSPcalc_ap(ntlmssp_state->send_sign_hash, sig->data+4, sig->length-4); } else { uint32 crc; crc = crc32_calc_buffer((const char *)data, length); - if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmssp_seq_num)) { + if (!msrpc_gen(sig, "dddd", NTLMSSP_SIGN_VERSION, 0, crc, ntlmssp_state->ntlmv1_seq_num)) { return NT_STATUS_NO_MEMORY; } /* The order of these two operations matters - we must first seal the packet, - then seal the sequence number - this is becouse the ntlmssp_hash is not + then seal the sequence number - this is becouse the ntlmv1_arc4_state is not constant, but is is rather updated with each iteration */ - dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash, - sizeof(ntlmssp_state->ntlmssp_hash)); - NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, data, length); + dump_data_pw("ntlmv1 arc4 state:\n", ntlmssp_state->ntlmv1_arc4_state, + sizeof(ntlmssp_state->ntlmv1_arc4_state)); + smb_arc4_crypt(ntlmssp_state->ntlmv1_arc4_state, data, length); + + dump_data_pw("ntlmv1 arc4 state:\n", ntlmssp_state->ntlmv1_arc4_state, + sizeof(ntlmssp_state->ntlmv1_arc4_state)); + + smb_arc4_crypt(ntlmssp_state->ntlmv1_arc4_state, sig->data+4, sig->length-4); - dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash, - sizeof(ntlmssp_state->ntlmssp_hash)); - NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, sig->data+4, sig->length-4); + ntlmssp_state->ntlmv1_seq_num++; + + nt_status = NT_STATUS_OK; } + dump_data_pw("ntlmssp signature\n", sig->data, sig->length); dump_data_pw("ntlmssp sealed data\n", data, length); - /* increment counter on send */ - ntlmssp_state->ntlmssp_seq_num++; - return NT_STATUS_OK; } @@ -286,26 +298,27 @@ NTSTATUS ntlmssp_seal_packet(NTLMSSP_STATE *ntlmssp_state, */ NTSTATUS ntlmssp_unseal_packet(NTLMSSP_STATE *ntlmssp_state, - uchar *data, size_t length, - DATA_BLOB *sig) + uchar *data, size_t length, + uchar *whole_pdu, size_t pdu_length, + DATA_BLOB *sig) { if (!ntlmssp_state->session_key.length) { DEBUG(3, ("NO session key, cannot unseal packet\n")); return NT_STATUS_NO_USER_SESSION_KEY; } - DEBUG(10,("ntlmssp__unseal_data: seal\n")); + DEBUG(10,("ntlmssp_unseal_data: seal\n")); dump_data_pw("ntlmssp sealed data\n", data, length); + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { - NTLMSSPcalc_ap(ntlmssp_state->recv_seal_hash, data, length); + /* First unseal the data. */ + smb_arc4_crypt(ntlmssp_state->recv_seal_arc4_state, data, length); + dump_data_pw("ntlmv2 clear data\n", data, length); } else { - dump_data_pw("ntlmssp hash:\n", ntlmssp_state->ntlmssp_hash, - sizeof(ntlmssp_state->ntlmssp_hash)); - NTLMSSPcalc_ap(ntlmssp_state->ntlmssp_hash, data, length); + smb_arc4_crypt(ntlmssp_state->ntlmv1_arc4_state, data, length); + dump_data_pw("ntlmv1 clear data\n", data, length); } - dump_data_pw("ntlmssp clear data\n", data, length); - - return ntlmssp_check_packet(ntlmssp_state, data, length, sig); + return ntlmssp_check_packet(ntlmssp_state, data, length, whole_pdu, pdu_length, sig); } /** @@ -326,6 +339,7 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state) if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_NTLM2) { + DATA_BLOB weak_session_key = ntlmssp_state->session_key; const char *send_sign_const; const char *send_seal_const; const char *recv_sign_const; @@ -352,62 +366,96 @@ NTSTATUS ntlmssp_sign_init(NTLMSSP_STATE *ntlmssp_state) break; } - calc_ntlmv2_hash(ntlmssp_state->send_sign_hash, - ntlmssp_state->send_sign_const, - ntlmssp_state->session_key, send_sign_const); - dump_data_pw("NTLMSSP send sign hash:\n", - ntlmssp_state->send_sign_hash, - sizeof(ntlmssp_state->send_sign_hash)); - - calc_ntlmv2_hash(ntlmssp_state->send_seal_hash, - ntlmssp_state->send_seal_const, - ntlmssp_state->session_key, send_seal_const); - dump_data_pw("NTLMSSP send sesl hash:\n", - ntlmssp_state->send_seal_hash, - sizeof(ntlmssp_state->send_seal_hash)); - - calc_ntlmv2_hash(ntlmssp_state->recv_sign_hash, - ntlmssp_state->recv_sign_const, - ntlmssp_state->session_key, recv_sign_const); - dump_data_pw("NTLMSSP receive sign hash:\n", - ntlmssp_state->recv_sign_hash, - sizeof(ntlmssp_state->recv_sign_hash)); - - calc_ntlmv2_hash(ntlmssp_state->recv_seal_hash, - ntlmssp_state->recv_seal_const, - ntlmssp_state->session_key, recv_seal_const); - dump_data_pw("NTLMSSP receive seal hash:\n", - ntlmssp_state->recv_sign_hash, - sizeof(ntlmssp_state->recv_sign_hash)); - - } - else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_LM_KEY) { - if (!ntlmssp_state->session_key.data || ntlmssp_state->session_key.length < 8) { - /* can't sign or check signatures yet */ - DEBUG(5, ("NTLMSSP Sign/Seal - cannot use LM KEY yet\n")); - return NT_STATUS_UNSUCCESSFUL; + /** + Weaken NTLMSSP keys to cope with down-level clients, servers and export restrictions. + We probably should have some parameters to control this, once we get NTLM2 working. + */ + + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_128) { + ; + } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) { + weak_session_key.length = 6; + } else { /* forty bits */ + weak_session_key.length = 5; } + + dump_data_pw("NTLMSSP weakend master key:\n", + weak_session_key.data, + weak_session_key.length); + + /* SEND */ + calc_ntlmv2_key(ntlmssp_state->send_sign_key, + ntlmssp_state->session_key, send_sign_const); + dump_data_pw("NTLMSSP send sign key:\n", + ntlmssp_state->send_sign_key, 16); + + calc_ntlmv2_key(ntlmssp_state->send_seal_key, + weak_session_key, send_seal_const); + dump_data_pw("NTLMSSP send seal key:\n", + ntlmssp_state->send_seal_key, 16); + + smb_arc4_init(ntlmssp_state->send_seal_arc4_state, + ntlmssp_state->send_seal_key, 16); + + dump_data_pw("NTLMSSP send seal arc4 state:\n", + ntlmssp_state->send_seal_arc4_state, + sizeof(ntlmssp_state->send_seal_arc4_state)); + + /* RECV */ + calc_ntlmv2_key(ntlmssp_state->recv_sign_key, + ntlmssp_state->session_key, recv_sign_const); + dump_data_pw("NTLMSSP recv send sign key:\n", + ntlmssp_state->recv_sign_key, 16); + + calc_ntlmv2_key(ntlmssp_state->recv_seal_key, + weak_session_key, recv_seal_const); - DEBUG(5, ("NTLMSSP Sign/Seal - using LM KEY\n")); + dump_data_pw("NTLMSSP recv seal key:\n", + ntlmssp_state->recv_seal_key, 16); + + smb_arc4_init(ntlmssp_state->recv_seal_arc4_state, + ntlmssp_state->recv_seal_key, 16); + + dump_data_pw("NTLMSSP recv seal arc4 state:\n", + ntlmssp_state->recv_seal_arc4_state, + sizeof(ntlmssp_state->recv_seal_arc4_state)); + + ntlmssp_state->ntlm2_send_seq_num = 0; + ntlmssp_state->ntlm2_recv_seq_num = 0; + - calc_hash(ntlmssp_state->ntlmssp_hash, ntlmssp_state->session_key.data, 8); - dump_data_pw("NTLMSSP hash:\n", ntlmssp_state->ntlmssp_hash, - sizeof(ntlmssp_state->ntlmssp_hash)); } else { - if (!ntlmssp_state->session_key.data || ntlmssp_state->session_key.length < 16) { - /* can't sign or check signatures yet */ - DEBUG(5, ("NTLMSSP Sign/Seal - cannot use NT KEY yet\n")); - return NT_STATUS_UNSUCCESSFUL; +#if 0 + /* Hmmm. Shouldn't we also weaken keys for ntlmv1 ? JRA. */ + + DATA_BLOB weak_session_key = ntlmssp_state->session_key; + /** + Weaken NTLMSSP keys to cope with down-level clients, servers and export restrictions. + We probably should have some parameters to control this, once we get NTLM2 working. + */ + + if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_128) { + ; + } else if (ntlmssp_state->neg_flags & NTLMSSP_NEGOTIATE_56) { + weak_session_key.length = 6; + } else { /* forty bits */ + weak_session_key.length = 5; } - - DEBUG(5, ("NTLMSSP Sign/Seal - using NT KEY\n")); + dump_data_pw("NTLMSSP weakend master key:\n", + weak_session_key.data, + weak_session_key.length); +#endif - calc_hash(ntlmssp_state->ntlmssp_hash, ntlmssp_state->session_key.data, 16); - dump_data_pw("NTLMSSP hash:\n", ntlmssp_state->ntlmssp_hash, - sizeof(ntlmssp_state->ntlmssp_hash)); - } + DEBUG(5, ("NTLMSSP Sign/Seal - using NTLM1\n")); + + smb_arc4_init(ntlmssp_state->ntlmv1_arc4_state, + ntlmssp_state->session_key.data, ntlmssp_state->session_key.length); - ntlmssp_state->ntlmssp_seq_num = 0; + dump_data_pw("NTLMv1 arc4 state:\n", ntlmssp_state->ntlmv1_arc4_state, + sizeof(ntlmssp_state->ntlmv1_arc4_state)); + + ntlmssp_state->ntlmv1_seq_num = 0; + } return NT_STATUS_OK; } diff --git a/source3/libsmb/passchange.c b/source3/libsmb/passchange.c index 8bce9c86a1e..b104a4678d9 100644 --- a/source3/libsmb/passchange.c +++ b/source3/libsmb/passchange.c @@ -21,16 +21,17 @@ #include "includes.h" /************************************************************* -change a password on a remote machine using IPC calls + Change a password on a remote machine using IPC calls. *************************************************************/ + BOOL 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) { struct nmb_name calling, called; struct cli_state cli; + struct rpc_pipe_client *pipe_hnd; struct in_addr ip; - struct ntuser_creds creds; NTSTATUS result; @@ -85,11 +86,9 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name, return False; } - init_creds(&creds, "", "", NULL); - cli_init_creds(&cli, &creds); + cli_init_creds(&cli, "", "", NULL); } else { - init_creds(&creds, user_name, "", old_passwd); - cli_init_creds(&cli, &creds); + cli_init_creds(&cli, user_name, "", old_passwd); } if (!cli_send_tconX(&cli, "IPC$", "IPC", "", 1)) { @@ -99,14 +98,19 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name, return False; } - /* Try not to give the password away to easily */ + /* Try not to give the password away too easily */ - cli.pipe_auth_flags = AUTH_PIPE_NTLMSSP; - cli.pipe_auth_flags |= AUTH_PIPE_SIGN; - cli.pipe_auth_flags |= AUTH_PIPE_SEAL; - - if ( !cli_nt_session_open( &cli, PI_SAMR ) ) { + pipe_hnd = cli_rpc_pipe_open_ntlmssp(&cli, + PI_SAMR, + PIPE_AUTH_LEVEL_PRIVACY, + "", /* what domain... ? */ + user_name, + old_passwd, + &result); + + if (!pipe_hnd) { if (lp_client_lanman_auth()) { + /* Use the old RAP method. */ 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) ); @@ -114,14 +118,16 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name, return False; } } else { - slprintf(err_str, err_str_len-1, "machine %s does not support SAMR connections, but LANMAN password changed are disabled\n", - remote_machine); + 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; } } - if (NT_STATUS_IS_OK(result = cli_samr_chgpasswd_user(&cli, cli.mem_ctx, user_name, + if (NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user(pipe_hnd, cli.mem_ctx, user_name, new_passwd, old_passwd))) { /* Great - it all worked! */ cli_shutdown(&cli); @@ -138,25 +144,25 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name, } /* OK, that failed, so try again... */ - cli_nt_session_close(&cli); + cli_rpc_pipe_close(pipe_hnd); /* Try anonymous NTLMSSP... */ - init_creds(&creds, "", "", NULL); - cli_init_creds(&cli, &creds); + cli_init_creds(&cli, "", "", NULL); - cli.pipe_auth_flags = 0; - result = NT_STATUS_UNSUCCESSFUL; - /* OK, this is ugly, but... */ - if ( cli_nt_session_open( &cli, PI_SAMR ) - && NT_STATUS_IS_OK(result - = cli_samr_chgpasswd_user(&cli, cli.mem_ctx, user_name, - new_passwd, old_passwd))) { + /* OK, this is ugly, but... try an anonymous pipe. */ + pipe_hnd = cli_rpc_pipe_open_noauth(&cli, PI_SAMR, &result); + + if ( pipe_hnd && + (NT_STATUS_IS_OK(result = rpccli_samr_chgpasswd_user(pipe_hnd, + cli.mem_ctx, + user_name, + new_passwd, + old_passwd)))) { /* Great - it all worked! */ cli_shutdown(&cli); return True; - } else { if (!(NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) || NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) { @@ -173,6 +179,7 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name, just might not support SAMR password changes, so fall back */ if (lp_client_lanman_auth()) { + /* Use the old RAP method. */ if (cli_oem_change_password(&cli, user_name, new_passwd, old_passwd)) { /* SAMR failed, but the old LanMan protocol worked! */ @@ -185,9 +192,10 @@ BOOL remote_password_change(const char *remote_machine, const char *user_name, cli_shutdown(&cli); return False; } else { - slprintf(err_str, err_str_len-1, - "machine %s does not support SAMR connections, but LANMAN password changed are disabled\n", - remote_machine); + 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; } diff --git a/source3/libsmb/pwd_cache.c b/source3/libsmb/pwd_cache.c index e010f226a02..a0f3383e297 100644 --- a/source3/libsmb/pwd_cache.c +++ b/source3/libsmb/pwd_cache.c @@ -60,4 +60,3 @@ void pwd_get_cleartext(struct pwd_info *pwd, fstring clr) clr[0] = 0; } - diff --git a/source3/libsmb/smb_share_modes.c b/source3/libsmb/smb_share_modes.c index 87a386307c1..7659d1cd6e8 100644 --- a/source3/libsmb/smb_share_modes.c +++ b/source3/libsmb/smb_share_modes.c @@ -55,6 +55,12 @@ struct smbdb_ctx *smb_share_mode_db_open(const char *db_path) return smb_db; } +/* key and data records in the tdb locking database */ +struct locking_key { + SMB_DEV_T dev; + SMB_INO_T inode; +}; + int smb_share_mode_db_close(struct smbdb_ctx *db_ctx) { int ret = tdb_close(db_ctx->smb_tdb); @@ -102,10 +108,10 @@ struct locking_data { int num_share_mode_entries; BOOL delete_on_close; } s; - share_mode_entry dummy; /* Needed for alignment. */ + struct share_mode_entry dummy; /* Needed for alignment. */ } u; /* the following two entries are implicit - share_mode_entry modes[num_share_mode_entries]; + struct share_mode_entry modes[num_share_mode_entries]; char file_name[]; */ }; @@ -114,9 +120,9 @@ struct locking_data { * Check if an external smb_share_mode_entry and an internal share_mode entry match. */ -static int share_mode_entry_equal(const struct smb_share_mode_entry *e_entry, const share_mode_entry *entry) +static int share_mode_entry_equal(const struct smb_share_mode_entry *e_entry, const struct share_mode_entry *entry) { - return (e_entry->pid == entry->pid && + return (procid_equal(&e_entry->pid, &entry->pid) && e_entry->file_id == (uint32_t)entry->share_file_id && e_entry->open_time.tv_sec == entry->time.tv_sec && e_entry->open_time.tv_usec == entry->time.tv_usec && @@ -130,9 +136,9 @@ static int share_mode_entry_equal(const struct smb_share_mode_entry *e_entry, co * Create an internal Samba share_mode entry from an external smb_share_mode_entry. */ -static void create_share_mode_entry(share_mode_entry *out, const struct smb_share_mode_entry *in) +static void create_share_mode_entry(struct share_mode_entry *out, const struct smb_share_mode_entry *in) { - memset(out, '\0', sizeof(share_mode_entry)); + memset(out, '\0', sizeof(struct share_mode_entry)); out->pid = in->pid; out->share_file_id = (unsigned long)in->file_id; @@ -159,7 +165,7 @@ int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx, struct smb_share_mode_entry *list = NULL; int num_share_modes = 0; struct locking_data *ld = NULL; /* internal samba db state. */ - share_mode_entry *shares = NULL; + struct share_mode_entry *shares = NULL; size_t i; int list_num; @@ -187,19 +193,24 @@ int smb_get_share_mode_entries(struct smbdb_ctx *db_ctx, memset(list, '\0', num_share_modes * sizeof(struct smb_share_mode_entry)); - shares = (share_mode_entry *)(db_data.dptr + sizeof(share_mode_entry)); + shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct share_mode_entry)); list_num = 0; for (i = 0; i < num_share_modes; i++) { - share_mode_entry *share = &shares[i]; + struct share_mode_entry *share = &shares[i]; struct smb_share_mode_entry *sme = &list[list_num]; - pid_t pid = share->pid; + struct process_id pid = share->pid; /* Check this process really exists. */ - if (kill(pid, 0) == -1 && (errno == ESRCH)) { + if (kill(procid_to_pid(&pid), 0) == -1 && (errno == ESRCH)) { continue; /* No longer exists. */ } + /* Ignore deferred open entries. */ + if (share->op_type == DEFERRED_OPEN_ENTRY) { + continue; + } + /* Copy into the external list. */ sme->dev = (uint64_t)share->dev; sme->ino = (uint64_t)share->inode; @@ -238,27 +249,27 @@ int smb_create_share_mode_entry(struct smbdb_ctx *db_ctx, TDB_DATA locking_key = get_locking_key(dev, ino); int orig_num_share_modes = 0; struct locking_data *ld = NULL; /* internal samba db state. */ - share_mode_entry *shares = NULL; + struct share_mode_entry *shares = NULL; char *new_data_p = NULL; size_t new_data_size = 0; db_data = tdb_fetch(db_ctx->smb_tdb, locking_key); if (!db_data.dptr) { /* We must create the entry. */ - db_data.dptr = malloc((2*sizeof(share_mode_entry)) + strlen(filename) + 1); + db_data.dptr = malloc((2*sizeof(struct share_mode_entry)) + strlen(filename) + 1); if (!db_data.dptr) { return -1; } ld = (struct locking_data *)db_data.dptr; ld->u.s.num_share_mode_entries = 1; ld->u.s.delete_on_close = 0; - shares = (share_mode_entry *)(db_data.dptr + sizeof(share_mode_entry)); + shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct share_mode_entry)); create_share_mode_entry(shares, new_entry); - memcpy(db_data.dptr + 2*sizeof(share_mode_entry), + memcpy(db_data.dptr + 2*sizeof(struct share_mode_entry), filename, strlen(filename) + 1); - db_data.dsize = 2*sizeof(share_mode_entry) + strlen(filename) + 1; + db_data.dsize = 2*sizeof(struct share_mode_entry) + strlen(filename) + 1; if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_INSERT) == -1) { free(db_data.dptr); return -1; @@ -268,7 +279,7 @@ int smb_create_share_mode_entry(struct smbdb_ctx *db_ctx, } /* Entry exists, we must add a new entry. */ - new_data_p = malloc(db_data.dsize + sizeof(share_mode_entry)); + new_data_p = malloc(db_data.dsize + sizeof(struct share_mode_entry)); if (!new_data_p) { free(db_data.dptr); return -1; @@ -278,11 +289,11 @@ int smb_create_share_mode_entry(struct smbdb_ctx *db_ctx, orig_num_share_modes = ld->u.s.num_share_mode_entries; /* Copy the original data. */ - memcpy(new_data_p, db_data.dptr, (orig_num_share_modes+1)*sizeof(share_mode_entry)); + memcpy(new_data_p, db_data.dptr, (orig_num_share_modes+1)*sizeof(struct share_mode_entry)); /* Add in the new share mode */ - shares = (share_mode_entry *)(new_data_p + - ((orig_num_share_modes+1)*sizeof(share_mode_entry))); + shares = (struct share_mode_entry *)(new_data_p + + ((orig_num_share_modes+1)*sizeof(struct share_mode_entry))); create_share_mode_entry(shares, new_entry); @@ -290,11 +301,11 @@ int smb_create_share_mode_entry(struct smbdb_ctx *db_ctx, ld->u.s.num_share_mode_entries++; /* Append the original filename */ - memcpy(new_data_p + ((ld->u.s.num_share_mode_entries+1)*sizeof(share_mode_entry)), - db_data.dptr + ((orig_num_share_modes+1)*sizeof(share_mode_entry)), - db_data.dsize - ((orig_num_share_modes+1) * sizeof(share_mode_entry))); + memcpy(new_data_p + ((ld->u.s.num_share_mode_entries+1)*sizeof(struct share_mode_entry)), + db_data.dptr + ((orig_num_share_modes+1)*sizeof(struct share_mode_entry)), + db_data.dsize - ((orig_num_share_modes+1) * sizeof(struct share_mode_entry))); - new_data_size = db_data.dsize + sizeof(share_mode_entry); + new_data_size = db_data.dsize + sizeof(struct share_mode_entry); free(db_data.dptr); @@ -318,7 +329,7 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx, TDB_DATA locking_key = get_locking_key(dev, ino); int orig_num_share_modes = 0; struct locking_data *ld = NULL; /* internal samba db state. */ - share_mode_entry *shares = NULL; + struct share_mode_entry *shares = NULL; char *new_data_p = NULL; size_t filename_size = 0; size_t i, num_share_modes; @@ -331,7 +342,7 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx, ld = (struct locking_data *)db_data.dptr; orig_num_share_modes = ld->u.s.num_share_mode_entries; - shares = (share_mode_entry *)(db_data.dptr + sizeof(share_mode_entry)); + shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct share_mode_entry)); if (orig_num_share_modes == 1) { /* Only one entry - better be ours... */ @@ -346,22 +357,22 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx, } /* More than one - allocate a new record minus the one we'll delete. */ - new_data_p = malloc(db_data.dsize - sizeof(share_mode_entry)); + new_data_p = malloc(db_data.dsize - sizeof(struct share_mode_entry)); if (!new_data_p) { free(db_data.dptr); return -1; } /* Copy the header. */ - memcpy(new_data_p, db_data.dptr, sizeof(share_mode_entry)); + memcpy(new_data_p, db_data.dptr, sizeof(struct share_mode_entry)); num_share_modes = 0; for (i = 0; i < orig_num_share_modes; i++) { - share_mode_entry *share = &shares[i]; - pid_t pid = share->pid; + struct share_mode_entry *share = &shares[i]; + struct process_id pid = share->pid; /* Check this process really exists. */ - if (kill(pid, 0) == -1 && (errno == ESRCH)) { + if (kill(procid_to_pid(&pid), 0) == -1 && (errno == ESRCH)) { continue; /* No longer exists. */ } @@ -369,8 +380,8 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx, continue; /* This is our delete taget. */ } - memcpy(new_data_p + ((num_share_modes+1)*sizeof(share_mode_entry)), - share, sizeof(share_mode_entry) ); + memcpy(new_data_p + ((num_share_modes+1)*sizeof(struct share_mode_entry)), + share, sizeof(struct share_mode_entry) ); num_share_modes++; } @@ -383,10 +394,10 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx, } /* Copy the terminating filename. */ - fname_ptr = db_data.dptr + ((orig_num_share_modes+1) * sizeof(share_mode_entry)); + fname_ptr = db_data.dptr + ((orig_num_share_modes+1) * sizeof(struct share_mode_entry)); filename_size = db_data.dsize - (fname_ptr - db_data.dptr); - memcpy(new_data_p + ((num_share_modes+1)*sizeof(share_mode_entry)), + memcpy(new_data_p + ((num_share_modes+1)*sizeof(struct share_mode_entry)), fname_ptr, filename_size); @@ -398,7 +409,7 @@ int smb_delete_share_mode_entry(struct smbdb_ctx *db_ctx, ld = (struct locking_data *)db_data.dptr; ld->u.s.num_share_mode_entries = num_share_modes; - db_data.dsize = ((num_share_modes+1)*sizeof(share_mode_entry)) + filename_size; + db_data.dsize = ((num_share_modes+1)*sizeof(struct share_mode_entry)) + filename_size; if (tdb_store(db_ctx->smb_tdb, locking_key, db_data, TDB_REPLACE) == -1) { free(db_data.dptr); @@ -418,7 +429,7 @@ int smb_change_share_mode_entry(struct smbdb_ctx *db_ctx, TDB_DATA locking_key = get_locking_key(dev, ino); int num_share_modes = 0; struct locking_data *ld = NULL; /* internal samba db state. */ - share_mode_entry *shares = NULL; + struct share_mode_entry *shares = NULL; size_t i; int found_entry = 0; @@ -429,14 +440,14 @@ int smb_change_share_mode_entry(struct smbdb_ctx *db_ctx, ld = (struct locking_data *)db_data.dptr; num_share_modes = ld->u.s.num_share_mode_entries; - shares = (share_mode_entry *)(db_data.dptr + sizeof(share_mode_entry)); + shares = (struct share_mode_entry *)(db_data.dptr + sizeof(struct share_mode_entry)); for (i = 0; i < num_share_modes; i++) { - share_mode_entry *share = &shares[i]; - pid_t pid = share->pid; + struct share_mode_entry *share = &shares[i]; + struct process_id pid = share->pid; /* Check this process really exists. */ - if (kill(pid, 0) == -1 && (errno == ESRCH)) { + if (kill(procid_to_pid(&pid), 0) == -1 && (errno == ESRCH)) { continue; /* No longer exists. */ } diff --git a/source3/libsmb/smbdes.c b/source3/libsmb/smbdes.c index b7f0cd05c33..dc49396d9e1 100644 --- a/source3/libsmb/smbdes.c +++ b/source3/libsmb/smbdes.c @@ -357,78 +357,24 @@ void cred_hash3(unsigned char *out, unsigned char *in, const unsigned char *key, des_crypt56(out + 8, in + 8, key2, forw); } -void SamOEMhash( unsigned char *data, const unsigned char *key, int val) -{ - unsigned char s_box[256]; - unsigned char index_i = 0; - unsigned char index_j = 0; - unsigned char j = 0; - int ind; - - for (ind = 0; ind < 256; ind++) { - s_box[ind] = (unsigned char)ind; - } - - for( ind = 0; ind < 256; ind++) { - unsigned char tc; +/***************************************************************** + arc4 crypt/decrypt with a 16 byte key. +*****************************************************************/ - j += (s_box[ind] + key[ind%16]); - - tc = s_box[ind]; - s_box[ind] = s_box[j]; - s_box[j] = tc; - } - for( ind = 0; ind < val; ind++) { - unsigned char tc; - unsigned char t; - - index_i++; - index_j += s_box[index_i]; - - tc = s_box[index_i]; - s_box[index_i] = s_box[index_j]; - s_box[index_j] = tc; +void SamOEMhash( unsigned char *data, const unsigned char key[16], size_t len) +{ + unsigned char arc4_state[258]; - t = s_box[index_i] + s_box[index_j]; - data[ind] = data[ind] ^ s_box[t]; - } + smb_arc4_init(arc4_state, key, 16); + smb_arc4_crypt(arc4_state, data, len); } -void SamOEMhashBlob( unsigned char *data, int len, DATA_BLOB *key) +void SamOEMhashBlob( unsigned char *data, size_t len, DATA_BLOB *key) { - unsigned char s_box[256]; - unsigned char index_i = 0; - unsigned char index_j = 0; - unsigned char j = 0; - int ind; - - for (ind = 0; ind < 256; ind++) { - s_box[ind] = (unsigned char)ind; - } - - for( ind = 0; ind < 256; ind++) { - unsigned char tc; - - j += (s_box[ind] + key->data[ind%key->length]); - - tc = s_box[ind]; - s_box[ind] = s_box[j]; - s_box[j] = tc; - } - for( ind = 0; ind < len; ind++) { - unsigned char tc; - unsigned char t; - - index_i++; - index_j += s_box[index_i]; + unsigned char arc4_state[258]; - tc = s_box[index_i]; - s_box[index_i] = s_box[index_j]; - s_box[index_j] = tc; - - t = s_box[index_i] + s_box[index_j]; - data[ind] = data[ind] ^ s_box[t]; - } + smb_arc4_init(arc4_state, key->data, key->length); + smb_arc4_crypt(arc4_state, data, len); } /* Decode a sam password hash into a password. The password hash is the diff --git a/source3/libsmb/smbencrypt.c b/source3/libsmb/smbencrypt.c index 8361c35a8e2..0c9eacfe4c0 100644 --- a/source3/libsmb/smbencrypt.c +++ b/source3/libsmb/smbencrypt.c @@ -308,32 +308,6 @@ void SMBsesskeygen_ntv1(const uchar kr[16], #endif } -void SMBsesskeygen_lmv1(const uchar lm_hash[16], - const uchar lm_resp[24], /* only uses 8 */ - uint8 sess_key[16]) -{ - /* Calculate the LM session key (effective length 40 bits, - but changes with each session) */ - - uchar p24[24]; - uchar partial_lm_hash[16]; - - memcpy(partial_lm_hash, lm_hash, 8); - memset(partial_lm_hash + 8, 0xbd, 8); - - SMBOWFencrypt(lm_hash, lm_resp, p24); - - memcpy(sess_key, p24, 16); - sess_key[5] = 0xe5; - sess_key[6] = 0x38; - sess_key[7] = 0xb0; - -#ifdef DEBUG_PASSWORD - DEBUG(100, ("SMBsesskeygen_lmv1:\n")); - dump_data(100, sess_key, 16); -#endif -} - void SMBsesskeygen_lm_sess_key(const uchar lm_hash[16], const uchar lm_resp[24], /* only uses 8 */ uint8 sess_key[16]) @@ -485,7 +459,7 @@ BOOL SMBNTLMv2encrypt(const char *user, const char *domain, const char *password encode a password buffer with a unicode password. The buffer is filled with random data to make it harder to attack. ************************************************************/ -BOOL encode_pw_buffer(char buffer[516], const char *password, int string_flags) +BOOL encode_pw_buffer(uint8 buffer[516], const char *password, int string_flags) { uchar new_pw[512]; size_t new_pw_len; @@ -496,7 +470,7 @@ BOOL encode_pw_buffer(char buffer[516], const char *password, int string_flags) memcpy(&buffer[512 - new_pw_len], new_pw, new_pw_len); - generate_random_buffer((unsigned char *)buffer, 512 - new_pw_len); + generate_random_buffer(buffer, 512 - new_pw_len); /* * The length of the new password is in the last 4 bytes of diff --git a/source3/libsmb/smberr.c b/source3/libsmb/smberr.c index a21063e52ac..82a06bde2bc 100644 --- a/source3/libsmb/smberr.c +++ b/source3/libsmb/smberr.c @@ -75,6 +75,7 @@ err_code_struct dos_msgs[] = { {"ERRlogonfailure",ERRlogonfailure,"Logon failure"}, {"ERRdiskfull",ERRdiskfull,"Disk full"}, {"ERRgeneral",ERRgeneral, "General failure"}, + {"ERRbaddirectory", ERRbaddirectory, "Bad directory name"}, {"ERRunknownlevel",ERRunknownlevel, "Unknown info level"}, {NULL,-1,NULL}}; diff --git a/source3/libsmb/spnego.c b/source3/libsmb/spnego.c index 2eaec61ed79..2cf3480fce3 100644 --- a/source3/libsmb/spnego.c +++ b/source3/libsmb/spnego.c @@ -42,11 +42,11 @@ static BOOL read_negTokenInit(ASN1_DATA *asn1, negTokenInit_t *token) asn1_start_tag(asn1, ASN1_CONTEXT(0)); asn1_start_tag(asn1, ASN1_SEQUENCE(0)); - token->mechTypes = SMB_MALLOC_P(char *); + token->mechTypes = SMB_MALLOC_P(const char *); for (i = 0; !asn1->has_error && 0 < asn1_tag_remaining(asn1); i++) { token->mechTypes = - SMB_REALLOC_ARRAY(token->mechTypes, char *, i + 2); + SMB_REALLOC_ARRAY(token->mechTypes, const char *, i + 2); asn1_read_OID(asn1, &token->mechTypes[i]); } token->mechTypes[i] = NULL; diff --git a/source3/libsmb/trusts_util.c b/source3/libsmb/trusts_util.c index aab0d7d1517..50fa613e72c 100644 --- a/source3/libsmb/trusts_util.c +++ b/source3/libsmb/trusts_util.c @@ -29,22 +29,36 @@ Caller must have the cli connected to the netlogon pipe already. **********************************************************/ -static NTSTATUS just_change_the_password(struct cli_state *cli, TALLOC_CTX *mem_ctx, + +static NTSTATUS just_change_the_password(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, unsigned char orig_trust_passwd_hash[16], unsigned char new_trust_passwd_hash[16], uint32 sec_channel_type) { NTSTATUS result; - /* ensure that schannel uses the right domain */ - fstrcpy(cli->domain, lp_workgroup()); - if (! NT_STATUS_IS_OK(result = cli_nt_establish_netlogon(cli, sec_channel_type, orig_trust_passwd_hash))) { - DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n", - nt_errstr(result))); - return result; + /* Check if the netlogon pipe is open using schannel. If so we + already have valid creds. If not we must set them up. */ + + if (cli->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) { + uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + + result = rpccli_netlogon_setup_creds(cli, + cli->cli->desthost, + lp_workgroup(), + global_myname(), + orig_trust_passwd_hash, + sec_channel_type, + &neg_flags); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(3,("just_change_the_password: unable to setup creds (%s)!\n", + nt_errstr(result))); + return result; + } } - - result = cli_net_srv_pwset(cli, mem_ctx, global_myname(), new_trust_passwd_hash); + + result = rpccli_net_srv_pwset(cli, mem_ctx, global_myname(), new_trust_passwd_hash); if (!NT_STATUS_IS_OK(result)) { DEBUG(0,("just_change_the_password: unable to change password (%s)!\n", @@ -59,7 +73,7 @@ static NTSTATUS just_change_the_password(struct cli_state *cli, TALLOC_CTX *mem_ Caller must have already setup the connection to the NETLOGON pipe **********************************************************/ -NTSTATUS trust_pw_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS trust_pw_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *domain, unsigned char orig_trust_passwd_hash[16], uint32 sec_channel_type) @@ -99,7 +113,7 @@ NTSTATUS trust_pw_change_and_store_it(struct cli_state *cli, TALLOC_CTX *mem_ctx already setup the connection to the NETLOGON pipe **********************************************************/ -NTSTATUS trust_pw_find_change_and_store_it(struct cli_state *cli, +NTSTATUS trust_pw_find_change_and_store_it(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *domain) { @@ -116,7 +130,6 @@ NTSTATUS trust_pw_find_change_and_store_it(struct cli_state *cli, return trust_pw_change_and_store_it(cli, mem_ctx, domain, old_trust_passwd_hash, sec_channel_type); - } /********************************************************************* @@ -133,6 +146,7 @@ BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain, struct in_addr dc_ip; uint32 enum_ctx = 0; struct cli_state *cli = NULL; + struct rpc_pipe_client *lsa_pipe; BOOL retry; *domain_names = NULL; @@ -156,21 +170,21 @@ BOOL enumerate_domain_trusts( TALLOC_CTX *mem_ctx, const char *domain, /* open the LSARPC_PIPE */ - if ( !cli_nt_session_open( cli, PI_LSARPC ) ) { - result = NT_STATUS_UNSUCCESSFUL; + lsa_pipe = cli_rpc_pipe_open_noauth( cli, PI_LSARPC, &result ); + if ( !lsa_pipe) { goto done; } /* get a handle */ - result = cli_lsa_open_policy(cli, mem_ctx, True, + result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True, POLICY_VIEW_LOCAL_INFORMATION, &pol); if ( !NT_STATUS_IS_OK(result) ) goto done; /* Lookup list of trusted domains */ - result = cli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx, + result = rpccli_lsa_enum_trust_dom(lsa_pipe, mem_ctx, &pol, &enum_ctx, num_domains, domain_names, sids); if ( !NT_STATUS_IS_OK(result) ) goto done; @@ -184,4 +198,3 @@ done: return NT_STATUS_IS_OK(result); } - diff --git a/source3/locking/brlock.c b/source3/locking/brlock.c index da7fc1e67d4..25a1ed5e2f6 100644 --- a/source3/locking/brlock.c +++ b/source3/locking/brlock.c @@ -39,7 +39,7 @@ struct lock_context { uint16 smbpid; uint16 tid; - pid_t pid; + struct process_id pid; }; /* The data in brlock records is an unsorted linear array of these @@ -89,9 +89,9 @@ static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) static BOOL brl_same_context(struct lock_context *ctx1, struct lock_context *ctx2) { - return (ctx1->pid == ctx2->pid) && + return (procid_equal(&ctx1->pid, &ctx2->pid) && (ctx1->smbpid == ctx2->smbpid) && - (ctx1->tid == ctx2->tid); + (ctx1->tid == ctx2->tid)); } /**************************************************************************** @@ -252,7 +252,7 @@ static int delete_fn(TDB_CONTEXT *ttdb, TDB_DATA kbuf, TDB_DATA dbuf, void *stat DEBUG(0,("brlock : delete_fn. LOGIC ERROR ! Shutting down and a record for my pid (%u) exists !\n", (unsigned int)lock->context.pid )); - } else if (process_exists(lock->context.pid)) { + } else if (process_exists(&lock->context.pid)) { DEBUG(10,("brlock : delete_fn. pid %u exists.\n", (unsigned int)lock->context.pid )); continue; @@ -347,7 +347,7 @@ static int lock_compare(struct lock_struct *lck1, ****************************************************************************/ NTSTATUS brl_lock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, - uint16 smbpid, pid_t pid, uint16 tid, + uint16 smbpid, struct process_id pid, uint16 tid, br_off start, br_off size, enum brl_type lock_type, BOOL *my_lock_ctx) { @@ -450,7 +450,7 @@ static BOOL brl_pending_overlap(struct lock_struct *lock, struct lock_struct *pe ****************************************************************************/ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, - uint16 smbpid, pid_t pid, uint16 tid, + uint16 smbpid, struct process_id pid, uint16 tid, br_off start, br_off size, BOOL remove_pending_locks_only, void (*pre_unlock_fn)(void *), @@ -542,8 +542,8 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, /* We could send specific lock info here... */ if (brl_pending_overlap(lock, pend_lock)) { - DEBUG(10,("brl_unlock: sending unlock message to pid %u\n", - (unsigned int)pend_lock->context.pid )); + DEBUG(10,("brl_unlock: sending unlock message to pid %s\n", + procid_str_static(&pend_lock->context.pid ))); message_send_pid(pend_lock->context.pid, MSG_SMB_UNLOCK, @@ -584,7 +584,7 @@ BOOL brl_unlock(SMB_DEV_T dev, SMB_INO_T ino, int fnum, ****************************************************************************/ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum, - uint16 smbpid, pid_t pid, uint16 tid, + uint16 smbpid, struct process_id pid, uint16 tid, br_off start, br_off size, enum brl_type lock_type) { @@ -632,7 +632,7 @@ BOOL brl_locktest(SMB_DEV_T dev, SMB_INO_T ino, int fnum, Remove any locks associated with a open file. ****************************************************************************/ -void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) +void brl_close(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, int tid, int fnum) { TDB_DATA kbuf, dbuf; int count, i, j, dcount=0; @@ -655,7 +655,7 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) struct lock_struct *lock = &locks[i]; if (lock->context.tid == tid && - lock->context.pid == pid && + procid_equal(&lock->context.pid, &pid) && lock->fnum == fnum) { /* Send unlock messages to any pending waiters that overlap. */ @@ -667,7 +667,7 @@ void brl_close(SMB_DEV_T dev, SMB_INO_T ino, pid_t pid, int tid, int fnum) continue; if (pend_lock->context.tid == tid && - pend_lock->context.pid == pid && + procid_equal(&pend_lock->context.pid, &pid) && pend_lock->fnum == fnum) continue; diff --git a/source3/locking/locking.c b/source3/locking/locking.c index 5bcf7f2eda8..e3131e26a2a 100644 --- a/source3/locking/locking.c +++ b/source3/locking/locking.c @@ -43,7 +43,6 @@ uint16 global_smbpid; /* the locking database handle */ static TDB_CONTEXT *tdb; -static TDB_CONTEXT *deferred_open_tdb; struct locking_data { union { @@ -51,10 +50,10 @@ struct locking_data { int num_share_mode_entries; BOOL delete_on_close; } s; - share_mode_entry dummy; /* Needed for alignment. */ + struct share_mode_entry dummy; /* Needed for alignment. */ } u; /* the following two entries are implicit - share_mode_entry modes[num_share_mode_entries]; + struct share_mode_entry modes[num_share_mode_entries]; char file_name[]; */ }; @@ -90,17 +89,18 @@ BOOL is_locked(files_struct *fsp,connection_struct *conn, if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK || lock_type == WRITE_LOCK)) { DEBUG(10,("is_locked: optimisation - exclusive oplock on file %s\n", fsp->fsp_name )); ret = 0; - } else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type) && (lock_type == READ_LOCK)) { + } else if ((fsp->oplock_type == LEVEL_II_OPLOCK) && + (lock_type == READ_LOCK)) { DEBUG(10,("is_locked: optimisation - level II oplock on file %s\n", fsp->fsp_name )); ret = 0; } else { ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, sys_getpid(), conn->cnum, + global_smbpid, procid_self(), conn->cnum, offset, count, lock_type); } } else { ret = !brl_locktest(fsp->dev, fsp->inode, fsp->fnum, - global_smbpid, sys_getpid(), conn->cnum, + global_smbpid, procid_self(), conn->cnum, offset, count, lock_type); } @@ -143,7 +143,7 @@ static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_p if (OPEN_FSP(fsp) && fsp->can_lock && (fsp->conn == conn)) { status = brl_lock(fsp->dev, fsp->inode, fsp->fnum, - lock_pid, sys_getpid(), conn->cnum, + lock_pid, procid_self(), conn->cnum, offset, count, lock_type, my_lock_ctx); @@ -166,7 +166,7 @@ static NTSTATUS do_lock(files_struct *fsp,connection_struct *conn, uint16 lock_p * lock entry. */ (void)brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - lock_pid, sys_getpid(), conn->cnum, + lock_pid, procid_self(), conn->cnum, offset, count, False, NULL, NULL); } @@ -264,7 +264,7 @@ NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, posix_data.count = count; ok = brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - lock_pid, sys_getpid(), conn->cnum, offset, count, + lock_pid, procid_self(), conn->cnum, offset, count, False, posix_unlock, (void *)&posix_data); if (!ok) { @@ -280,7 +280,7 @@ NTSTATUS do_unlock(files_struct *fsp,connection_struct *conn, uint16 lock_pid, void locking_close_file(files_struct *fsp) { - pid_t pid = sys_getpid(); + struct process_id pid = procid_self(); if (!lp_locking(SNUM(fsp->conn))) return; @@ -324,20 +324,6 @@ BOOL locking_init(int read_only) return False; } - if (!read_only && !deferred_open_tdb) { - deferred_open_tdb = tdb_open_log(lock_path("deferred_open.tdb"), - 0, TDB_DEFAULT|TDB_CLEAR_IF_FIRST, - O_RDWR|O_CREAT, - 0644); - - if (!deferred_open_tdb) { - DEBUG(0,("ERROR: Failed to initialise deferred open database\n")); - tdb_close(tdb); - tdb = NULL; - return False; - } - } - if (!posix_locking_init(read_only)) return False; @@ -360,11 +346,6 @@ BOOL locking_end(void) ret = False; } - if (deferred_open_tdb) { - if (tdb_close(deferred_open_tdb) != 0) - ret = False; - } - return ret; } @@ -372,6 +353,16 @@ BOOL locking_end(void) Form a static locking key for a dev/inode pair. ******************************************************************/ +/* key and data records in the tdb locking database */ +struct locking_key { + SMB_DEV_T dev; + SMB_INO_T ino; +}; + +/******************************************************************* + Form a static locking key for a dev/inode pair. +******************************************************************/ + static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) { static struct locking_key key; @@ -379,70 +370,27 @@ static TDB_DATA locking_key(SMB_DEV_T dev, SMB_INO_T inode) memset(&key, '\0', sizeof(key)); key.dev = dev; - key.inode = inode; + key.ino = inode; kbuf.dptr = (char *)&key; kbuf.dsize = sizeof(key); return kbuf; } -static TDB_DATA locking_key_fsp(files_struct *fsp) -{ - return locking_key(fsp->dev, fsp->inode); -} - -/******************************************************************* - Lock a hash bucket entry. -******************************************************************/ - -BOOL lock_share_entry(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode) -{ - return tdb_chainlock(tdb, locking_key(dev, inode)) == 0; -} - -/******************************************************************* - Unlock a hash bucket entry. -******************************************************************/ - -void unlock_share_entry(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode) -{ - tdb_chainunlock(tdb, locking_key(dev, inode)); -} - -/******************************************************************* - Lock a hash bucket entry. use a fsp for convenience -******************************************************************/ - -BOOL lock_share_entry_fsp(files_struct *fsp) -{ - return tdb_chainlock(tdb, locking_key(fsp->dev, fsp->inode)) == 0; -} - -/******************************************************************* - Unlock a hash bucket entry. -******************************************************************/ - -void unlock_share_entry_fsp(files_struct *fsp) -{ - tdb_chainunlock(tdb, locking_key(fsp->dev, fsp->inode)); -} - /******************************************************************* Print out a share mode. ********************************************************************/ -char *share_mode_str(int num, share_mode_entry *e) +char *share_mode_str(int num, struct share_mode_entry *e) { static pstring share_str; slprintf(share_str, sizeof(share_str)-1, "share_mode_entry[%d]: " - "pid = %lu, share_access = 0x%x, private_options = 0x%x, " - "access_mask = 0x%x, port = 0x%x, type= 0x%x, file_id = %lu, " + "pid = %s, share_access = 0x%x, private_options = 0x%x, " + "access_mask = 0x%x, mid = 0x%x, type= 0x%x, file_id = %lu, " "dev = 0x%x, inode = %.0f", - num, (unsigned long)e->pid, + num, procid_str_static(&e->pid), e->share_access, e->private_options, - e->access_mask, e->op_port, e->op_type, e->share_file_id, + e->access_mask, e->op_mid, e->op_type, e->share_file_id, (unsigned int)e->dev, (double)e->inode ); return share_str; @@ -455,12 +403,14 @@ char *share_mode_str(int num, share_mode_entry *e) static void print_share_mode_table(struct locking_data *data) { int num_share_modes = data->u.s.num_share_mode_entries; - share_mode_entry *shares = (share_mode_entry *)(data + 1); + struct share_mode_entry *shares = + (struct share_mode_entry *)(data + 1); int i; for (i = 0; i < num_share_modes; i++) { - share_mode_entry *entry_p = &shares[i]; - DEBUG(10,("print_share_mode_table: %s\n", share_mode_str(i, entry_p) )); + struct share_mode_entry *entry_p = &shares[i]; + DEBUG(10,("print_share_mode_table: %s\n", + share_mode_str(i, entry_p))); } } @@ -468,825 +418,581 @@ static void print_share_mode_table(struct locking_data *data) Get all share mode entries for a dev/inode pair. ********************************************************************/ -int get_share_modes(SMB_DEV_T dev, SMB_INO_T inode, - share_mode_entry **pp_shares, - BOOL *delete_on_close) +static BOOL parse_share_modes(TDB_DATA dbuf, struct share_mode_lock *lck) { - TDB_DATA dbuf; struct locking_data *data; - int num_share_modes; - share_mode_entry *shares = NULL; - TDB_DATA key = locking_key(dev, inode); - *pp_shares = NULL; - *delete_on_close = False; - - dbuf = tdb_fetch(tdb, key); - if (!dbuf.dptr) - return 0; - - data = (struct locking_data *)dbuf.dptr; + int i; - *delete_on_close = data->u.s.delete_on_close; - DEBUG(10, ("get_share_modes: delete_on_close: %d\n", - *delete_on_close)); - num_share_modes = data->u.s.num_share_mode_entries; - if(num_share_modes) { - pstring fname; - int i; - int del_count = 0; - - shares = (share_mode_entry *)memdup(dbuf.dptr + sizeof(*data), - num_share_modes * sizeof(share_mode_entry)); - - if (!shares) { - SAFE_FREE(dbuf.dptr); - return 0; - } + if (dbuf.dsize < sizeof(struct locking_data)) { + DEBUG(0, ("parse_share_modes: buffer too short\n")); + return False; + } - /* Save off the associated filename. */ - pstrcpy(fname, dbuf.dptr + sizeof(*data) + num_share_modes * sizeof(share_mode_entry)); + data = (struct locking_data *)dbuf.dptr; - /* - * Ensure that each entry has a real process attached. - */ + lck->delete_on_close = data->u.s.delete_on_close; + lck->num_share_modes = data->u.s.num_share_mode_entries; - for (i = 0; i < num_share_modes; ) { - share_mode_entry *entry_p = &shares[i]; - if (process_exists(entry_p->pid)) { - DEBUG(10,("get_share_modes: %s\n", share_mode_str(i, entry_p) )); - i++; - } else { - DEBUG(10,("get_share_modes: deleted %s\n", share_mode_str(i, entry_p) )); - if (num_share_modes - i - 1 > 0) { - memcpy( &shares[i], &shares[i+1], - sizeof(share_mode_entry) * (num_share_modes - i - 1)); - } - num_share_modes--; - del_count++; - } - } + DEBUG(10, ("parse_share_modes: delete_on_close: %d, " + "num_share_modes: %d\n", lck->delete_on_close, + lck->num_share_modes)); - /* Did we delete any ? If so, re-store in tdb. */ - if (del_count) { - data->u.s.num_share_mode_entries = num_share_modes; - - if (num_share_modes) { - memcpy(dbuf.dptr + sizeof(*data), shares, - num_share_modes * sizeof(share_mode_entry)); - /* Append the filename. */ - pstrcpy(dbuf.dptr + sizeof(*data) + num_share_modes * sizeof(share_mode_entry), fname); - } - - /* The record has shrunk a bit */ - dbuf.dsize -= del_count * sizeof(share_mode_entry); - - if (data->u.s.num_share_mode_entries == 0) { - if (tdb_delete(tdb, key) == -1) { - SAFE_FREE(shares); - SAFE_FREE(dbuf.dptr); - return 0; - } - } else { - if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) { - SAFE_FREE(shares); - SAFE_FREE(dbuf.dptr); - return 0; - } - } - } + if ((lck->num_share_modes < 0) || (lck->num_share_modes > 1000000)) { + DEBUG(0, ("invalid number of share modes: %d\n", + lck->num_share_modes)); + return False; } - SAFE_FREE(dbuf.dptr); - *pp_shares = shares; - return num_share_modes; -} + lck->share_modes = NULL; -BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode) -{ - share_mode_entry *shares; - BOOL result; - get_share_modes(dev, inode, &shares, &result); - SAFE_FREE(shares); - return result; -} + if (lck->num_share_modes != 0) { -/******************************************************************* - Fill a share mode entry. -********************************************************************/ + if (dbuf.dsize < (sizeof(struct locking_data) + + (lck->num_share_modes * + sizeof(struct share_mode_entry)))) { + DEBUG(0, ("parse_share_modes: buffer too short\n")); + return False; + } + + lck->share_modes = talloc_memdup(lck, dbuf.dptr+sizeof(*data), + lck->num_share_modes * + sizeof(struct share_mode_entry)); -static void fill_share_mode(char *p, files_struct *fsp, uint16 port, uint16 op_type) -{ - share_mode_entry *e = (share_mode_entry *)p; - void *x = &e->time; /* Needed to force alignment. p may not be aligned.... */ + if (lck->share_modes == NULL) { + DEBUG(0, ("talloc failed\n")); + return False; + } + } - memset(e, '\0', sizeof(share_mode_entry)); - e->pid = sys_getpid(); - e->share_access = fsp->share_access; - e->private_options = fsp->fh->private_options; - e->access_mask = fsp->access_mask; - e->op_port = port; - e->op_type = op_type; - memcpy(x, &fsp->open_time, sizeof(struct timeval)); - e->share_file_id = fsp->file_id; - e->dev = fsp->dev; - e->inode = fsp->inode; -} + /* Save off the associated filename. */ + lck->filename = talloc_strdup(lck, dbuf.dptr + sizeof(*data) + + lck->num_share_modes * + sizeof(struct share_mode_entry)); -/******************************************************************* - Check if two share mode entries are identical, ignoring oplock - and port info and desired_access. -********************************************************************/ + /* + * Ensure that each entry has a real process attached. + */ -BOOL share_modes_identical( share_mode_entry *e1, share_mode_entry *e2) -{ -#if 1 /* JRA PARANOIA TEST - REMOVE LATER */ - if (e1->pid == e2->pid && - e1->share_file_id == e2->share_file_id && - e1->dev == e2->dev && - e1->inode == e2->inode && - (e1->share_access) != (e2->share_access)) { - DEBUG(0,("PANIC: share_modes_identical: share_mode " - "mismatch (e1 = 0x%x, e2 = 0x%x). Logic error.\n", - (unsigned int)e1->share_access, - (unsigned int)e2->share_access )); - smb_panic("PANIC: share_modes_identical logic error.\n"); + for (i = 0; i < lck->num_share_modes; i++) { + struct share_mode_entry *entry_p = &lck->share_modes[i]; + DEBUG(10,("parse_share_modes: %s\n", + share_mode_str(i, entry_p) )); + if (!process_exists(entry_p->pid)) { + DEBUG(10,("parse_share_modes: deleted %s\n", + share_mode_str(i, entry_p) )); + entry_p->op_type = UNUSED_SHARE_MODE_ENTRY; + lck->modified = True; + } } -#endif - return (e1->pid == e2->pid && - (e1->share_access) == (e2->share_access) && - e1->dev == e2->dev && - e1->inode == e2->inode && - e1->share_file_id == e2->share_file_id ); + return True; } -/******************************************************************* - Delete a specific share mode. Return the number - of entries left, and a memdup'ed copy of the entry deleted (if required). - Ignore if no entry deleted. -********************************************************************/ - -ssize_t del_share_entry(SMB_DEV_T dev, SMB_INO_T inode, - share_mode_entry *entry, share_mode_entry **ppse, - BOOL *delete_on_close) +static TDB_DATA unparse_share_modes(struct share_mode_lock *lck) { - TDB_DATA dbuf; + TDB_DATA result; + int num_valid = 0; + int i; struct locking_data *data; - int i, del_count=0; - share_mode_entry *shares; - ssize_t count = 0; - TDB_DATA key = locking_key(dev, inode); - - if (ppse) - *ppse = NULL; - - /* read in the existing share modes */ - dbuf = tdb_fetch(tdb, key); - if (!dbuf.dptr) - return -1; - - data = (struct locking_data *)dbuf.dptr; - *delete_on_close = data->u.s.delete_on_close; - shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); - - /* - * Find any with this pid and delete it - * by overwriting with the rest of the data - * from the record. - */ - - DEBUG(10,("del_share_entry: num_share_modes = %d\n", data->u.s.num_share_mode_entries )); - - for (i=0;iu.s.num_share_mode_entries;) { - if (share_modes_identical(&shares[i], entry)) { - DEBUG(10,("del_share_entry: deleted %s\n", - share_mode_str(i, &shares[i]) )); - if (ppse) - *ppse = memdup(&shares[i], sizeof(*shares)); - data->u.s.num_share_mode_entries--; - if ((dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))) > 0) { - memmove(&shares[i], &shares[i+1], - dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*shares))); - } - del_count++; + ssize_t offset; - DEBUG(10,("del_share_entry: deleting entry %d\n", i )); + result.dptr = NULL; + result.dsize = 0; - } else { - i++; + for (i=0; inum_share_modes; i++) { + if (!is_unused_share_mode_entry(&lck->share_modes[i])) { + num_valid += 1; } } - if (del_count) { - /* the record may have shrunk a bit */ - dbuf.dsize -= del_count * sizeof(*shares); - - count = (ssize_t)data->u.s.num_share_mode_entries; - - /* store it back in the database */ - if (data->u.s.num_share_mode_entries == 0) { - if (tdb_delete(tdb, key) == -1) - count = -1; - } else { - if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) - count = -1; - } + if (num_valid == 0) { + return result; } - DEBUG(10,("del_share_entry: Remaining table.\n")); - print_share_mode_table((struct locking_data *)dbuf.dptr); - SAFE_FREE(dbuf.dptr); - return count; -} -/******************************************************************* - Del the share mode of a file for this process. Return the number - of entries left, and a memdup'ed copy of the entry deleted. -********************************************************************/ - -ssize_t del_share_mode(files_struct *fsp, share_mode_entry **ppse, - BOOL *delete_on_close) -{ - share_mode_entry entry; + result.dsize = sizeof(*data) + + lck->num_share_modes * sizeof(struct share_mode_entry) + + strlen(lck->filename) + 1; + result.dptr = talloc_size(lck, result.dsize); - /* - * Fake up a share_mode_entry for comparisons. - */ + if (result.dptr == NULL) { + smb_panic("talloc failed\n"); + } - fill_share_mode((char *)&entry, fsp, 0, 0); - return del_share_entry(fsp->dev, fsp->inode, &entry, ppse, - delete_on_close); + data = (struct locking_data *)result.dptr; + ZERO_STRUCTP(data); + data->u.s.num_share_mode_entries = lck->num_share_modes; + data->u.s.delete_on_close = lck->delete_on_close; + DEBUG(10, ("unparse_share_modes: del: %d, num: %d\n", + data->u.s.delete_on_close, + data->u.s.num_share_mode_entries)); + memcpy(result.dptr + sizeof(*data), lck->share_modes, + sizeof(struct share_mode_entry)*lck->num_share_modes); + offset = sizeof(*data) + + sizeof(struct share_mode_entry)*lck->num_share_modes; + safe_strcpy(result.dptr + offset, lck->filename, + result.dsize - offset - 1); + print_share_mode_table(data); + return result; } -/******************************************************************* - Set the share mode of a file. Return False on fail, True on success. -********************************************************************/ - -BOOL set_share_mode(files_struct *fsp, uint16 port, uint16 op_type) +static int share_mode_lock_destructor(void *p) { - TDB_DATA dbuf; - struct locking_data *data; - char *p=NULL; - int size; - TDB_DATA key = locking_key_fsp(fsp); - BOOL ret = True; - - /* read in the existing share modes if any */ - dbuf = tdb_fetch(tdb, key); - if (!dbuf.dptr) { - size_t offset; - /* we'll need to create a new record */ - pstring fname; - - pstrcpy(fname, fsp->conn->connectpath); - pstrcat(fname, "/"); - pstrcat(fname, fsp->fsp_name); - - size = sizeof(*data) + sizeof(share_mode_entry) + strlen(fname) + 1; - p = (char *)SMB_MALLOC(size); - if (!p) - return False; - data = (struct locking_data *)p; - ZERO_STRUCT(data->u); /* Keep valgrind happy */ - data->u.s.num_share_mode_entries = 1; - - DEBUG(10,("set_share_mode: creating entry for file %s. num_share_modes = 1\n", - fsp->fsp_name )); + struct share_mode_lock *lck = + talloc_get_type_abort(p, struct share_mode_lock); + TDB_DATA key = locking_key(lck->dev, lck->ino); + TDB_DATA data; - offset = sizeof(*data) + sizeof(share_mode_entry); - safe_strcpy(p + offset, fname, size - offset - 1); - fill_share_mode(p + sizeof(*data), fsp, port, op_type); - dbuf.dptr = p; - dbuf.dsize = size; - if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) - ret = False; + if (!lck->modified) { + goto done; + } - print_share_mode_table((struct locking_data *)p); + data = unparse_share_modes(lck); - SAFE_FREE(p); - return ret; + if (data.dptr == NULL) { + if (!lck->fresh) { + /* There has been an entry before, delete it */ + if (tdb_delete(tdb, key) == -1) { + smb_panic("Could not delete share entry\n"); + } + } + goto done; } - /* we're adding to an existing entry - this is a bit fiddly */ - data = (struct locking_data *)dbuf.dptr; + if (tdb_store(tdb, key, data, TDB_REPLACE) == -1) { + smb_panic("Could not store share mode entry\n"); + } - data->u.s.num_share_mode_entries++; - - DEBUG(10,("set_share_mode: adding entry for file %s. new num_share_modes = %d\n", - fsp->fsp_name, data->u.s.num_share_mode_entries )); + done: + tdb_chainunlock(tdb, key); - size = dbuf.dsize + sizeof(share_mode_entry); - p = SMB_MALLOC(size); - if (!p) { - SAFE_FREE(dbuf.dptr); - return False; - } - memcpy(p, dbuf.dptr, sizeof(*data)); - fill_share_mode(p + sizeof(*data), fsp, port, op_type); - memcpy(p + sizeof(*data) + sizeof(share_mode_entry), dbuf.dptr + sizeof(*data), - dbuf.dsize - sizeof(*data)); - SAFE_FREE(dbuf.dptr); - dbuf.dptr = p; - dbuf.dsize = size; - if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) - ret = False; - print_share_mode_table((struct locking_data *)p); - SAFE_FREE(p); - return ret; + return 0; } -/******************************************************************* - A generic in-place modification call for share mode entries. -********************************************************************/ - -static BOOL mod_share_mode( SMB_DEV_T dev, SMB_INO_T inode, share_mode_entry *entry, - void (*mod_fn)(share_mode_entry *, SMB_DEV_T, SMB_INO_T, void *), - void *param) +struct share_mode_lock *get_share_mode_lock(TALLOC_CTX *mem_ctx, + SMB_DEV_T dev, SMB_INO_T ino, + const char *fname) { - TDB_DATA dbuf; - struct locking_data *data; - int i; - share_mode_entry *shares; - BOOL need_store=False; - BOOL ret = True; - TDB_DATA key = locking_key(dev, inode); - - /* read in the existing share modes */ - dbuf = tdb_fetch(tdb, key); - if (!dbuf.dptr) - return False; + struct share_mode_lock *lck; + TDB_DATA key = locking_key(dev, ino); + TDB_DATA data; - data = (struct locking_data *)dbuf.dptr; - shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); + lck = TALLOC_P(mem_ctx, struct share_mode_lock); + if (lck == NULL) { + DEBUG(0, ("talloc failed\n")); + return NULL; + } - /* find any with our pid and call the supplied function */ - for (i=0;iu.s.num_share_mode_entries;i++) { - if (share_modes_identical(entry, &shares[i])) { - mod_fn(&shares[i], dev, inode, param); - need_store=True; - } + lck->dev = dev; + lck->ino = ino; + lck->delete_on_close = False; + lck->num_share_modes = 0; + lck->share_modes = NULL; + lck->modified = False; + + if (tdb_chainlock(tdb, key) != 0) { + DEBUG(3, ("Could not lock share entry\n")); + talloc_free(lck); + return NULL; } - /* if the mod fn was called then store it back */ - if (need_store) { - if (data->u.s.num_share_mode_entries == 0) { - if (tdb_delete(tdb, key) == -1) - ret = False; - } else { - if (tdb_store(tdb, key, dbuf, TDB_REPLACE) == -1) - ret = False; + data = tdb_fetch(tdb, key); + lck->fresh = (data.dptr == NULL); + + if (lck->fresh) { + if (fname == NULL) { + DEBUG(0, ("New file, but no filename supplied\n")); + talloc_free(lck); + return NULL; + } + lck->filename = talloc_strdup(lck, fname); + if (lck->filename == NULL) { + DEBUG(0, ("talloc failed\n")); + talloc_free(lck); + return NULL; + } + } else { + if (!parse_share_modes(data, lck)) { + DEBUG(0, ("Could not parse share modes\n")); + talloc_free(lck); + SAFE_FREE(data.dptr); + return NULL; } } - SAFE_FREE(dbuf.dptr); - return ret; -} + talloc_set_destructor(lck, share_mode_lock_destructor); + SAFE_FREE(data.dptr); -/******************************************************************* - Static function that actually does the work for the generic function - below. -********************************************************************/ + return lck; +} -static void remove_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, - void *param) +BOOL get_delete_on_close_flag(SMB_DEV_T dev, SMB_INO_T inode, + const char *fname) { - DEBUG(10,("remove_share_oplock_fn: removing oplock info for entry dev=%x ino=%.0f\n", - (unsigned int)dev, (double)inode )); - /* Delete the oplock info. */ - entry->op_port = 0; - entry->op_type = NO_OPLOCK; + BOOL result; + struct share_mode_lock *lck = get_share_mode_lock(NULL, dev, inode, + fname); + result = lck->delete_on_close; + talloc_free(lck); + return result; } -/******************************************************************* - Remove an oplock port and mode entry from a share mode. -********************************************************************/ - -BOOL remove_share_oplock(files_struct *fsp) +BOOL is_valid_share_mode_entry(const struct share_mode_entry *e) { - share_mode_entry entry; - /* - * Fake up an entry for comparisons... - */ - fill_share_mode((char *)&entry, fsp, 0, 0); - return mod_share_mode(fsp->dev, fsp->inode, &entry, remove_share_oplock_fn, NULL); + int num_props = 0; + + num_props += ((e->op_type == NO_OPLOCK) ? 1 : 0); + num_props += (EXCLUSIVE_OPLOCK_TYPE(e->op_type) ? 1 : 0); + num_props += (LEVEL_II_OPLOCK_TYPE(e->op_type) ? 1 : 0); + + SMB_ASSERT(num_props <= 1); + return (num_props != 0); } -/******************************************************************* - Static function that actually does the work for the generic function - below. -********************************************************************/ +BOOL is_deferred_open_entry(const struct share_mode_entry *e) +{ + return (e->op_type == DEFERRED_OPEN_ENTRY); +} -static void downgrade_share_oplock_fn(share_mode_entry *entry, SMB_DEV_T dev, SMB_INO_T inode, - void *param) +BOOL is_unused_share_mode_entry(const struct share_mode_entry *e) { - DEBUG(10,("downgrade_share_oplock_fn: downgrading oplock info for entry dev=%x ino=%.0f\n", - (unsigned int)dev, (double)inode )); - entry->op_type = LEVEL_II_OPLOCK; + return (e->op_type == UNUSED_SHARE_MODE_ENTRY); } /******************************************************************* - Downgrade a oplock type from exclusive to level II. + Fill a share mode entry. ********************************************************************/ -BOOL downgrade_share_oplock(files_struct *fsp) +static void fill_share_mode_entry(struct share_mode_entry *e, + files_struct *fsp, + uint16 mid, uint16 op_type) { - share_mode_entry entry; - /* - * Fake up an entry for comparisons... - */ - fill_share_mode((char *)&entry, fsp, 0, 0); - return mod_share_mode(fsp->dev, fsp->inode, &entry, downgrade_share_oplock_fn, NULL); + ZERO_STRUCTP(e); + e->pid = procid_self(); + e->share_access = fsp->share_access; + e->private_options = fsp->fh->private_options; + e->access_mask = fsp->access_mask; + e->op_mid = mid; + e->op_type = op_type; + e->time.tv_sec = fsp->open_time.tv_sec; + e->time.tv_usec = fsp->open_time.tv_usec; + e->share_file_id = fsp->file_id; + e->dev = fsp->dev; + e->inode = fsp->inode; } -/******************************************************************* - Get/Set the delete on close flag in a set of share modes. - Return False on fail, True on success. -********************************************************************/ - -BOOL modify_delete_flag( SMB_DEV_T dev, SMB_INO_T inode, BOOL delete_on_close) +static void fill_deferred_open_entry(struct share_mode_entry *e, + const struct timeval request_time, + SMB_DEV_T dev, SMB_INO_T ino, uint16 mid) { - TDB_DATA dbuf; - struct locking_data *data; - BOOL res; - TDB_DATA key = locking_key(dev, inode); + ZERO_STRUCTP(e); + e->pid = procid_self(); + e->op_mid = mid; + e->op_type = DEFERRED_OPEN_ENTRY; + e->time.tv_sec = request_time.tv_sec; + e->time.tv_usec = request_time.tv_usec; + e->dev = dev; + e->inode = ino; +} - /* read in the existing share modes */ - dbuf = tdb_fetch(tdb, key); - if (!dbuf.dptr) - return False; +static void add_share_mode_entry(struct share_mode_lock *lck, + const struct share_mode_entry *entry) +{ + int i; - data = (struct locking_data *)dbuf.dptr; + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *e = &lck->share_modes[i]; + if (is_unused_share_mode_entry(e)) { + *e = *entry; + break; + } + } - /* Set/Unset the delete on close element. */ - data->u.s.delete_on_close = delete_on_close; + if (i == lck->num_share_modes) { + /* No unused entry found */ + ADD_TO_ARRAY(lck, struct share_mode_entry, *entry, + &lck->share_modes, &lck->num_share_modes); + } + lck->modified = True; +} - res = (tdb_store(tdb, key, dbuf, TDB_REPLACE)!=-1); +void set_share_mode(struct share_mode_lock *lck, files_struct *fsp, + uint16 mid, uint16 op_type) +{ + struct share_mode_entry entry; + fill_share_mode_entry(&entry, fsp, mid, op_type); + add_share_mode_entry(lck, &entry); +} - SAFE_FREE(dbuf.dptr); - return res; +void add_deferred_open(struct share_mode_lock *lck, uint16 mid, + struct timeval request_time, + SMB_DEV_T dev, SMB_INO_T ino) +{ + struct share_mode_entry entry; + fill_deferred_open_entry(&entry, request_time, dev, ino, mid); + add_share_mode_entry(lck, &entry); } /******************************************************************* - Print out a deferred open entry. + Check if two share mode entries are identical, ignoring oplock + and mid info and desired_access. ********************************************************************/ -char *deferred_open_str(int num, deferred_open_entry *e) +static BOOL share_modes_identical(struct share_mode_entry *e1, + struct share_mode_entry *e2) { - static pstring de_str; - - slprintf(de_str, sizeof(de_str)-1, "deferred_open_entry[%d]: \ -pid = %lu, mid = %u, dev = 0x%x, inode = %.0f, port = %u, time = [%u.%06u]", - num, (unsigned long)e->pid, (unsigned int)e->mid, (unsigned int)e->dev, (double)e->inode, - (unsigned int)e->port, - (unsigned int)e->time.tv_sec, (unsigned int)e->time.tv_usec ); +#if 1 /* JRA PARANOIA TEST - REMOVE LATER */ + if (procid_equal(&e1->pid, &e2->pid) && + e1->share_file_id == e2->share_file_id && + e1->dev == e2->dev && + e1->inode == e2->inode && + (e1->share_access) != (e2->share_access)) { + DEBUG(0,("PANIC: share_modes_identical: share_mode " + "mismatch (e1 = 0x%x, e2 = 0x%x). Logic error.\n", + (unsigned int)e1->share_access, + (unsigned int)e2->share_access )); + smb_panic("PANIC: share_modes_identical logic error.\n"); + } +#endif - return de_str; + return (procid_equal(&e1->pid, &e2->pid) && + (e1->share_access) == (e2->share_access) && + e1->dev == e2->dev && + e1->inode == e2->inode && + e1->share_file_id == e2->share_file_id ); } -/* Internal data structures for deferred opens... */ +static BOOL deferred_open_identical(struct share_mode_entry *e1, + struct share_mode_entry *e2) +{ + return (procid_equal(&e1->pid, &e2->pid) && + (e1->op_mid == e2->op_mid) && + (e1->dev == e2->dev) && + (e1->inode == e2->inode)); +} -struct de_locking_key { - char name[4]; - SMB_DEV_T dev; - SMB_INO_T inode; -}; +static struct share_mode_entry *find_share_mode_entry(struct share_mode_lock *lck, + struct share_mode_entry *entry) +{ + int i; -struct deferred_open_data { - union { - int num_deferred_open_entries; - deferred_open_entry dummy; /* Needed for alignment. */ - } u; - /* the following two entries are implicit - deferred_open_entry de_entries[num_deferred_open_entries]; - char file_name[]; - */ -}; + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *e = &lck->share_modes[i]; + if (is_valid_share_mode_entry(entry) && + is_valid_share_mode_entry(e) && + share_modes_identical(e, entry)) { + return e; + } + if (is_deferred_open_entry(entry) && + is_deferred_open_entry(e) && + deferred_open_identical(e, entry)) { + return e; + } + } + return NULL; +} /******************************************************************* - Print out a deferred open table. + Del the share mode of a file for this process. Return the number of + entries left. ********************************************************************/ -static void print_deferred_open_table(struct deferred_open_data *data) +BOOL del_share_mode(struct share_mode_lock *lck, files_struct *fsp) { - int num_de_entries = data->u.num_deferred_open_entries; - deferred_open_entry *de_entries = (deferred_open_entry *)(data + 1); - int i; + struct share_mode_entry entry, *e; + + fill_share_mode_entry(&entry, fsp, 0, 0); - for (i = 0; i < num_de_entries; i++) { - deferred_open_entry *entry_p = &de_entries[i]; - DEBUG(10,("print_deferred_open_table: %s\n", deferred_open_str(i, entry_p) )); + e = find_share_mode_entry(lck, &entry); + if (e == NULL) { + return False; } + + e->op_type = UNUSED_SHARE_MODE_ENTRY; + lck->modified = True; + return True; } +void del_deferred_open_entry(struct share_mode_lock *lck, uint16 mid) +{ + struct share_mode_entry entry, *e; -/******************************************************************* - Form a static deferred open locking key for a dev/inode pair. -******************************************************************/ + fill_deferred_open_entry(&entry, timeval_zero(), + lck->dev, lck->ino, mid); -static TDB_DATA deferred_open_locking_key(SMB_DEV_T dev, SMB_INO_T inode) -{ - static struct de_locking_key key; - TDB_DATA kbuf; + e = find_share_mode_entry(lck, &entry); + if (e == NULL) { + return; + } - memset(&key, '\0', sizeof(key)); - memcpy(&key.name[0], "DOE", 4); - key.dev = dev; - key.inode = inode; - kbuf.dptr = (char *)&key; - kbuf.dsize = sizeof(key); - return kbuf; + e->op_type = UNUSED_SHARE_MODE_ENTRY; + lck->modified = True; } /******************************************************************* - Get all deferred open entries for a dev/inode pair. + Remove an oplock mid and mode entry from a share mode. ********************************************************************/ -int get_deferred_opens(connection_struct *conn, - SMB_DEV_T dev, SMB_INO_T inode, - deferred_open_entry **pp_de_entries) +BOOL remove_share_oplock(struct share_mode_lock *lck, files_struct *fsp) { - TDB_DATA dbuf; - struct deferred_open_data *data; - int num_de_entries; - deferred_open_entry *de_entries = NULL; - TDB_DATA key = deferred_open_locking_key(dev, inode); + struct share_mode_entry entry, *e; - *pp_de_entries = NULL; + fill_share_mode_entry(&entry, fsp, 0, 0); - dbuf = tdb_fetch(deferred_open_tdb, key); - if (!dbuf.dptr) - return 0; - - data = (struct deferred_open_data *)dbuf.dptr; - num_de_entries = data->u.num_deferred_open_entries; - if(num_de_entries) { - pstring fname; - int i; - int del_count = 0; - - de_entries = (deferred_open_entry *)memdup(dbuf.dptr + sizeof(*data), - num_de_entries * sizeof(deferred_open_entry)); - - if (!de_entries) { - SAFE_FREE(dbuf.dptr); - return 0; - } + e = find_share_mode_entry(lck, &entry); + if (e == NULL) { + return False; + } - /* Save off the associated filename. */ - pstrcpy(fname, dbuf.dptr + sizeof(*data) + num_de_entries * sizeof(deferred_open_entry)); + e->op_mid = 0; + e->op_type = NO_OPLOCK; + lck->modified = True; + return True; +} - /* - * Ensure that each entry has a real process attached. - */ +/******************************************************************* + Downgrade a oplock type from exclusive to level II. +********************************************************************/ - for (i = 0; i < num_de_entries; ) { - deferred_open_entry *entry_p = &de_entries[i]; - if (process_exists(entry_p->pid)) { - DEBUG(10,("get_deferred_opens: %s\n", deferred_open_str(i, entry_p) )); - i++; - } else { - DEBUG(10,("get_deferred_opens: deleted %s\n", deferred_open_str(i, entry_p) )); - if (num_de_entries - i - 1 > 0) { - memcpy( &de_entries[i], &de_entries[i+1], - sizeof(deferred_open_entry) * (num_de_entries - i - 1)); - } - num_de_entries--; - del_count++; - } - } +BOOL downgrade_share_oplock(struct share_mode_lock *lck, files_struct *fsp) +{ + struct share_mode_entry entry, *e; - /* Did we delete any ? If so, re-store in tdb. */ - if (del_count) { - data->u.num_deferred_open_entries = num_de_entries; - - if (num_de_entries) { - memcpy(dbuf.dptr + sizeof(*data), de_entries, - num_de_entries * sizeof(deferred_open_entry)); - /* Append the filename. */ - pstrcpy(dbuf.dptr + sizeof(*data) + num_de_entries * sizeof(deferred_open_entry), fname); - } + fill_share_mode_entry(&entry, fsp, 0, 0); - /* The record has shrunk a bit */ - dbuf.dsize -= del_count * sizeof(deferred_open_entry); - - if (data->u.num_deferred_open_entries == 0) { - if (tdb_delete(deferred_open_tdb, key) == -1) { - SAFE_FREE(de_entries); - SAFE_FREE(dbuf.dptr); - return 0; - } - } else { - if (tdb_store(deferred_open_tdb, key, dbuf, TDB_REPLACE) == -1) { - SAFE_FREE(de_entries); - SAFE_FREE(dbuf.dptr); - return 0; - } - } - } + e = find_share_mode_entry(lck, &entry); + if (e == NULL) { + return False; } - SAFE_FREE(dbuf.dptr); - *pp_de_entries = de_entries; - return num_de_entries; + e->op_type = LEVEL_II_OPLOCK; + lck->modified = True; + return True; } + /******************************************************************* - Check if two deferred open entries are identical. + We've just told all the smbd's that our level2 or fake level2 has been + written to. ********************************************************************/ - -static BOOL deferred_open_entries_identical( deferred_open_entry *e1, deferred_open_entry *e2) +BOOL remove_all_share_oplocks(struct share_mode_lock *lck, files_struct *fsp) { - return (e1->pid == e2->pid && - e1->mid == e2->mid && - e1->port == e2->port && - e1->dev == e2->dev && - e1->inode == e2->inode && - e1->time.tv_sec == e2->time.tv_sec && - e1->time.tv_usec == e2->time.tv_usec); + int i; + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *e = &lck->share_modes[i]; + if (!is_valid_share_mode_entry(e)) { + continue; + } + if (e->op_type == NO_OPLOCK) { + continue; + } + e->op_type = NO_OPLOCK; + lck->modified = True; + } + return True; } -/******************************************************************* - Delete a specific deferred open entry. - Ignore if no entry deleted. -********************************************************************/ +/**************************************************************************** + Deal with the internal needs of setting the delete on close flag. Note that + as the tdb locking is recursive, it is safe to call this from within + open_file_shared. JRA. +****************************************************************************/ -BOOL delete_deferred_open_entry(deferred_open_entry *entry) +NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close, + uint32 dosmode) { - TDB_DATA dbuf; - struct deferred_open_data *data; - int i, del_count=0; - deferred_open_entry *de_entries; - BOOL ret = True; - TDB_DATA key = deferred_open_locking_key(entry->dev, entry->inode); - - /* read in the existing share modes */ - dbuf = tdb_fetch(deferred_open_tdb, key); - if (!dbuf.dptr) - return -1; - - data = (struct deferred_open_data *)dbuf.dptr; - de_entries = (deferred_open_entry *)(dbuf.dptr + sizeof(*data)); + if (!delete_on_close) { + return NT_STATUS_OK; + } /* - * Find any with this pid and delete it - * by overwriting with the rest of the data - * from the record. + * Only allow delete on close for writable files. */ - DEBUG(10,("delete_deferred_open_entry: num_deferred_open_entries = %d\n", - data->u.num_deferred_open_entries )); - - for (i=0;iu.num_deferred_open_entries;) { - if (deferred_open_entries_identical(&de_entries[i], entry)) { - DEBUG(10,("delete_deferred_open_entry: deleted %s\n", - deferred_open_str(i, &de_entries[i]) )); - - data->u.num_deferred_open_entries--; - if ((dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*de_entries))) > 0) { - memmove(&de_entries[i], &de_entries[i+1], - dbuf.dsize - (sizeof(*data) + (i+1)*sizeof(*de_entries))); - } - del_count++; - - DEBUG(10,("delete_deferred_open_entry: deleting entry %d\n", i )); - - } else { - i++; - } + if ((dosmode & aRONLY) && + !lp_delete_readonly(SNUM(fsp->conn))) { + DEBUG(10,("can_set_delete_on_close: file %s delete on close " + "flag set but file attribute is readonly.\n", + fsp->fsp_name )); + return NT_STATUS_CANNOT_DELETE; } - SMB_ASSERT(del_count == 0 || del_count == 1); - - if (del_count) { - /* the record may have shrunk a bit */ - dbuf.dsize -= del_count * sizeof(*de_entries); + /* + * Only allow delete on close for writable shares. + */ - /* store it back in the database */ - if (data->u.num_deferred_open_entries == 0) { - if (tdb_delete(deferred_open_tdb, key) == -1) - ret = False; - } else { - if (tdb_store(deferred_open_tdb, key, dbuf, TDB_REPLACE) == -1) - ret = False; - } + if (!CAN_WRITE(fsp->conn)) { + DEBUG(10,("can_set_delete_on_close: file %s delete on " + "close flag set but write access denied on share.\n", + fsp->fsp_name )); + return NT_STATUS_ACCESS_DENIED; } - DEBUG(10,("delete_deferred_open_entry: Remaining table.\n")); - print_deferred_open_table((struct deferred_open_data*)dbuf.dptr); - SAFE_FREE(dbuf.dptr); - return ret; -} -/******************************************************************* - Fill a deferred open entry. -********************************************************************/ + /* + * Only allow delete on close for files/directories opened with delete + * intent. + */ -static void fill_deferred_open(char *p, uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T inode, uint16 port) -{ - deferred_open_entry *e = (deferred_open_entry *)p; - void *x = &e->time; /* Needed to force alignment. p may not be aligned.... */ + if (!(fsp->access_mask & DELETE_ACCESS)) { + DEBUG(10,("can_set_delete_on_close: file %s delete on " + "close flag set but delete access denied.\n", + fsp->fsp_name )); + return NT_STATUS_ACCESS_DENIED; + } - memset(e, '\0', sizeof(deferred_open_entry)); - e->mid = mid; - e->pid = sys_getpid(); - memcpy(x, ptv, sizeof(struct timeval)); - e->dev = dev; - e->inode = inode; - e->port = port; + return NT_STATUS_OK; } -/******************************************************************* - Add a deferred open record. Return False on fail, True on success. -********************************************************************/ +/**************************************************************************** + Sets the delete on close flag over all share modes on this file. + Modify the share mode entry for all files open + on this device and inode to tell other smbds we have + changed the delete on close flag. This will be noticed + in the close code, the last closer will delete the file + if flag is set. +****************************************************************************/ -BOOL add_deferred_open(uint16 mid, struct timeval *ptv, SMB_DEV_T dev, SMB_INO_T inode, uint16 port, const char *fname) +BOOL set_delete_on_close(files_struct *fsp, BOOL delete_on_close) { - TDB_DATA dbuf; - struct deferred_open_data *data; - char *p=NULL; - int size; - TDB_DATA key = deferred_open_locking_key(dev, inode); - BOOL ret = True; - - /* read in the existing deferred open records if any */ - dbuf = tdb_fetch(deferred_open_tdb, key); - if (!dbuf.dptr) { - size_t offset; - /* we'll need to create a new record */ - - size = sizeof(*data) + sizeof(deferred_open_entry) + strlen(fname) + 1; - p = (char *)SMB_MALLOC(size); - if (!p) - return False; - data = (struct deferred_open_data *)p; - ZERO_STRUCT(data->u.dummy); /* Keep valgrind happy */ - data->u.num_deferred_open_entries = 1; + struct share_mode_lock *lck; - DEBUG(10,("add_deferred_open: creating entry for file %s. num_deferred_open_entries = 1\n", - fname )); - - offset = sizeof(*data) + sizeof(deferred_open_entry); - safe_strcpy(p + offset, fname, size - offset - 1); - fill_deferred_open(p + sizeof(*data), mid, ptv, dev, inode, port); - dbuf.dptr = p; - dbuf.dsize = size; - if (tdb_store(deferred_open_tdb, key, dbuf, TDB_REPLACE) == -1) - ret = False; - - print_deferred_open_table((struct deferred_open_data *)p); - - SAFE_FREE(p); - return ret; - } - - /* we're adding to an existing entry - this is a bit fiddly */ - data = (struct deferred_open_data *)dbuf.dptr; + DEBUG(10,("set_delete_on_close: %s delete on close flag for " + "fnum = %d, file %s\n", + delete_on_close ? "Adding" : "Removing", fsp->fnum, + fsp->fsp_name )); - data->u.num_deferred_open_entries++; - - DEBUG(10,("add_deferred_open: adding entry for file %s. new num_deferred_open_entries = %d\n", - fname, data->u.num_deferred_open_entries )); + if (fsp->is_directory || fsp->is_stat) + return True; - size = dbuf.dsize + sizeof(deferred_open_entry); - p = SMB_MALLOC(size); - if (!p) { - SAFE_FREE(dbuf.dptr); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); + if (lck == NULL) { return False; } - memcpy(p, dbuf.dptr, sizeof(*data)); - fill_deferred_open(p + sizeof(*data), mid, ptv, dev, inode, port); - memcpy(p + sizeof(*data) + sizeof(deferred_open_entry), dbuf.dptr + sizeof(*data), - dbuf.dsize - sizeof(*data)); - SAFE_FREE(dbuf.dptr); - dbuf.dptr = p; - dbuf.dsize = size; - if (tdb_store(deferred_open_tdb, key, dbuf, TDB_REPLACE) == -1) - ret = False; - print_deferred_open_table((struct deferred_open_data *)p); - SAFE_FREE(p); - return ret; -} + if (lck->delete_on_close != delete_on_close) { + lck->delete_on_close = delete_on_close; + lck->modified = True; + } -/**************************************************************************** - Traverse the whole database with this function, calling traverse_callback - on each share mode -****************************************************************************/ + talloc_free(lck); + return True; +} static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, - void* state) + void *state) { struct locking_data *data; - share_mode_entry *shares; + struct share_mode_entry *shares; char *name; int i; - - SHAREMODE_FN(traverse_callback) = (SHAREMODE_FN_CAST())state; + void (*traverse_callback)(struct share_mode_entry *, char *) = state; /* Ensure this is a locking_key record. */ if (kbuf.dsize != sizeof(struct locking_key)) return 0; data = (struct locking_data *)dbuf.dptr; - shares = (share_mode_entry *)(dbuf.dptr + sizeof(*data)); - name = dbuf.dptr + sizeof(*data) + data->u.s.num_share_mode_entries*sizeof(*shares); + shares = (struct share_mode_entry *)(dbuf.dptr + sizeof(*data)); + name = dbuf.dptr + sizeof(*data) + + data->u.s.num_share_mode_entries*sizeof(*shares); for (i=0;iu.s.num_share_mode_entries;i++) { traverse_callback(&shares[i], name); @@ -1299,9 +1005,9 @@ static int traverse_fn(TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, share mode system. ********************************************************************/ -int share_mode_forall(SHAREMODE_FN(fn)) +int share_mode_forall(void (*fn)(const struct share_mode_entry *, char *)) { - if (!tdb) + if (tdb == NULL) return 0; - return tdb_traverse(tdb, traverse_fn, (void*)fn); + return tdb_traverse(tdb, traverse_fn, fn); } diff --git a/source3/modules/weird.c b/source3/modules/weird.c index 3c59fd9d61f..ccee9d71edd 100644 --- a/source3/modules/weird.c +++ b/source3/modules/weird.c @@ -23,7 +23,7 @@ static struct { char from; - char *to; + const char *to; int len; } weird_table[] = { {'q', "^q^", 3}, diff --git a/source3/nmbd/asyncdns.c b/source3/nmbd/asyncdns.c index 653cb97fbb0..4db54ea198c 100644 --- a/source3/nmbd/asyncdns.c +++ b/source3/nmbd/asyncdns.c @@ -201,7 +201,7 @@ void run_dns_queue(void) /* Allow SIGTERM to kill us. */ BlockSignals(False, SIGTERM); - if (!process_exists(child_pid)) { + if (!process_exists_by_pid(child_pid)) { close(fd_in); start_async_dns(); } diff --git a/source3/nmbd/nmbd.c b/source3/nmbd/nmbd.c index bc58dd3a281..fcaba03b3db 100644 --- a/source3/nmbd/nmbd.c +++ b/source3/nmbd/nmbd.c @@ -76,7 +76,8 @@ static void terminate(void) Handle a SHUTDOWN message from smbcontrol. **************************************************************************** */ -static void nmbd_terminate(int msg_type, pid_t src, void *buf, size_t len) +static void nmbd_terminate(int msg_type, struct process_id src, + void *buf, size_t len) { terminate(); } @@ -307,7 +308,8 @@ static BOOL reload_nmbd_services(BOOL test) * detects that there are no subnets. **************************************************************************** */ -static void msg_reload_nmbd_services(int msg_type, pid_t src, void *buf, size_t len) +static void msg_reload_nmbd_services(int msg_type, struct process_id src, + void *buf, size_t len) { write_browse_list( 0, True ); dump_all_namelists(); @@ -323,31 +325,33 @@ static void msg_reload_nmbd_services(int msg_type, pid_t src, void *buf, size_t } } -static void msg_nmbd_send_packet(int msg_type, pid_t src, +static void msg_nmbd_send_packet(int msg_type, struct process_id src, void *buf, size_t len) { struct packet_struct *p = (struct packet_struct *)buf; struct subnet_record *subrec; struct in_addr *local_ip; - DEBUG(10, ("Received send_packet from %d\n", src)); + DEBUG(10, ("Received send_packet from %d\n", procid_to_pid(&src))); if (len != sizeof(struct packet_struct)) { - DEBUG(2, ("Discarding invalid packet length from %d\n", src)); + DEBUG(2, ("Discarding invalid packet length from %d\n", + procid_to_pid(&src))); return; } if ((p->packet_type != NMB_PACKET) && (p->packet_type != DGRAM_PACKET)) { DEBUG(2, ("Discarding invalid packet type from %d: %d\n", - src, p->packet_type)); + procid_to_pid(&src), p->packet_type)); return; } local_ip = iface_ip(p->ip); if (local_ip == NULL) { - DEBUG(2, ("Could not find ip for packet from %d\n", src)); + DEBUG(2, ("Could not find ip for packet from %d\n", + procid_to_pid(&src))); return; } @@ -590,7 +594,8 @@ static void process(void) if(reload_after_sighup) { DEBUG( 0, ( "Got SIGHUP dumping debug info.\n" ) ); - msg_reload_nmbd_services(MSG_SMB_CONF_UPDATED, (pid_t) 0, (void*) &no_subnets, 0); + msg_reload_nmbd_services(MSG_SMB_CONF_UPDATED, + pid_to_procid(0), (void*) &no_subnets, 0); if(no_subnets) return; reload_after_sighup = 0; diff --git a/source3/nmbd/nmbd_elections.c b/source3/nmbd/nmbd_elections.c index 470cf4277b5..6e8e8429bec 100644 --- a/source3/nmbd/nmbd_elections.c +++ b/source3/nmbd/nmbd_elections.c @@ -374,7 +374,8 @@ yet registered on subnet %s\n", nmb_namestr(&nmbname), subrec->subnet_name )); Process a internal Samba message forcing an election. ***************************************************************************/ -void nmbd_message_election(int msg_type, pid_t src, void *buf, size_t len) +void nmbd_message_election(int msg_type, struct process_id src, + void *buf, size_t len) { struct subnet_record *subrec; diff --git a/source3/nmbd/nmbd_packets.c b/source3/nmbd/nmbd_packets.c index 4baf2d3d6ce..c25473c4fba 100644 --- a/source3/nmbd/nmbd_packets.c +++ b/source3/nmbd/nmbd_packets.c @@ -1246,7 +1246,7 @@ packet sent to name %s from IP %s\n", packet sent to name %s from IP %s\n", dgram->datasize, len, - PTR_DIFF(buf2, dgram->data), + (int)PTR_DIFF(buf2, dgram->data), nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip) )); return; @@ -1257,7 +1257,7 @@ packet sent to name %s from IP %s\n", packet sent to name %s from IP %s\n", dgram->datasize, len, - PTR_DIFF(buf2, dgram->data), + (int)PTR_DIFF(buf2, dgram->data), nmb_namestr(&dgram->dest_name), inet_ntoa(p->ip) )); return; diff --git a/source3/nmbd/nmbd_synclists.c b/source3/nmbd/nmbd_synclists.c index 33690133bf8..28ad92ed108 100644 --- a/source3/nmbd/nmbd_synclists.c +++ b/source3/nmbd/nmbd_synclists.c @@ -294,7 +294,7 @@ void sync_check_completion(void) for (s=syncs;s;s=next) { next = s->next; - if (!process_exists(s->pid)) { + if (!process_exists_by_pid(s->pid)) { /* it has completed - grab the info */ complete_sync(s); DLIST_REMOVE(syncs, s); diff --git a/source3/nmbd/nmbd_winsserver.c b/source3/nmbd/nmbd_winsserver.c index 86f5b9c4261..d76cb8f0322 100644 --- a/source3/nmbd/nmbd_winsserver.c +++ b/source3/nmbd/nmbd_winsserver.c @@ -1874,7 +1874,8 @@ void wins_write_database(BOOL background) Process a internal Samba message receiving a wins record. ***************************************************************************/ -void nmbd_wins_new_entry(int msg_type, pid_t src, void *buf, size_t len) +void nmbd_wins_new_entry(int msg_type, struct process_id src, + void *buf, size_t len) { WINS_RECORD *record; struct name_record *namerec = NULL; diff --git a/source3/nsswitch/wb_common.c b/source3/nsswitch/wb_common.c index 6d09666525f..5521614965a 100644 --- a/source3/nsswitch/wb_common.c +++ b/source3/nsswitch/wb_common.c @@ -543,6 +543,11 @@ NSS_STATUS winbindd_send_request(int req_type, struct winbindd_request *request) if (write_sock(request, sizeof(*request), request->flags & WBFLAG_RECURSE) == -1) { return NSS_STATUS_UNAVAIL; } + + if ((request->extra_len != 0) && + (write_sock(request->extra_data, request->extra_len, request->flags & WBFLAG_RECURSE) == -1)) { + return NSS_STATUS_UNAVAIL; + } return NSS_STATUS_SUCCESS; } diff --git a/source3/nsswitch/wbinfo.c b/source3/nsswitch/wbinfo.c index 34b2d6c9299..60f1d6b7221 100644 --- a/source3/nsswitch/wbinfo.c +++ b/source3/nsswitch/wbinfo.c @@ -192,7 +192,6 @@ static BOOL wbinfo_get_userdomgroups(const char *user_sid) return True; } - /* Convert NetBIOS name to IP */ static BOOL wbinfo_wins_byname(char *name) diff --git a/source3/nsswitch/winbindd.c b/source3/nsswitch/winbindd.c index dffaad5ef00..565764fa4be 100644 --- a/source3/nsswitch/winbindd.c +++ b/source3/nsswitch/winbindd.c @@ -204,7 +204,7 @@ static void sigchld_handler(int signum) } /* React on 'smbcontrol winbindd reload-config' in the same way as on SIGHUP*/ -static void msg_reload_services(int msg_type, pid_t src, void *buf, size_t len) +static void msg_reload_services(int msg_type, struct process_id src, void *buf, size_t len) { /* Flush various caches */ flush_caches(); @@ -212,7 +212,7 @@ static void msg_reload_services(int msg_type, pid_t src, void *buf, size_t len) } /* React on 'smbcontrol winbindd shutdown' in the same way as on SIGTERM*/ -static void msg_shutdown(int msg_type, pid_t src, void *buf, size_t len) +static void msg_shutdown(int msg_type, struct process_id src, void *buf, size_t len) { terminate(); } @@ -455,6 +455,7 @@ void setup_async_write(struct fd_event *event, void *data, size_t length, static void request_len_recv(void *private_data, BOOL success); static void request_recv(void *private_data, BOOL success); +static void request_main_recv(void *private_data, BOOL success); static void request_finished(struct winbindd_cli_state *state); void request_finished_cont(void *private_data, BOOL success); static void response_main_sent(void *private_data, BOOL success); @@ -475,6 +476,7 @@ static void response_extra_sent(void *private_data, BOOL success) return; } + SAFE_FREE(state->request.extra_data); SAFE_FREE(state->response.extra_data); setup_async_read(&state->fd_event, &state->request, sizeof(uint32), @@ -538,7 +540,7 @@ void request_finished_cont(void *private_data, BOOL success) request_error(state); } -static void request_recv(void *private_data, BOOL success) +static void request_len_recv(void *private_data, BOOL success) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); @@ -548,10 +550,19 @@ static void request_recv(void *private_data, BOOL success) return; } - process_request(state); + if (*(uint32 *)(&state->request) != sizeof(state->request)) { + DEBUG(0,("request_len_recv: Invalid request size received: %d\n", + *(uint32 *)(&state->request))); + state->finished = True; + return; + } + + setup_async_read(&state->fd_event, (uint32 *)(&state->request)+1, + sizeof(state->request) - sizeof(uint32), + request_main_recv, state); } -static void request_len_recv(void *private_data, BOOL success) +static void request_main_recv(void *private_data, BOOL success) { struct winbindd_cli_state *state = talloc_get_type_abort(private_data, struct winbindd_cli_state); @@ -561,16 +572,48 @@ static void request_len_recv(void *private_data, BOOL success) return; } - if (*(uint32 *)(&state->request) != sizeof(state->request)) { - DEBUG(0,("request_len_recv: Invalid request size received: %d\n", - *(uint32 *)(&state->request))); + if (state->request.extra_len == 0) { + state->request.extra_data = NULL; + request_recv(state, True); + return; + } + + if ((!state->privileged) && + (state->request.extra_len > WINBINDD_MAX_EXTRA_DATA)) { + DEBUG(3, ("Got request with %d bytes extra data on " + "unprivileged socket\n", (int)state->request.extra_len)); + state->request.extra_data = NULL; state->finished = True; return; } - setup_async_read(&state->fd_event, (uint32 *)(&state->request)+1, - sizeof(state->request) - sizeof(uint32), - request_recv, state); + state->request.extra_data = + SMB_MALLOC_ARRAY(char, state->request.extra_len + 1); + + if (state->request.extra_data == NULL) { + DEBUG(0, ("malloc failed\n")); + state->finished = True; + return; + } + + /* Ensure null termination */ + state->request.extra_data[state->request.extra_len] = '\0'; + + setup_async_read(&state->fd_event, state->request.extra_data, + state->request.extra_len, request_recv, state); +} + +static void request_recv(void *private_data, BOOL success) +{ + struct winbindd_cli_state *state = + talloc_get_type_abort(private_data, struct winbindd_cli_state); + + if (!success) { + state->finished = True; + return; + } + + process_request(state); } /* Process a new connection by adding it to the client connection list */ @@ -842,7 +885,7 @@ static void process_loop(void) DEBUG(3, ("got SIGHUP\n")); - msg_reload_services(MSG_SMB_CONF_UPDATED, (pid_t) 0, NULL, 0); + msg_reload_services(MSG_SMB_CONF_UPDATED, pid_to_procid(0), NULL, 0); do_sighup = False; } diff --git a/source3/nsswitch/winbindd.h b/source3/nsswitch/winbindd.h index 3a7728e4a2c..0db109dacde 100644 --- a/source3/nsswitch/winbindd.h +++ b/source3/nsswitch/winbindd.h @@ -47,6 +47,14 @@ struct fd_event { void *private_data; }; +struct sid_ctr { + DOM_SID *sid; + BOOL finished; + const char *domain; + const char *name; + enum SID_NAME_USE type; +}; + struct winbindd_cli_state { struct winbindd_cli_state *prev, *next; /* Linked list pointers */ int sock; /* Open socket from client */ @@ -122,12 +130,6 @@ struct winbindd_cm_conn { struct rpc_pipe_client *lsa_pipe; POLICY_HND lsa_policy; - /* Auth2 pipe is the pipe used to setup the netlogon schannel key - * using rpccli_net_auth2. It needs to be kept open. */ - - struct rpc_pipe_client *netlogon_auth2_pipe; - unsigned char sess_key[16]; /* Current session key. */ - DOM_CRED clnt_cred; /* Client NETLOGON credential. */ struct rpc_pipe_client *netlogon_pipe; }; @@ -305,8 +307,6 @@ struct winbindd_idmap_methods { #include "nsswitch/winbindd_proto.h" -#include "rpc_parse.h" - #define WINBINDD_ESTABLISH_LOOP 30 #define WINBINDD_RESCAN_FREQ 300 diff --git a/source3/nsswitch/winbindd_ads.c b/source3/nsswitch/winbindd_ads.c index eda6dea2c48..dfabccd4194 100644 --- a/source3/nsswitch/winbindd_ads.c +++ b/source3/nsswitch/winbindd_ads.c @@ -830,13 +830,7 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, *names = NULL; *dom_sids = NULL; - { - unsigned char *session_key; - DOM_CRED *creds; - - result = cm_connect_netlogon(domain, mem_ctx, &cli, - &session_key, &creds); - } + result = cm_connect_netlogon(domain, &cli); if (!NT_STATUS_IS_OK(result)) { DEBUG(5, ("trusted_domains: Could not open a connection to %s " @@ -845,11 +839,12 @@ static NTSTATUS trusted_domains(struct winbindd_domain *domain, return NT_STATUS_UNSUCCESSFUL; } - if ( NT_STATUS_IS_OK(result) ) + if ( NT_STATUS_IS_OK(result) ) { result = rpccli_ds_enum_domain_trusts(cli, mem_ctx, cli->cli->desthost, flags, &domains, (unsigned int *)&count); + } if ( NT_STATUS_IS_OK(result) && count) { diff --git a/source3/nsswitch/winbindd_async.c b/source3/nsswitch/winbindd_async.c index acae7e7f371..d43671380d0 100644 --- a/source3/nsswitch/winbindd_async.c +++ b/source3/nsswitch/winbindd_async.c @@ -84,12 +84,12 @@ static void do_async(TALLOC_CTX *mem_ctx, struct winbindd_child *child, &state->response, do_async_recv, state); } -static void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, - const struct winbindd_request *request, - void (*cont)(TALLOC_CTX *mem_ctx, BOOL success, - struct winbindd_response *response, - void *c, void *private_data), - void *c, void *private_data) +void do_async_domain(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, + const struct winbindd_request *request, + void (*cont)(TALLOC_CTX *mem_ctx, BOOL success, + struct winbindd_response *response, + void *c, void *private_data), + void *c, void *private_data) { struct do_async_state *state; @@ -706,16 +706,16 @@ enum winbindd_result winbindd_dual_lookupname(struct winbindd_domain *domain, return WINBINDD_OK; } -static BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids, - int num_sids, char **result) +BOOL print_sidlist(TALLOC_CTX *mem_ctx, const DOM_SID *sids, + int num_sids, char **result, ssize_t *len) { int i; size_t buflen = 0; - ssize_t len = 0; + *len = 0; *result = NULL; for (i=0; iname); - fstrcpy(request.data.dual_sidaliases.cache_key, keystr); + request.extra_len = len; + request.extra_data = sidstr; do_async_domain(mem_ctx, domain, &request, getsidaliases_recv, cont, private_data); @@ -838,20 +875,15 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain, { DOM_SID *sids = NULL; int num_sids = 0; - char *key = state->request.data.dual_sidaliases.cache_key; char *sidstr; + size_t len; int i, num_aliases; uint32 *alias_rids; NTSTATUS result; DEBUG(3, ("[%5lu]: getsidaliases\n", (unsigned long)state->pid)); - /* Ensure null termination */ - state->request.domain_name[sizeof(state->request.domain_name)-1]='\0'; - state->request.data.dual_sidaliases.cache_key - [sizeof(state->request.data.dual_sidaliases.cache_key)-1]='\0'; - - sidstr = cache_retrieve_request_data(state->mem_ctx, key); + sidstr = state->request.extra_data; if (sidstr == NULL) sidstr = talloc_strdup(state->mem_ctx, "\n"); /* No SID */ @@ -891,7 +923,7 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain, } if (!print_sidlist(NULL, sids, num_sids, - (char **)&state->response.extra_data)) { + (char **)&state->response.extra_data, &len)) { DEBUG(0, ("Could not print_sidlist\n")); return WINBINDD_ERROR; } @@ -899,7 +931,7 @@ enum winbindd_result winbindd_dual_getsidaliases(struct winbindd_domain *domain, if (state->response.extra_data != NULL) { DEBUG(10, ("aliases_list: %s\n", (char *)state->response.extra_data)); - state->response.length += strlen(state->response.extra_data)+1; + state->response.length += len+1; } return WINBINDD_OK; @@ -1405,3 +1437,4 @@ void query_user_async(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, do_async_domain(mem_ctx, domain, &request, query_user_recv, cont, private_data); } + diff --git a/source3/nsswitch/winbindd_cache.c b/source3/nsswitch/winbindd_cache.c index ce291a6c253..78b49d01eac 100644 --- a/source3/nsswitch/winbindd_cache.c +++ b/source3/nsswitch/winbindd_cache.c @@ -469,6 +469,7 @@ static struct cache_entry *wcache_fetch(struct winbind_cache *cache, centry->sequence_number = centry_uint32(centry); if (centry_expired(domain, kstr, centry)) { + DEBUG(10,("wcache_fetch: entry %s expired for domain %s\n", kstr, domain->name )); @@ -1048,7 +1049,6 @@ do_query: return status; } - /* Lookup user information from a rid */ static NTSTATUS query_user(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, @@ -1466,7 +1466,7 @@ void cache_store_response(pid_t pid, struct winbindd_response *response) /* There's extra data */ DEBUG(10, ("Storing extra data: len=%d\n", - response->length - sizeof(*response))); + (int)(response->length - sizeof(*response)))); fstr_sprintf(key_str, "DE/%d", pid); if (tdb_store(wcache->tdb, string_tdb_data(key_str), @@ -1514,7 +1514,7 @@ BOOL cache_retrieve_response(pid_t pid, struct winbindd_response * response) /* There's extra data */ DEBUG(10, ("Retrieving extra data length=%d\n", - response->length - sizeof(*response))); + (int)(response->length - sizeof(*response)))); fstr_sprintf(key_str, "DE/%d", pid); data = tdb_fetch(wcache->tdb, string_tdb_data(key_str)); @@ -1525,63 +1525,57 @@ BOOL cache_retrieve_response(pid_t pid, struct winbindd_response * response) } if (data.dsize != (response->length - sizeof(*response))) { - DEBUG(0, ("Invalid extra data length: %d\n", data.dsize)); + DEBUG(0, ("Invalid extra data length: %d\n", (int)data.dsize)); SAFE_FREE(data.dptr); return False; } + dump_data(11, data.dptr, data.dsize); + response->extra_data = data.dptr; return True; } -char *cache_store_request_data(TALLOC_CTX *mem_ctx, char *request_string) +BOOL lookup_cached_sid(TALLOC_CTX *mem_ctx, const DOM_SID *sid, + const char **domain_name, const char **name, + enum SID_NAME_USE *type) { - int i; - - if (!init_wcache()) - return NULL; + struct winbindd_domain *domain; + struct winbind_cache *cache; + struct cache_entry *centry = NULL; + NTSTATUS status; - for (i=0; i<2; i++) { - char *key = talloc_strdup(mem_ctx, generate_random_str(16)); - if (key == NULL) - return NULL; - DEBUG(10, ("Storing request key %s\n", key)); - if (tdb_store_bystring(wcache->tdb, key, - string_tdb_data(request_string), - TDB_INSERT) == 0) - return key; + domain = find_lookup_domain_from_sid(sid); + if (domain == NULL) { + return False; } - return NULL; -} -char *cache_retrieve_request_data(TALLOC_CTX *mem_ctx, char *key) -{ - TDB_DATA data; - char *result = NULL; + cache = get_cache(domain); - if (!init_wcache()) - return NULL; - - DEBUG(10, ("Retrieving key %s\n", key)); - - data = tdb_fetch_bystring(wcache->tdb, key); - if (data.dptr == NULL) - return NULL; - - if (strnlen(data.dptr, data.dsize) != (data.dsize)) { - DEBUG(0, ("Received invalid request string\n")); - goto done; + if (cache->tdb == NULL) { + return False; } - result = TALLOC_ARRAY(mem_ctx, char, data.dsize+1); - if (result != NULL) { - memcpy(result, data.dptr, data.dsize); - result[data.dsize] = '\0'; + + centry = wcache_fetch(cache, domain, "SN/%s", sid_string_static(sid)); + if (centry == NULL) { + return False; } - if (tdb_delete_bystring(wcache->tdb, key) != 0) { - DEBUG(0, ("Could not delete key %s\n", key)); - result = NULL; + + if (NT_STATUS_IS_OK(centry->status)) { + *type = (enum SID_NAME_USE)centry_uint32(centry); + *domain_name = centry_string(centry, mem_ctx); + *name = centry_string(centry, mem_ctx); } - done: - SAFE_FREE(data.dptr); - return result; + + 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) +{ + wcache_save_sid_to_name(domain, NT_STATUS_OK, sid, domain_name, + name, type); } diff --git a/source3/nsswitch/winbindd_cm.c b/source3/nsswitch/winbindd_cm.c index 14221483adc..c91f9555682 100644 --- a/source3/nsswitch/winbindd_cm.c +++ b/source3/nsswitch/winbindd_cm.c @@ -73,7 +73,7 @@ SAMR pipe as well for now. --jerry ******************************************************************/ -#define DISABLE_SCHANNEL_WIN2K3_SP1 1 +/* #define DISABLE_SCHANNEL_WIN2K3_SP1 1 */ /* Choose between anonymous or authenticated connections. We need to use @@ -113,8 +113,8 @@ static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain, fstring dcname, struct in_addr *dc_ip) { struct winbindd_domain *our_domain; + struct rpc_pipe_client *netlogon_pipe; NTSTATUS result; - struct rpc_pipe_client *cli; TALLOC_CTX *mem_ctx; fstring tmp; @@ -123,30 +123,26 @@ static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain, /* Hmmmm. We can only open one connection to the NETLOGON pipe at the * moment.... */ - if (IS_DC) + if (IS_DC) { return False; + } - if (domain->primary) + if (domain->primary) { return False; + } our_domain = find_our_domain(); - if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) + if ((mem_ctx = talloc_init("get_dc_name_via_netlogon")) == NULL) { return False; - - { - /* These var's can be ignored -- we're not requesting - anything in the credential chain here */ - unsigned char *session_key; - DOM_CRED *creds; - result = cm_connect_netlogon(our_domain, mem_ctx, &cli, - &session_key, &creds); } - if (!NT_STATUS_IS_OK(result)) + result = cm_connect_netlogon(our_domain, &netlogon_pipe); + if (!NT_STATUS_IS_OK(result)) { return False; + } - result = rpccli_netlogon_getdcname(cli, mem_ctx, domain->dcname, + result = rpccli_netlogon_getdcname(netlogon_pipe, mem_ctx, domain->dcname, domain->name, tmp); talloc_destroy(mem_ctx); @@ -156,13 +152,18 @@ static BOOL get_dc_name_via_netlogon(const struct winbindd_domain *domain, /* cli_netlogon_getdcname gives us a name with \\ */ p = tmp; - if (*p == '\\') p+=1; - if (*p == '\\') p+=1; + if (*p == '\\') { + p+=1; + } + if (*p == '\\') { + p+=1; + } fstrcpy(dcname, p); - if (!resolve_name(dcname, dc_ip, 0x20)) + if (!resolve_name(dcname, dc_ip, 0x20)) { return False; + } return True; } @@ -178,7 +179,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, struct cli_state **cli, BOOL *retry) { - char *machine_password, *machine_krb5_principal; + char *machine_password, *machine_krb5_principal, *machine_account; char *ipc_username, *ipc_domain, *ipc_password; BOOL got_mutex; @@ -194,8 +195,14 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, machine_password = secrets_fetch_machine_password(lp_workgroup(), NULL, NULL); + if (asprintf(&machine_account, "%s$", global_myname()) == -1) { + SAFE_FREE(machine_password); + return NT_STATUS_NO_MEMORY; + } + if (asprintf(&machine_krb5_principal, "%s$@%s", global_myname(), lp_realm()) == -1) { + SAFE_FREE(machine_account); SAFE_FREE(machine_password); return NT_STATUS_NO_MEMORY; } @@ -257,33 +264,61 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, goto done; } - /* Krb5 session */ - if ((lp_security() == SEC_ADS) - && ((*cli)->protocol >= PROTOCOL_NT1 && - (*cli)->capabilities & CAP_EXTENDED_SECURITY)) { - + if ((*cli)->protocol >= PROTOCOL_NT1 && (*cli)->capabilities & CAP_EXTENDED_SECURITY) { ADS_STATUS ads_status; - (*cli)->use_kerberos = True; - DEBUG(5, ("connecting to %s from %s with kerberos principal " - "[%s]\n", controller, global_myname(), - machine_krb5_principal)); + + if (lp_security() == SEC_ADS) { + + /* Try a krb5 session */ + + (*cli)->use_kerberos = True; + DEBUG(5, ("connecting to %s from %s with kerberos principal " + "[%s]\n", controller, global_myname(), + machine_krb5_principal)); + + ads_status = cli_session_setup_spnego(*cli, + machine_krb5_principal, + machine_password, + lp_workgroup()); + + if (!ADS_ERR_OK(ads_status)) { + DEBUG(4,("failed kerberos session setup with %s\n", + ads_errstr(ads_status))); + } + + result = ads_ntstatus(ads_status); + if (NT_STATUS_IS_OK(result)) { + /* Ensure creds are stored for NTLMSSP authenticated pipe access. */ + cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password); + goto session_setup_done; + } + } + + /* Fall back to non-kerberos session setup using NTLMSSP SPNEGO with the machine account. */ + (*cli)->use_kerberos = False; + + DEBUG(5, ("connecting to %s from %s with username " + "[%s]\\[%s]\n", controller, global_myname(), + machine_account, machine_password)); ads_status = cli_session_setup_spnego(*cli, - machine_krb5_principal, + machine_account, machine_password, lp_workgroup()); - - if (!ADS_ERR_OK(ads_status)) - DEBUG(4,("failed kerberos session setup with %s\n", - ads_errstr(ads_status))); + if (!ADS_ERR_OK(ads_status)) { + DEBUG(4, ("authenticated session setup failed with %s\n", + ads_errstr(ads_status))); + } result = ads_ntstatus(ads_status); + if (NT_STATUS_IS_OK(result)) { + /* Ensure creds are stored for NTLMSSP authenticated pipe access. */ + cli_init_creds(*cli, machine_account, lp_workgroup(), machine_password); + goto session_setup_done; + } } - if (NT_STATUS_IS_OK(result)) - goto session_setup_done; - /* Fall back to non-kerberos session setup */ (*cli)->use_kerberos = False; @@ -301,8 +336,12 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, ipc_password, strlen(ipc_password)+1, ipc_password, strlen(ipc_password)+1, ipc_domain)) { - DEBUG(5, ("authenticated session setup failed\n")); + /* Successful logon with given username. */ + cli_init_creds(*cli, ipc_username, ipc_domain, ipc_password); goto session_setup_done; + } else { + DEBUG(4, ("authenticated session setup with user %s\\%s failed.\n", + ipc_domain, ipc_username )); } } @@ -310,6 +349,7 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, if (cli_session_setup(*cli, "", NULL, 0, NULL, 0, "")) { DEBUG(5, ("Connected anonymously\n")); + cli_init_creds(*cli, "", "", ""); goto session_setup_done; } @@ -342,26 +382,28 @@ static NTSTATUS cm_prepare_connection(const struct winbindd_domain *domain, *retry = False; /* set the domain if empty; needed for schannel connections */ - if ( !*(*cli)->domain ) + if ( !*(*cli)->domain ) { fstrcpy( (*cli)->domain, domain->name ); - - (*cli)->pipe_auth_flags = 0; + } result = NT_STATUS_OK; add_failed_connection = False; done: - if (got_mutex) + if (got_mutex) { secrets_named_mutex_release(controller); + } + SAFE_FREE(machine_account); SAFE_FREE(machine_password); SAFE_FREE(machine_krb5_principal); SAFE_FREE(ipc_username); SAFE_FREE(ipc_domain); SAFE_FREE(ipc_password); - if (add_failed_connection) + if (add_failed_connection) { add_failed_connection_entry(domain->name, controller, result); + } return result; } @@ -721,7 +763,7 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, for (retries = 0; retries < 3; retries++) { int fd = -1; - BOOL retry; + BOOL retry = False; result = NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND; @@ -758,27 +800,23 @@ static NTSTATUS cm_open_connection(struct winbindd_domain *domain, void invalidate_cm_connection(struct winbindd_cm_conn *conn) { if (conn->samr_pipe != NULL) { - cli_rpc_close(conn->samr_pipe); + cli_rpc_pipe_close(conn->samr_pipe); conn->samr_pipe = NULL; } if (conn->lsa_pipe != NULL) { - cli_rpc_close(conn->lsa_pipe); + cli_rpc_pipe_close(conn->lsa_pipe); conn->lsa_pipe = NULL; } - if (conn->netlogon_auth2_pipe != NULL) { - cli_rpc_close(conn->netlogon_auth2_pipe); - conn->netlogon_auth2_pipe = NULL; - } - if (conn->netlogon_pipe != NULL) { - cli_rpc_close(conn->netlogon_pipe); + cli_rpc_pipe_close(conn->netlogon_pipe); conn->netlogon_pipe = NULL; } - if (conn->cli) + if (conn->cli) { cli_shutdown(conn->cli); + } conn->cli = NULL; } @@ -872,7 +910,7 @@ void set_dc_type_and_flags( struct winbindd_domain *domain ) return; } - cli = cli_rpc_open_noauth(domain->conn.cli, PI_LSARPC_DS); + cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC_DS, &result); if (cli == NULL) { DEBUG(5, ("set_dc_type_and_flags: Could not bind to " @@ -885,7 +923,7 @@ void set_dc_type_and_flags( struct winbindd_domain *domain ) result = rpccli_ds_getprimarydominfo(cli, cli->cli->mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr); - cli_rpc_close(cli); + cli_rpc_pipe_close(cli); if (!NT_STATUS_IS_OK(result)) { domain->initialized = True; @@ -896,7 +934,7 @@ void set_dc_type_and_flags( struct winbindd_domain *domain ) !(ctr.basic->flags & DSROLE_PRIMARY_DS_MIXED_MODE) ) domain->native_mode = True; - cli = cli_rpc_open_noauth(domain->conn.cli, PI_LSARPC); + cli = cli_rpc_pipe_open_noauth(domain->conn.cli, PI_LSARPC, &result); if (cli == NULL) { domain->initialized = True; @@ -907,6 +945,7 @@ void set_dc_type_and_flags( struct winbindd_domain *domain ) domain->name); if (!mem_ctx) { DEBUG(1, ("set_dc_type_and_flags: talloc_init() failed\n")); + cli_rpc_pipe_close(cli); return; } @@ -956,7 +995,7 @@ void set_dc_type_and_flags( struct winbindd_domain *domain ) } done: - cli_rpc_close(cli); + cli_rpc_pipe_close(cli); talloc_destroy(mem_ctx); @@ -965,20 +1004,28 @@ done: return; } -static BOOL cm_get_schannel_key(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - unsigned char **session_key) +#ifndef DISABLE_SCHANNEL_WIN2K3_SP1 +static BOOL cm_get_schannel_dcinfo(struct winbindd_domain *domain, struct dcinfo **ppdc) { - struct rpc_pipe_client *cli; - DOM_CRED *credentials; + NTSTATUS result; + struct rpc_pipe_client *netlogon_pipe; - if (lp_client_schannel() == False) + if (lp_client_schannel() == False) { return False; + } - return NT_STATUS_IS_OK(cm_connect_netlogon(domain, mem_ctx, - &cli, session_key, - &credentials)); + result = cm_connect_netlogon(domain, &netlogon_pipe); + if (!NT_STATUS_IS_OK(result)) { + return False; + } + + /* Return a pointer to the struct dcinfo from the + netlogon pipe. */ + + *ppdc = domain->conn.netlogon_pipe->dc; + return True; } +#endif NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, struct rpc_pipe_client **cli, POLICY_HND *sam_handle) @@ -987,24 +1034,85 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, NTSTATUS result; result = init_dc_connection(domain); - if (!NT_STATUS_IS_OK(result)) + if (!NT_STATUS_IS_OK(result)) { return result; + } conn = &domain->conn; if (conn->samr_pipe == NULL) { + /* + * No SAMR pipe yet. Attempt to get an NTLMSSP SPNEGO + * authenticated sign and sealed pipe using the machine + * account password by preference. If we can't - try schannel, + * if that fails, try anonymous. + */ + + fstring conn_pwd; + pwd_get_cleartext(&conn->cli->pwd, conn_pwd); + if (conn->cli->user_name[0] && conn->cli->domain[0] && + conn_pwd[0]) { + /* We have an authenticated connection. Use + a NTLMSSP SPNEGO authenticated SAMR pipe with + sign & seal. */ + conn->samr_pipe = + cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, + PI_SAMR, + PIPE_AUTH_LEVEL_PRIVACY, + conn->cli->domain, + conn->cli->user_name, + conn_pwd, + &result); + if (conn->samr_pipe == NULL) { + DEBUG(10,("cm_connect_sam: failed to connect " + "to SAMR pipe for domain %s using " + "NTLMSSP authenticated pipe: user " + "%s\\%s. Error was %s\n", + domain->name, conn->cli->domain, + conn->cli->user_name, + nt_errstr(result))); + } else { + DEBUG(10,("cm_connect_sam: connected to SAMR " + "pipe for domain %s using NTLMSSP " + "authenticated pipe: user %s\\%s\n", + domain->name, conn->cli->domain, + conn->cli->user_name )); + } + } + #ifndef DISABLE_SCHANNEL_WIN2K3_SP1 - unsigned char *session_key; - - if (cm_get_schannel_key(domain, mem_ctx, &session_key)) - conn->samr_pipe = cli_rpc_open_schannel(conn->cli, - PI_SAMR, - session_key, - domain->name); - else + /* Fall back to schannel if it's a W2K pre-SP1 box. */ + if (conn->samr_pipe == NULL) { + struct dcinfo *p_dcinfo; + + if (cm_get_schannel_dcinfo(domain, &p_dcinfo)) { + conn->samr_pipe = + cli_rpc_pipe_open_schannel_with_key(conn->cli, + PI_SAMR, + PIPE_AUTH_LEVEL_PRIVACY, + domain->name, + p_dcinfo, + &result); + } + if (conn->samr_pipe == NULL) { + DEBUG(10,("cm_connect_sam: failed to connect " + "to SAMR pipe for domain %s using " + "schannel authenticated. Error " + "was %s\n", domain->name, + nt_errstr(result) )); + } else { + DEBUG(10,("cm_connect_sam: connected to SAMR " + "pipe for domain %s using schannel.\n", + domain->name )); + } + } #endif /* DISABLE_SCHANNEL_WIN2K3_SP1 */ - conn->samr_pipe = cli_rpc_open_noauth(conn->cli, - PI_SAMR); + + /* Finally fall back to anonymous. */ + if (conn->samr_pipe == NULL) { + conn->samr_pipe = + cli_rpc_pipe_open_noauth(conn->cli, PI_SAMR, &result); + } if (conn->samr_pipe == NULL) { result = NT_STATUS_PIPE_NOT_AVAILABLE; @@ -1014,8 +1122,12 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, result = rpccli_samr_connect(conn->samr_pipe, mem_ctx, SEC_RIGHTS_MAXIMUM_ALLOWED, &conn->sam_connect_handle); - if (!NT_STATUS_IS_OK(result)) + if (!NT_STATUS_IS_OK(result)) { + DEBUG(10,("cm_connect_sam: rpccli_samr_connect failed " + "for domain %s Error was %s\n", + domain->name, nt_errstr(result) )); goto done; + } result = rpccli_samr_open_domain(conn->samr_pipe, mem_ctx, @@ -1026,9 +1138,10 @@ NTSTATUS cm_connect_sam(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, } done: + if (!NT_STATUS_IS_OK(result)) { invalidate_cm_connection(conn); - return NT_STATUS_UNSUCCESSFUL; + return result; } *cli = conn->samr_pipe; @@ -1049,18 +1162,72 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, conn = &domain->conn; if (conn->lsa_pipe == NULL) { + fstring conn_pwd; + pwd_get_cleartext(&conn->cli->pwd, conn_pwd); + if (conn->cli->user_name[0] && conn->cli->domain[0] && + conn_pwd[0]) { + /* We have an authenticated connection. Use + a NTLMSSP SPNEGO authenticated LSA pipe with + sign & seal. */ + conn->lsa_pipe = + cli_rpc_pipe_open_spnego_ntlmssp(conn->cli, + PI_LSARPC, + PIPE_AUTH_LEVEL_PRIVACY, + conn->cli->domain, + conn->cli->user_name, + conn_pwd, + &result); + if (conn->lsa_pipe == NULL) { + DEBUG(10,("cm_connect_lsa: failed to connect " + "to LSA pipe for domain %s using " + "NTLMSSP authenticated pipe: user " + "%s\\%s. Error was %s\n", + domain->name, conn->cli->domain, + conn->cli->user_name, + nt_errstr(result))); + } else { + DEBUG(10,("cm_connect_lsa: connected to LSA " + "pipe for domain %s using NTLMSSP " + "authenticated pipe: user %s\\%s\n", + domain->name, conn->cli->domain, + conn->cli->user_name )); + } + } + #ifndef DISABLE_SCHANNEL_WIN2K3_SP1 - unsigned char *session_key; - - if (cm_get_schannel_key(domain, mem_ctx, &session_key)) - conn->lsa_pipe = cli_rpc_open_schannel(conn->cli, - PI_LSARPC, - session_key, - domain->name); - else + /* Fall back to schannel if it's a W2K pre-SP1 box. */ + if (conn->lsa_pipe == NULL) { + struct dcinfo *p_dcinfo; + + if (cm_get_schannel_dcinfo(domain, &p_dcinfo)) { + conn->lsa_pipe = + cli_rpc_pipe_open_schannel_with_key(conn->cli, + PI_LSARPC, + PIPE_AUTH_LEVEL_PRIVACY, + domain->name, + p_dcinfo, + &result); + } + if (conn->lsa_pipe == NULL) { + DEBUG(10,("cm_connect_lsa: failed to connect " + "to LSA pipe for domain %s using " + "schannel authenticated. Error " + "was %s\n", domain->name, + nt_errstr(result) )); + } else { + DEBUG(10,("cm_connect_lsa: connected to LSA " + "pipe for domain %s using schannel.\n", + domain->name )); + } + } #endif /* DISABLE_SCHANNEL_WIN2K3_SP1 */ - conn->lsa_pipe = cli_rpc_open_noauth(conn->cli, - PI_LSARPC); + + /* Finally fall back to anonymous. */ + if (conn->lsa_pipe == NULL) { + conn->lsa_pipe = cli_rpc_pipe_open_noauth(conn->cli, + PI_LSARPC, + &result); + } if (conn->lsa_pipe == NULL) { result = NT_STATUS_PIPE_NOT_AVAILABLE; @@ -1083,55 +1250,12 @@ NTSTATUS cm_connect_lsa(struct winbindd_domain *domain, TALLOC_CTX *mem_ctx, return result; } -/******************************************************************* - wrapper around retrieving the trust account password -*******************************************************************/ +/**************************************************************************** + Open the netlogon pipe to this DC. Use schannel if specified in client conf. + session key stored in conn->netlogon_pipe->dc->sess_key. +****************************************************************************/ -static BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16], - uint32 *channel) -{ - DOM_SID sid; - char *pwd; - time_t last_set_time; - - /* if we are a DC and this is not our domain, then lookup an account - for the domain trust */ - - if ( IS_DC && !strequal(domain, lp_workgroup()) && - lp_allow_trusted_domains() ) { - - if (!secrets_fetch_trusted_domain_password(domain, &pwd, &sid, - &last_set_time)) { - DEBUG(0, ("get_trust_pw: could not fetch trust " - "account password for trusted domain %s\n", - domain)); - return False; - } - - *channel = SEC_CHAN_DOMAIN; - E_md4hash(pwd, ret_pwd); - SAFE_FREE(pwd); - - return True; - } - - /* Just get the account for the requested domain. In the future this - * might also cover to be member of more than one domain. */ - - if (secrets_fetch_trust_account_password(domain, ret_pwd, - &last_set_time, channel)) - return True; - - DEBUG(5, ("get_trust_pw: could not fetch trust account " - "password for domain %s\n", domain)); - return False; -} - -NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, - TALLOC_CTX *mem_ctx, - struct rpc_pipe_client **cli, - unsigned char **session_key, - DOM_CRED **credentials) +NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, struct rpc_pipe_client **cli) { struct winbindd_cm_conn *conn; NTSTATUS result; @@ -1139,119 +1263,100 @@ NTSTATUS cm_connect_netlogon(struct winbindd_domain *domain, uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; uint8 mach_pwd[16]; uint32 sec_chan_type; - DOM_CHAL clnt_chal, srv_chal, rcv_chal; - const char *server_name; const char *account_name; - UTIME zerotime; + struct rpc_pipe_client *netlogon_pipe; result = init_dc_connection(domain); - if (!NT_STATUS_IS_OK(result)) + if (!NT_STATUS_IS_OK(result)) { return result; + } conn = &domain->conn; if (conn->netlogon_pipe != NULL) { *cli = conn->netlogon_pipe; - *session_key = (unsigned char *)&conn->sess_key; - *credentials = &conn->clnt_cred; return NT_STATUS_OK; } - if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) + if (!get_trust_pw(domain->name, mach_pwd, &sec_chan_type)) { return NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + } - conn->netlogon_auth2_pipe = cli_rpc_open_noauth(conn->cli, - PI_NETLOGON); - if (conn->netlogon_auth2_pipe == NULL) - return NT_STATUS_UNSUCCESSFUL; + netlogon_pipe = cli_rpc_pipe_open_noauth(conn->cli, PI_NETLOGON, &result); + if (netlogon_pipe == NULL) { + return result; + } - if (lp_client_schannel() != False) + if (lp_client_schannel() != False) { neg_flags |= NETLOGON_NEG_SCHANNEL; - - generate_random_buffer(clnt_chal.data, 8); - - server_name = talloc_asprintf(mem_ctx, "\\\\%s", domain->dcname); + } /* if we are a DC and this is a trusted domain, then we need to use our domain name in the net_req_auth2() request */ - if ( IS_DC + if ( IS_DC && !strequal(domain->name, lp_workgroup()) && lp_allow_trusted_domains() ) { - account_name = talloc_asprintf( mem_ctx, "%s$", lp_workgroup() ); - } - else { - account_name = talloc_asprintf(mem_ctx, "%s$", - domain->primary ? global_myname() : domain->name); + account_name = lp_workgroup(); + } else { + account_name = domain->primary ? global_myname() : domain->name; } - if ((server_name == NULL) || (account_name == NULL)) + if (account_name == NULL) { + cli_rpc_pipe_close(netlogon_pipe); return NT_STATUS_NO_MEMORY; + } - result = rpccli_net_req_chal(conn->netlogon_auth2_pipe, server_name, - global_myname(), &clnt_chal, &srv_chal); - if (!NT_STATUS_IS_OK(result)) - return result; - - /**************** Long-term Session key **************/ - - /* calculate the session key */ - cred_session_key(&clnt_chal, &srv_chal, mach_pwd, conn->sess_key); - memset((char *)conn->sess_key+8, '\0', 8); - - /* calculate auth2 credentials */ - zerotime.time = 0; - cred_create(conn->sess_key, &clnt_chal, zerotime, - &conn->clnt_cred.challenge); - - result = rpccli_net_auth2(conn->netlogon_auth2_pipe, server_name, - account_name, sec_chan_type, global_myname(), - &conn->clnt_cred.challenge, &neg_flags, - &rcv_chal); + result = rpccli_netlogon_setup_creds(netlogon_pipe, + domain->dcname, /* server name. */ + domain->name, /* domain name */ + account_name, /* machine account */ + mach_pwd, /* machine password */ + sec_chan_type, /* from get_trust_pw */ + &neg_flags); - if (!NT_STATUS_IS_OK(result)) + if (!NT_STATUS_IS_OK(result)) { + cli_rpc_pipe_close(netlogon_pipe); return result; - - zerotime.time = 0; - if (!cred_assert(&rcv_chal, conn->sess_key, &srv_chal, zerotime)) { - DEBUG(0, ("Server replied with bad credential\n")); - return NT_STATUS_ACCESS_DENIED; } if ((lp_client_schannel() == True) && - ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { + ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { DEBUG(3, ("Server did not offer schannel\n")); - cli_rpc_close(conn->netlogon_auth2_pipe); - conn->netlogon_auth2_pipe = NULL; + cli_rpc_pipe_close(netlogon_pipe); return NT_STATUS_ACCESS_DENIED; } if ((lp_client_schannel() == False) || - ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { - /* keep the existing connection to NETLOGON open */ - conn->netlogon_pipe = conn->netlogon_auth2_pipe; - conn->netlogon_auth2_pipe = NULL; + ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { + /* We're done - just keep the existing connection to NETLOGON open */ + conn->netlogon_pipe = netlogon_pipe; *cli = conn->netlogon_pipe; - *session_key = (unsigned char *)&conn->sess_key; - *credentials = &conn->clnt_cred; return NT_STATUS_OK; } - conn->netlogon_pipe = cli_rpc_open_schannel(conn->cli, PI_NETLOGON, - conn->sess_key, - domain->name); + /* Using the credentials from the first pipe, open a signed and sealed + second netlogon pipe. The session key is stored in the schannel + part of the new pipe auth struct. + */ + + conn->netlogon_pipe = cli_rpc_pipe_open_schannel_with_key(conn->cli, + PI_NETLOGON, + PIPE_AUTH_LEVEL_PRIVACY, + domain->name, + netlogon_pipe->dc, + &result); + + /* We can now close the initial netlogon pipe. */ + cli_rpc_pipe_close(netlogon_pipe); if (conn->netlogon_pipe == NULL) { - DEBUG(3, ("Could not open schannel'ed NETLOGON pipe\n")); - cli_rpc_close(conn->netlogon_auth2_pipe); - conn->netlogon_auth2_pipe = NULL; - return NT_STATUS_ACCESS_DENIED; + DEBUG(3, ("Could not open schannel'ed NETLOGON pipe. Error was %s\n", + nt_errstr(result))); + return result; } *cli = conn->netlogon_pipe; - *session_key = (unsigned char *)&conn->sess_key; - *credentials = &conn->clnt_cred; - return NT_STATUS_OK; } diff --git a/source3/nsswitch/winbindd_dual.c b/source3/nsswitch/winbindd_dual.c index ec0b7a36e2f..60b74114172 100644 --- a/source3/nsswitch/winbindd_dual.c +++ b/source3/nsswitch/winbindd_dual.c @@ -38,35 +38,48 @@ /* Read some data from a client connection */ -static void dual_client_read(struct winbindd_cli_state *state) +static void child_read_request(struct winbindd_cli_state *state) { - int n; - + ssize_t len; + /* Read data */ - n = sys_read(state->sock, state->read_buf_len + - (char *)&state->request, - sizeof(state->request) - state->read_buf_len); - - DEBUG(10,("client_read: read %d bytes. Need %ld more for a full " - "request.\n", n, (unsigned long)(sizeof(state->request) - n - - state->read_buf_len) )); + len = read_data(state->sock, (char *)&state->request, + sizeof(state->request)); - /* Read failed, kill client */ - - if (n == -1 || n == 0) { - DEBUG(5,("read failed on sock %d, pid %lu: %s\n", - state->sock, (unsigned long)state->pid, - (n == -1) ? strerror(errno) : "EOF")); - + if (len != sizeof(state->request)) { + DEBUG(0, ("Got invalid request length: %d\n", (int)len)); + state->finished = True; + return; + } + + if (state->request.extra_len == 0) { + state->request.extra_data = NULL; + return; + } + + DEBUG(10, ("Need to read %d extra bytes\n", (int)state->request.extra_len)); + + state->request.extra_data = + SMB_MALLOC_ARRAY(char, state->request.extra_len + 1); + + if (state->request.extra_data == NULL) { + DEBUG(0, ("malloc failed\n")); + state->finished = True; + return; + } + + /* Ensure null termination */ + state->request.extra_data[state->request.extra_len] = '\0'; + + len = read_data(state->sock, state->request.extra_data, + state->request.extra_len); + + if (len != state->request.extra_len) { + DEBUG(0, ("Could not read extra data\n")); state->finished = True; return; } - - /* Update client state */ - - state->read_buf_len += n; - state->last_access = time(NULL); } /* @@ -86,6 +99,7 @@ struct winbindd_async_request { void *private_data; }; +static void async_main_request_sent(void *private_data, BOOL success); static void async_request_sent(void *private_data, BOOL success); static void async_reply_recv(void *private_data, BOOL success); static void schedule_async_request(struct winbindd_child *child); @@ -122,7 +136,7 @@ void async_request(TALLOC_CTX *mem_ctx, struct winbindd_child *child, return; } -static void async_request_sent(void *private_data, BOOL success) +static void async_main_request_sent(void *private_data, BOOL success) { struct winbindd_async_request *state = talloc_get_type_abort(private_data, struct winbindd_async_request); @@ -136,6 +150,30 @@ static void async_request_sent(void *private_data, BOOL success) return; } + if (state->request->extra_len == 0) { + async_request_sent(private_data, True); + return; + } + + setup_async_write(&state->child->event, state->request->extra_data, + state->request->extra_len, + async_request_sent, state); +} + +static void async_request_sent(void *private_data_data, BOOL success) +{ + struct winbindd_async_request *state = + talloc_get_type_abort(private_data_data, struct winbindd_async_request); + + if (!success) { + DEBUG(5, ("Could not send async request\n")); + + state->response->length = sizeof(struct winbindd_response); + state->response->result = WINBINDD_ERROR; + state->continuation(state->private_data, False); + return; + } + /* Request successfully sent to the child, setup the wait for reply */ setup_async_read(&state->child->event, @@ -196,7 +234,7 @@ static void schedule_async_request(struct winbindd_child *child) setup_async_write(&child->event, request->request, sizeof(*request->request), - async_request_sent, request); + async_main_request_sent, request); return; } @@ -205,31 +243,31 @@ struct domain_request_state { struct winbindd_domain *domain; struct winbindd_request *request; struct winbindd_response *response; - void (*continuation)(void *private_data, BOOL success); - void *private_data; + void (*continuation)(void *private_data_data, BOOL success); + void *private_data_data; }; -static void domain_init_recv(void *private_data, BOOL success); +static void domain_init_recv(void *private_data_data, BOOL success); void async_domain_request(TALLOC_CTX *mem_ctx, struct winbindd_domain *domain, struct winbindd_request *request, struct winbindd_response *response, - void (*continuation)(void *private_data, BOOL success), - void *private_data) + void (*continuation)(void *private_data_data, BOOL success), + void *private_data_data) { struct domain_request_state *state; if (domain->initialized) { async_request(mem_ctx, &domain->child, request, response, - continuation, private_data); + continuation, private_data_data); return; } state = TALLOC_P(mem_ctx, struct domain_request_state); if (state == NULL) { DEBUG(0, ("talloc failed\n")); - continuation(private_data, False); + continuation(private_data_data, False); return; } @@ -238,15 +276,15 @@ void async_domain_request(TALLOC_CTX *mem_ctx, state->request = request; state->response = response; state->continuation = continuation; - state->private_data = private_data; + state->private_data_data = private_data_data; init_child_connection(domain, domain_init_recv, state); } -static void recvfrom_child(void *private_data, BOOL success) +static void recvfrom_child(void *private_data_data, BOOL success) { struct winbindd_cli_state *state = - talloc_get_type_abort(private_data, struct winbindd_cli_state); + talloc_get_type_abort(private_data_data, struct winbindd_cli_state); enum winbindd_result result = state->response.result; /* This is an optimization: The child has written directly to the @@ -278,20 +316,20 @@ void sendto_domain(struct winbindd_cli_state *state, recvfrom_child, state); } -static void domain_init_recv(void *private_data, BOOL success) +static void domain_init_recv(void *private_data_data, BOOL success) { struct domain_request_state *state = - talloc_get_type_abort(private_data, struct domain_request_state); + talloc_get_type_abort(private_data_data, struct domain_request_state); if (!success) { DEBUG(5, ("Domain init returned an error\n")); - state->continuation(state->private_data, False); + state->continuation(state->private_data_data, False); return; } async_request(state->mem_ctx, &state->domain->child, state->request, state->response, - state->continuation, state->private_data); + state->continuation, state->private_data_data); } struct winbindd_child_dispatch_table { @@ -466,39 +504,34 @@ static BOOL fork_domain_child(struct winbindd_child *child) main_loop_talloc_free(); /* fetch a request from the main daemon */ - dual_client_read(&state); + child_read_request(&state); if (state.finished) { /* we lost contact with our parent */ exit(0); } - /* process full rquests */ - if (state.read_buf_len == sizeof(state.request)) { - DEBUG(4,("child daemon request %d\n", - (int)state.request.cmd)); + DEBUG(4,("child daemon request %d\n", (int)state.request.cmd)); - ZERO_STRUCT(state.response); - state.request.null_term = '\0'; - child_process_request(child->domain, &state); + ZERO_STRUCT(state.response); + state.request.null_term = '\0'; + child_process_request(child->domain, &state); - cache_store_response(sys_getpid(), &state.response); + SAFE_FREE(state.request.extra_data); - SAFE_FREE(state.response.extra_data); + cache_store_response(sys_getpid(), &state.response); - /* We just send the result code back, the result - * structure needs to be fetched via the - * winbindd_cache. Hmm. That needs fixing... */ + SAFE_FREE(state.response.extra_data); - if (write_data(state.sock, - (void *)&state.response.result, - sizeof(state.response.result)) != - sizeof(state.response.result)) { - DEBUG(0, ("Could not write result\n")); - exit(1); - } + /* We just send the result code back, the result + * structure needs to be fetched via the + * winbindd_cache. Hmm. That needs fixing... */ - state.read_buf_len = 0; + if (write_data(state.sock, (void *)&state.response.result, + sizeof(state.response.result)) != + sizeof(state.response.result)) { + DEBUG(0, ("Could not write result\n")); + exit(1); } } } diff --git a/source3/nsswitch/winbindd_group.c b/source3/nsswitch/winbindd_group.c index 6261dfb6165..c52ee2d960c 100644 --- a/source3/nsswitch/winbindd_group.c +++ b/source3/nsswitch/winbindd_group.c @@ -1150,10 +1150,10 @@ enum winbindd_result winbindd_dual_getuserdomgroups(struct winbindd_domain *doma DOM_SID user_sid; NTSTATUS status; - int i, num_groups; - size_t bufsize; - ssize_t len; + char *sidstring; + size_t len; DOM_SID *groups; + int num_groups; /* Ensure null termination */ state->request.data.sid[sizeof(state->request.data.sid)-1]='\0'; @@ -1176,22 +1176,15 @@ enum winbindd_result winbindd_dual_getuserdomgroups(struct winbindd_domain *doma return WINBINDD_OK; } - len=bufsize=0; - state->response.extra_data = NULL; - - for (i=0; iresponse.extra_data, - &len, &bufsize, - "%s\n", sid_string_static(&groups[i])); - } - - if (state->response.extra_data == NULL) { - /* Hmmm. Allocation failed somewhere */ + if (!print_sidlist(NULL, groups, num_groups, &sidstring, &len)) { + DEBUG(0, ("malloc failed\n")); return WINBINDD_ERROR; } - state->response.data.num_entries = num_groups; + state->response.extra_data = sidstring; state->response.length += len+1; + state->response.data.num_entries = num_groups; return WINBINDD_OK; } + diff --git a/source3/nsswitch/winbindd_misc.c b/source3/nsswitch/winbindd_misc.c index 6f72a0e2c63..83c4c0f6ee5 100644 --- a/source3/nsswitch/winbindd_misc.c +++ b/source3/nsswitch/winbindd_misc.c @@ -58,12 +58,8 @@ enum winbindd_result winbindd_dual_check_machine_acct(struct winbindd_domain *do invalidate_cm_connection(&contact_domain->conn); { - struct rpc_pipe_client *cli; - unsigned char *session_key; - DOM_CRED *creds; - - result = cm_connect_netlogon(contact_domain, state->mem_ctx, - &cli, &session_key, &creds); + struct rpc_pipe_client *netlogon_pipe; + result = cm_connect_netlogon(contact_domain, &netlogon_pipe); } if (!NT_STATUS_IS_OK(result)) { @@ -169,7 +165,7 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, { fstring dcname_slash; char *p; - struct rpc_pipe_client *cli; + struct rpc_pipe_client *netlogon_pipe; NTSTATUS result; state->request.domain_name @@ -178,21 +174,14 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, DEBUG(3, ("[%5lu]: Get DC name for %s\n", (unsigned long)state->pid, state->request.domain_name)); - { - /* These var's can be ignored -- we're not requesting - anything in the credential chain here */ - unsigned char *session_key; - DOM_CRED *creds; - result = cm_connect_netlogon(domain, state->mem_ctx, &cli, - &session_key, &creds); - } + result = cm_connect_netlogon(domain, &netlogon_pipe); if (!NT_STATUS_IS_OK(result)) { DEBUG(1, ("Can't contact our the NETLOGON pipe\n")); return WINBINDD_ERROR; } - result = rpccli_netlogon_getdcname(cli, state->mem_ctx, domain->dcname, + result = rpccli_netlogon_getdcname(netlogon_pipe, state->mem_ctx, domain->dcname, state->request.domain_name, dcname_slash); @@ -202,11 +191,14 @@ enum winbindd_result winbindd_dual_getdcname(struct winbindd_domain *domain, } p = dcname_slash; - if (*p == '\\') p+=1; - if (*p == '\\') p+=1; + if (*p == '\\') { + p+=1; + } + if (*p == '\\') { + p+=1; + } fstrcpy(state->response.data.dc_name, p); - return WINBINDD_OK; } diff --git a/source3/nsswitch/winbindd_nss.h b/source3/nsswitch/winbindd_nss.h index d012811d379..c1bb4b2600a 100644 --- a/source3/nsswitch/winbindd_nss.h +++ b/source3/nsswitch/winbindd_nss.h @@ -175,6 +175,8 @@ typedef struct winbindd_gr { /* Flag to say this is a winbindd internal send - don't recurse. */ #define WBFLAG_RECURSE 0x0800 +#define WINBINDD_MAX_EXTRA_DATA (128*1024) + /* Winbind request structure */ struct winbindd_request { @@ -183,7 +185,6 @@ struct winbindd_request { pid_t pid; /* pid of calling process */ uint32 flags; /* flags relavant to a given request */ fstring domain_name; /* name of domain for which the request applies */ - int msgid; union { fstring winsreq; /* WINS request */ @@ -240,10 +241,9 @@ struct winbindd_request { gid_t gid; fstring sid; } dual_idmapset; - struct { - fstring cache_key; - } dual_sidaliases; } data; + char *extra_data; + size_t extra_len; char null_term; }; diff --git a/source3/nsswitch/winbindd_pam.c b/source3/nsswitch/winbindd_pam.c index a0712144eeb..c2324291a63 100644 --- a/source3/nsswitch/winbindd_pam.c +++ b/source3/nsswitch/winbindd_pam.c @@ -37,7 +37,7 @@ static NTSTATUS append_info3_as_ndr(TALLOC_CTX *mem_ctx, if (!prs_init(&ps, 256 /* Random, non-zero number */, mem_ctx, MARSHALL)) { return NT_STATUS_NO_MEMORY; } - if (!net_io_user_info3("", info3, &ps, 1, 3)) { + if (!net_io_user_info3("", info3, &ps, 1, 3, False)) { prs_mem_free(&ps); return NT_STATUS_UNSUCCESSFUL; } @@ -227,15 +227,11 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, { NTSTATUS result; fstring name_domain, name_user; - const char *srv_name_slash; NET_USER_INFO_3 info3; - unsigned char *session_key; - struct rpc_pipe_client *pipe_cli; + struct rpc_pipe_client *netlogon_pipe; uchar chal[8]; DATA_BLOB lm_resp; DATA_BLOB nt_resp; - DOM_CRED ret_creds; - DOM_CRED *credentials; int attempts = 0; unsigned char local_lm_response[24]; unsigned char local_nt_response[24]; @@ -311,7 +307,6 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, local_nt_response, sizeof(local_nt_response)); } - /* what domain should we contact? */ @@ -333,49 +328,30 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, contact_domain = find_our_domain(); } - srv_name_slash = talloc_asprintf(state->mem_ctx, "\\\\%s", - contact_domain->dcname); - if (srv_name_slash == NULL) { - DEBUG(0, ("talloc_asprintf failed\n")); - return WINBINDD_ERROR; - } - /* check authentication loop */ do { - DOM_CRED clnt_creds; ZERO_STRUCT(info3); - ZERO_STRUCT(ret_creds); retry = False; - result = cm_connect_netlogon(contact_domain, state->mem_ctx, - &pipe_cli, &session_key, - &credentials); + result = cm_connect_netlogon(contact_domain, &netlogon_pipe); if (!NT_STATUS_IS_OK(result)) { DEBUG(3, ("could not open handle to NETLOGON pipe\n")); goto done; } - credentials->timestamp.time = time(NULL); - memcpy(&clnt_creds, credentials, sizeof(clnt_creds)); - - /* Calculate the new credentials. */ - cred_create(session_key, &credentials->challenge, - clnt_creds.timestamp, &(clnt_creds.challenge)); - - result = rpccli_netlogon_sam_network_logon(pipe_cli, - state->mem_ctx, - srv_name_slash, - &clnt_creds, - &ret_creds, - name_user, - name_domain, - global_myname(), - chal, lm_resp, - nt_resp, &info3, - session_key); + result = rpccli_netlogon_sam_network_logon(netlogon_pipe, + state->mem_ctx, + contact_domain->dcname, /* server name */ + name_user, /* user name */ + name_domain, /* target domain */ + global_myname(), /* workstation */ + chal, + lm_resp, + nt_resp, + &info3); attempts += 1; /* We have to try a second time as cm_connect_netlogon @@ -404,21 +380,11 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, } while ( (attempts < 2) && retry ); - /* Only check creds if we got a connection. */ - if (contact_domain->conn.cli && - !(NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || - NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL))) { - if (!clnt_deal_with_creds(session_key, credentials, &ret_creds)) { - DEBUG(3, ("DC %s sent wrong credentials\n", - pipe_cli->cli->srv_name_slash)); - result = NT_STATUS_ACCESS_DENIED; - } - } - if (NT_STATUS_IS_OK(result)) { /* Check if the user is in the right group */ - if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3, state->request.data.auth.require_membership_of_sid))) { + if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3, + state->request.data.auth.require_membership_of_sid))) { DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n", state->request.data.auth.user, state->request.data.auth.require_membership_of_sid)); @@ -426,8 +392,10 @@ enum winbindd_result winbindd_dual_pam_auth(struct winbindd_domain *domain, } done: + /* give us a more useful (more correct?) error code */ - if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { + if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || + (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { result = NT_STATUS_NO_LOGON_SERVERS; } @@ -450,7 +418,9 @@ done: char *afsname = SMB_STRDUP(lp_afs_username_map()); char *cell; - if (afsname == NULL) goto no_token; + if (afsname == NULL) { + goto no_token; + } afsname = realloc_string_sub(afsname, "%D", name_domain); afsname = realloc_string_sub(afsname, "%u", name_user); @@ -466,7 +436,9 @@ done: afsname = realloc_string_sub(afsname, "%s", sidstr); } - if (afsname == NULL) goto no_token; + if (afsname == NULL) { + goto no_token; + } strlower_m(afsname); @@ -474,7 +446,9 @@ done: cell = strchr(afsname, '@'); - if (cell == NULL) goto no_token; + if (cell == NULL) { + goto no_token; + } *cell = '\0'; cell += 1; @@ -565,16 +539,12 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, struct winbindd_cli_state *state) { NTSTATUS result; - const char *srv_name_slash; NET_USER_INFO_3 info3; - unsigned char *session_key; - struct rpc_pipe_client *pipe_cli; - DOM_CRED *credentials; + struct rpc_pipe_client *netlogon_pipe; const char *name_user = NULL; const char *name_domain = NULL; const char *workstation; struct winbindd_domain *contact_domain; - DOM_CRED ret_creds; int attempts = 0; BOOL retry; @@ -618,9 +588,10 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, goto done; } - lm_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.lm_resp, state->request.data.auth_crap.lm_resp_len); - nt_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.nt_resp, state->request.data.auth_crap.nt_resp_len); - + lm_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.lm_resp, + state->request.data.auth_crap.lm_resp_len); + nt_resp = data_blob_talloc(state->mem_ctx, state->request.data.auth_crap.nt_resp, + state->request.data.auth_crap.nt_resp_len); /* what domain should we contact? */ @@ -631,33 +602,20 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, result = NT_STATUS_NO_SUCH_USER; goto done; } - } else { if (is_myname(name_domain)) { DEBUG(3, ("Authentication for domain %s (local domain to this server) not supported at this stage\n", name_domain)); result = NT_STATUS_NO_SUCH_USER; goto done; } - contact_domain = find_our_domain(); } - srv_name_slash = talloc_asprintf(state->mem_ctx, "\\\\%s", - contact_domain->dcname); - if (srv_name_slash == NULL) { - DEBUG(0, ("talloc_asprintf failed\n")); - return WINBINDD_ERROR; - } - do { - DOM_CRED clnt_creds; ZERO_STRUCT(info3); - ZERO_STRUCT(ret_creds); retry = False; - result = cm_connect_netlogon(contact_domain, state->mem_ctx, - &pipe_cli, &session_key, - &credentials); + result = cm_connect_netlogon(contact_domain, &netlogon_pipe); if (!NT_STATUS_IS_OK(result)) { DEBUG(3, ("could not open handle to NETLOGON pipe (error: %s)\n", @@ -665,25 +623,16 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, goto done; } - credentials->timestamp.time = time(NULL); - memcpy(&clnt_creds, credentials, sizeof(clnt_creds)); - - /* Calculate the new credentials. */ - cred_create(session_key, &credentials->challenge, - clnt_creds.timestamp, &(clnt_creds.challenge)); - - result = rpccli_netlogon_sam_network_logon(pipe_cli, - state->mem_ctx, - srv_name_slash, - &clnt_creds, - &ret_creds, - name_user, - name_domain, - global_myname(), - state->request.data.auth_crap.chal, - lm_resp, - nt_resp, &info3, - session_key); + result = rpccli_netlogon_sam_network_logon(netlogon_pipe, + state->mem_ctx, + contact_domain->dcname, + name_user, + name_domain, + global_myname(), + state->request.data.auth_crap.chal, + lm_resp, + nt_resp, + &info3); attempts += 1; @@ -712,19 +661,9 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } while ( (attempts < 2) && retry ); - /* Only check creds if we got a connection. */ - if (contact_domain->conn.cli && - !(NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || - (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { - if (!clnt_deal_with_creds(session_key, credentials, &ret_creds)) { - DEBUG(3, ("DC %s sent wrong credentials\n", - pipe_cli->cli->srv_name_slash)); - result = NT_STATUS_ACCESS_DENIED; - } - } - if (NT_STATUS_IS_OK(result)) { - if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3, state->request.data.auth_crap.require_membership_of_sid))) { + if (!NT_STATUS_IS_OK(result = check_info3_in_group(state->mem_ctx, &info3, + state->request.data.auth_crap.require_membership_of_sid))) { DEBUG(3, ("User %s is not in the required group (%s), so plaintext authentication is rejected\n", state->request.data.auth_crap.user, state->request.data.auth_crap.require_membership_of_sid)); @@ -736,14 +675,14 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } else if (state->request.flags & WBFLAG_PAM_UNIX_NAME) { /* ntlm_auth should return the unix username, per 'winbind use default domain' settings and the like */ - + fstring username_out; const char *nt_username, *nt_domain; if (!(nt_username = unistr2_tdup(state->mem_ctx, &(info3.uni_user_name)))) { /* If the server didn't give us one, just use the one we sent them */ nt_username = name_user; } - + if (!(nt_domain = unistr2_tdup(state->mem_ctx, &(info3.uni_logon_dom)))) { /* If the server didn't give us one, just use the one we sent them */ nt_domain = name_domain; @@ -762,29 +701,34 @@ enum winbindd_result winbindd_dual_pam_auth_crap(struct winbindd_domain *domain, } if (state->request.flags & WBFLAG_PAM_USER_SESSION_KEY) { - memcpy(state->response.data.auth.user_session_key, info3.user_sess_key, sizeof(state->response.data.auth.user_session_key) /* 16 */); + memcpy(state->response.data.auth.user_session_key, info3.user_sess_key, + sizeof(state->response.data.auth.user_session_key) /* 16 */); } if (state->request.flags & WBFLAG_PAM_LMKEY) { - memcpy(state->response.data.auth.first_8_lm_hash, info3.lm_sess_key, sizeof(state->response.data.auth.first_8_lm_hash) /* 8 */); + memcpy(state->response.data.auth.first_8_lm_hash, info3.lm_sess_key, + sizeof(state->response.data.auth.first_8_lm_hash) /* 8 */); } } done: + /* give us a more useful (more correct?) error code */ - if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { + if ((NT_STATUS_EQUAL(result, NT_STATUS_DOMAIN_CONTROLLER_NOT_FOUND) || + (NT_STATUS_EQUAL(result, NT_STATUS_UNSUCCESSFUL)))) { result = NT_STATUS_NO_LOGON_SERVERS; } if (state->request.flags & WBFLAG_PAM_NT_STATUS_SQUASH) { result = nt_status_squash(result); } - + state->response.data.auth.nt_status = NT_STATUS_V(result); fstrcpy(state->response.data.auth.nt_status_string, nt_errstr(result)); - + /* we might have given a more useful error above */ - if (!*state->response.data.auth.error_string) + if (!*state->response.data.auth.error_string) { fstrcpy(state->response.data.auth.error_string, get_friendly_nt_error_msg(result)); + } state->response.data.auth.pam_error = nt_status_to_pam(result); DEBUG(NT_STATUS_IS_OK(result) ? 5 : 2, diff --git a/source3/pam_smbpass/pam_smb_auth.c b/source3/pam_smbpass/pam_smb_auth.c index 74645564d48..70275abf922 100644 --- a/source3/pam_smbpass/pam_smb_auth.c +++ b/source3/pam_smbpass/pam_smb_auth.c @@ -84,6 +84,11 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, pam_sm_setcred(). */ ret_data = SMB_MALLOC_P(int); + /* we need to do this before we call AUTH_RETURN */ + /* Getting into places that might use LDAP -- protect the app + from a SIGPIPE it's not expecting */ + oldsig_handler = CatchSignal(SIGPIPE, SIGNAL_CAST SIG_IGN); + /* get the username */ retval = pam_get_user( pamh, &name, "Username: " ); if ( retval != PAM_SUCCESS ) { @@ -96,10 +101,6 @@ int pam_sm_authenticate(pam_handle_t *pamh, int flags, _log_err( LOG_DEBUG, "username [%s] obtained", name ); } - /* Getting into places that might use LDAP -- protect the app - from a SIGPIPE it's not expecting */ - oldsig_handler = CatchSignal(SIGPIPE, SIGNAL_CAST SIG_IGN); - if (!initialize_password_db(True)) { _log_err( LOG_ALERT, "Cannot access samba password database" ); retval = PAM_AUTHINFO_UNAVAIL; diff --git a/source3/param/loadparm.c b/source3/param/loadparm.c index 7c5a17b86f7..0a4f0556ae1 100644 --- a/source3/param/loadparm.c +++ b/source3/param/loadparm.c @@ -122,6 +122,7 @@ typedef struct char *szConfigFile; char *szSMBPasswdFile; char *szPrivateDir; + char *szCountersDir; char **szPassdbBackend; char **szPreloadModules; char *szPasswordServer; @@ -188,6 +189,7 @@ typedef struct char *szEventLogNumRecordsCommand; char *szEventLogOldestRecordCommand; char *szEventLogCloseCommand; + char *szEventLogControlCommand; char **szEventLogs; char *szGuestaccount; char *szManglingMethod; @@ -833,6 +835,7 @@ static struct parm_struct parm_table[] = { {"password server", P_STRING, P_GLOBAL, &Globals.szPasswordServer, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, {"smb passwd file", P_STRING, P_GLOBAL, &Globals.szSMBPasswdFile, NULL, NULL, FLAG_ADVANCED}, {"private dir", P_STRING, P_GLOBAL, &Globals.szPrivateDir, NULL, NULL, FLAG_ADVANCED}, + {"counters dir", P_STRING, P_GLOBAL, &Globals.szCountersDir, NULL, NULL, FLAG_ADVANCED}, {"passdb backend", P_LIST, P_GLOBAL, &Globals.szPassdbBackend, NULL, NULL, FLAG_ADVANCED | FLAG_WIZARD}, {"algorithmic rid base", P_INTEGER, P_GLOBAL, &Globals.AlgorithmicRidBase, NULL, NULL, FLAG_ADVANCED}, {"root directory", P_STRING, P_GLOBAL, &Globals.szRootdir, NULL, NULL, FLAG_ADVANCED}, @@ -966,7 +969,7 @@ static struct parm_struct parm_table[] = { {"client use spnego", P_BOOL, P_GLOBAL, &Globals.bClientUseSpnego, NULL, NULL, FLAG_ADVANCED}, {"enable asu support", P_BOOL, P_GLOBAL, &Globals.bASUSupport, NULL, NULL, FLAG_ADVANCED}, - {"enable svcctl", P_LIST, P_GLOBAL, &Globals.szServicesList, NULL, NULL, FLAG_ADVANCED}, + {"svcctl list", P_LIST, P_GLOBAL, &Globals.szServicesList, NULL, NULL, FLAG_ADVANCED}, {N_("Tuning Options"), P_SEP, P_SEPARATOR}, @@ -1156,6 +1159,8 @@ static struct parm_struct parm_table[] = { {"eventlog clear command", P_STRING, P_GLOBAL, &Globals.szEventLogClearCommand, handle_eventlog, NULL, FLAG_ADVANCED}, {"eventlog num records command", P_STRING, P_GLOBAL, &Globals.szEventLogNumRecordsCommand, handle_eventlog, NULL, FLAG_ADVANCED}, {"eventlog oldest record command", P_STRING, P_GLOBAL, &Globals.szEventLogOldestRecordCommand, handle_eventlog, NULL, FLAG_ADVANCED}, + {"eventlog close command", P_STRING, P_GLOBAL, &Globals.szEventLogCloseCommand, handle_eventlog, NULL, FLAG_ADVANCED}, + {"eventlog control command", P_STRING, P_GLOBAL, &Globals.szEventLogControlCommand, handle_eventlog, NULL, FLAG_ADVANCED}, {"eventlog list", P_LIST, P_GLOBAL, &Globals.szEventLogs, NULL, NULL, FLAG_ADVANCED | FLAG_GLOBAL | FLAG_SHARE}, {"config file", P_STRING, P_GLOBAL, &Globals.szConfigFile, NULL, NULL, FLAG_HIDE}, @@ -1428,6 +1433,7 @@ static void init_globals(void) Globals.bLoadPrinters = True; Globals.PrintcapCacheTime = 750; /* 12.5 minutes */ + /* Was 65535 (0xFFFF). 0x4101 matches W2K and causes major speed improvements... */ /* Discovered by 2 days of pain by Don McCall @ HP :-). */ Globals.max_xmit = 0x4104; @@ -1520,7 +1526,6 @@ static void init_globals(void) #else Globals.szPassdbBackend = str_list_make("smbpasswd", NULL); #endif /* WITH_LDAP_SAMCONFIG */ - string_set(&Globals.szLdapSuffix, ""); string_set(&Globals.szLdapMachineSuffix, ""); string_set(&Globals.szLdapUserSuffix, ""); @@ -1581,6 +1586,8 @@ static void init_globals(void) string_set(&Globals.szEventLogClearCommand, ""); string_set(&Globals.szEventLogNumRecordsCommand, ""); string_set(&Globals.szEventLogOldestRecordCommand, ""); + string_set(&Globals.szEventLogCloseCommand, ""); + string_set(&Globals.szEventLogControlCommand, ""); Globals.winbind_cache_time = 300; /* 5 minutes */ Globals.bWinbindEnumUsers = True; @@ -1609,7 +1616,7 @@ static void init_globals(void) operations as root */ Globals.bEnablePrivileges = False; - + Globals.bASUSupport = True; Globals.szServicesList = str_list_make( "Spooler NETLOGON", NULL ); @@ -1703,6 +1710,7 @@ FN_GLOBAL_STRING(lp_logfile, &Globals.szLogFile) FN_GLOBAL_STRING(lp_configfile, &Globals.szConfigFile) FN_GLOBAL_STRING(lp_smb_passwd_file, &Globals.szSMBPasswdFile) FN_GLOBAL_STRING(lp_private_dir, &Globals.szPrivateDir) +FN_GLOBAL_STRING(lp_counters_dir, &Globals.szCountersDir) FN_GLOBAL_STRING(lp_serverstring, &Globals.szServerString) FN_GLOBAL_INTEGER(lp_printcap_cache_time, &Globals.PrintcapCacheTime) FN_GLOBAL_STRING(lp_enumports_cmd, &Globals.szEnumPortsCommand) @@ -1804,6 +1812,8 @@ FN_GLOBAL_STRING(lp_eventlog_clear_cmd, &Globals.szEventLogClearCommand) FN_GLOBAL_STRING(lp_eventlog_num_records_cmd, &Globals.szEventLogNumRecordsCommand) FN_GLOBAL_STRING(lp_eventlog_oldest_record_cmd, &Globals.szEventLogOldestRecordCommand) FN_GLOBAL_STRING(lp_eventlog_close_cmd, &Globals.szEventLogCloseCommand) +FN_GLOBAL_STRING(lp_eventlog_control_cmd, &Globals.szEventLogControlCommand) + FN_GLOBAL_LIST(lp_eventlog_list, &Globals.szEventLogs) FN_GLOBAL_BOOL(lp_disable_netbios, &Globals.bDisableNetbios) @@ -1904,7 +1914,7 @@ FN_LOCAL_STRING(lp_username, szUsername) FN_LOCAL_LIST(lp_invalid_users, szInvalidUsers) FN_LOCAL_LIST(lp_valid_users, szValidUsers) FN_LOCAL_LIST(lp_admin_users, szAdminUsers) -FN_GLOBAL_LIST(lp_enable_svcctl, &Globals.szServicesList) +FN_GLOBAL_LIST(lp_svcctl_list, &Globals.szServicesList) FN_LOCAL_STRING(lp_cups_options, szCupsOptions) FN_GLOBAL_STRING(lp_cups_server, &Globals.szCupsServer) FN_GLOBAL_STRING(lp_iprint_server, &Globals.szIPrintServer) @@ -3344,7 +3354,10 @@ BOOL lp_do_parameter(int snum, const char *pszParmName, const char *pszParmValue break; case P_OCTAL: - sscanf(pszParmValue, "%o", (int *)parm_ptr); + i = sscanf(pszParmValue, "%o", (int *)parm_ptr); + if ( i != 1 ) { + DEBUG ( 0, ("Invalid octal number %s\n", pszParmName )); + } break; case P_LIST: @@ -3698,13 +3711,13 @@ static void dump_a_service(service * pService, FILE * f) } } - if (pService->param_opt != NULL) { - data = pService->param_opt; - while(data) { - fprintf(f, "\t%s = %s\n", data->key, data->value); - data = data->next; - } - } + if (pService->param_opt != NULL) { + data = pService->param_opt; + while(data) { + fprintf(f, "\t%s = %s\n", data->key, data->value); + data = data->next; + } + } } /*************************************************************************** @@ -4128,7 +4141,7 @@ BOOL lp_load(const char *pszFname, BOOL global_only, BOOL save_defaults, are denied */ lp_add_ipc("IPC$", (lp_restrict_anonymous() < 2)); if ( lp_enable_asu_support() ) - lp_add_ipc("ADMIN$", False); + lp_add_ipc("ADMIN$", False); } set_server_role(); diff --git a/source3/passdb/lookup_sid.c b/source3/passdb/lookup_sid.c index 4cd9516dd19..6b58210919a 100644 --- a/source3/passdb/lookup_sid.c +++ b/source3/passdb/lookup_sid.c @@ -97,19 +97,27 @@ BOOL lookup_sid(const DOM_SID *sid, fstring dom_name, fstring name, enum SID_NAM } } - if (!winbind_lookup_sid(sid, dom_name, name, name_type)) { - fstring sid_str; - DOM_SID tmp_sid; - uint32 rid; + if (winbind_lookup_sid(sid, dom_name, name, name_type)) { + return True; + } - DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying local.\n", sid_to_string(sid_str, sid) )); + DEBUG(10,("lookup_sid: winbind lookup for SID %s failed - trying " + "special SIDs.\n", sid_string_static(sid))); - sid_copy(&tmp_sid, sid); - sid_split_rid(&tmp_sid, &rid); - return map_domain_sid_to_name(&tmp_sid, dom_name) && - lookup_known_rid(&tmp_sid, rid, name, name_type); + { + const char *dom, *obj_name; + + if (lookup_special_sid(sid, &dom, &obj_name, name_type)) { + DEBUG(10, ("found %s\\%s\n", dom, obj_name)); + fstrcpy(dom_name, dom); + fstrcpy(name, obj_name); + return True; + } } - return True; + + DEBUG(10, ("lookup_sid failed\n")); + + return False; } /***************************************************************** diff --git a/source3/passdb/passdb.c b/source3/passdb/passdb.c index 283eb7f1c16..a7ff3a04f7e 100644 --- a/source3/passdb/passdb.c +++ b/source3/passdb/passdb.c @@ -1875,7 +1875,7 @@ BOOL init_sam_from_buffer_v2(SAM_ACCOUNT *sampass, uint8 *buf, uint32 buflen) } /* Change from V1 is addition of password history field. */ - account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); + pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); if (pwHistLen) { uint8 *pw_hist = SMB_MALLOC(pwHistLen * PW_HISTORY_ENTRY_LEN); if (!pw_hist) { @@ -2083,7 +2083,7 @@ uint32 init_buffer_from_sam_v2 (uint8 **buf, const SAM_ACCOUNT *sampass, BOOL si nt_pw_len = 0; } - account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); + pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); nt_pw_hist = pdb_get_pw_history(sampass, &nt_pw_hist_len); if (pwHistLen && nt_pw_hist && nt_pw_hist_len) { nt_pw_hist_len *= PW_HISTORY_ENTRY_LEN; @@ -2292,8 +2292,8 @@ BOOL pdb_update_bad_password_count(SAM_ACCOUNT *sampass, BOOL *updated) return True; } - if (!account_policy_get(AP_RESET_COUNT_TIME, &resettime)) { - DEBUG(0, ("pdb_update_bad_password_count: account_policy_get failed.\n")); + if (!pdb_get_account_policy(AP_RESET_COUNT_TIME, &resettime)) { + DEBUG(0, ("pdb_update_bad_password_count: pdb_get_account_policy failed.\n")); return False; } @@ -2334,8 +2334,8 @@ BOOL pdb_update_autolock_flag(SAM_ACCOUNT *sampass, BOOL *updated) return True; } - if (!account_policy_get(AP_LOCK_ACCOUNT_DURATION, &duration)) { - DEBUG(0, ("pdb_update_autolock_flag: account_policy_get failed.\n")); + if (!pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &duration)) { + DEBUG(0, ("pdb_update_autolock_flag: pdb_get_account_policy failed.\n")); return False; } @@ -2383,9 +2383,9 @@ BOOL pdb_increment_bad_password_count(SAM_ACCOUNT *sampass) return False; /* Retrieve the account lockout policy */ - if (!account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, + if (!pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_lockout)) { - DEBUG(0, ("pdb_increment_bad_password_count: account_policy_get failed.\n")); + DEBUG(0, ("pdb_increment_bad_password_count: pdb_get_account_policy failed.\n")); return False; } diff --git a/source3/passdb/pdb_get_set.c b/source3/passdb/pdb_get_set.c index 12e8bcc9cf9..783e9e23fa3 100644 --- a/source3/passdb/pdb_get_set.c +++ b/source3/passdb/pdb_get_set.c @@ -1123,7 +1123,7 @@ BOOL pdb_set_pass_changed_now (SAM_ACCOUNT *sampass) if (!pdb_set_pass_last_set_time (sampass, time(NULL), PDB_CHANGED)) return False; - if (!account_policy_get(AP_MAX_PASSWORD_AGE, &expire) + if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire) || (expire==(uint32)-1) || (expire == 0)) { if (!pdb_set_pass_must_change_time (sampass, get_time_t_max(), PDB_CHANGED)) return False; @@ -1134,7 +1134,7 @@ BOOL pdb_set_pass_changed_now (SAM_ACCOUNT *sampass) return False; } - if (!account_policy_get(AP_MIN_PASSWORD_AGE, &min_age) + if (!pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &min_age) || (min_age==(uint32)-1)) { if (!pdb_set_pass_can_change_time (sampass, 0, PDB_CHANGED)) return False; @@ -1189,13 +1189,13 @@ BOOL pdb_set_plaintext_passwd (SAM_ACCOUNT *sampass, const char *plaintext) if (pdb_get_acct_ctrl(sampass) & ACB_NORMAL) { uchar *pwhistory; uint32 pwHistLen; - account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); + pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); if (pwHistLen != 0){ uint32 current_history_len; /* We need to make sure we don't have a race condition here - the account policy history length can change between when the pw_history was first loaded into the SAM_ACCOUNT struct and now.... JRA. */ - pwhistory = CONST_DISCARD(uchar *, pdb_get_pw_history(sampass, ¤t_history_len)); + pwhistory = (uchar *)pdb_get_pw_history(sampass, ¤t_history_len); if (current_history_len != pwHistLen) { /* After closing and reopening SAM_ACCOUNT the history diff --git a/source3/passdb/pdb_interface.c b/source3/passdb/pdb_interface.c index d4407492c21..a9e41984c3d 100644 --- a/source3/passdb/pdb_interface.c +++ b/source3/passdb/pdb_interface.c @@ -665,43 +665,46 @@ static NTSTATUS context_lookup_rids(struct pdb_context *context, rids, names, attrs); } -static BOOL context_search_users(struct pdb_context *context, - struct pdb_search *search, uint16 acct_flags) +static NTSTATUS context_get_account_policy(struct pdb_context *context, + int policy_index, uint32 *value) { + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + if ((!context) || (!context->pdb_methods)) { DEBUG(0, ("invalid pdb_context specified!\n")); - return False; + return ret; } - return context->pdb_methods->search_users(context->pdb_methods, - search, acct_flags); + return context->pdb_methods->get_account_policy(context->pdb_methods, + policy_index, value); } -static BOOL context_search_groups(struct pdb_context *context, - struct pdb_search *search) +static NTSTATUS context_set_account_policy(struct pdb_context *context, + int policy_index, uint32 value) { + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + if ((!context) || (!context->pdb_methods)) { DEBUG(0, ("invalid pdb_context specified!\n")); - return False; + return ret; } - return context->pdb_methods->search_groups(context->pdb_methods, - search); + return context->pdb_methods->set_account_policy(context->pdb_methods, + policy_index, value); } -static BOOL context_search_aliases(struct pdb_context *context, - struct pdb_search *search, - const DOM_SID *sid) +static NTSTATUS context_get_seq_num(struct pdb_context *context, time_t *seq_num) { + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + if ((!context) || (!context->pdb_methods)) { DEBUG(0, ("invalid pdb_context specified!\n")); - return False; + return ret; } - return context->pdb_methods->search_aliases(context->pdb_methods, - search, sid); + return context->pdb_methods->get_seq_num(context->pdb_methods, seq_num); } - + /****************************************************************** Free and cleanup a pdb context, any associated data and anything that the attached modules might have associated. @@ -721,6 +724,43 @@ static void free_pdb_context(struct pdb_context **context) *context = NULL; } +static BOOL context_search_users(struct pdb_context *context, + struct pdb_search *search, uint16 acct_flags) +{ + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return False; + } + + return context->pdb_methods->search_users(context->pdb_methods, + search, acct_flags); +} + +static BOOL context_search_groups(struct pdb_context *context, + struct pdb_search *search) +{ + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return False; + } + + return context->pdb_methods->search_groups(context->pdb_methods, + search); +} + +static BOOL context_search_aliases(struct pdb_context *context, + struct pdb_search *search, + const DOM_SID *sid) +{ + if ((!context) || (!context->pdb_methods)) { + DEBUG(0, ("invalid pdb_context specified!\n")); + return False; + } + + return context->pdb_methods->search_aliases(context->pdb_methods, + search, sid); +} + /****************************************************************** Make a pdb_methods from scratch *******************************************************************/ @@ -832,6 +872,11 @@ static NTSTATUS make_pdb_context(struct pdb_context **context) (*context)->pdb_enum_alias_memberships = context_enum_alias_memberships; (*context)->pdb_lookup_rids = context_lookup_rids; + (*context)->pdb_get_account_policy = context_get_account_policy; + (*context)->pdb_set_account_policy = context_set_account_policy; + + (*context)->pdb_get_seq_num = context_get_seq_num; + (*context)->pdb_search_users = context_search_users; (*context)->pdb_search_groups = context_search_groups; (*context)->pdb_search_aliases = context_search_aliases; @@ -1318,6 +1363,41 @@ NTSTATUS pdb_lookup_rids(TALLOC_CTX *mem_ctx, num_rids, rids, names, attrs); } +BOOL pdb_get_account_policy(int policy_index, uint32 *value) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return NT_STATUS_IS_OK(pdb_context-> + pdb_get_account_policy(pdb_context, policy_index, value)); +} + +BOOL pdb_set_account_policy(int policy_index, uint32 value) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return NT_STATUS_IS_OK(pdb_context-> + pdb_set_account_policy(pdb_context, policy_index, value)); +} + +BOOL pdb_get_seq_num(time_t *seq_num) +{ + struct pdb_context *pdb_context = pdb_get_static_context(False); + + if (!pdb_context) { + return False; + } + + return NT_STATUS_IS_OK(pdb_context-> + pdb_get_seq_num(pdb_context, seq_num)); +} /*************************************************************** Initialize the static context (at smbd startup etc). @@ -1380,6 +1460,22 @@ static void pdb_default_endsampwent(struct pdb_methods *methods) return; /* NT_STATUS_NOT_IMPLEMENTED; */ } +static NTSTATUS pdb_default_get_account_policy(struct pdb_methods *methods, int policy_index, uint32 *value) +{ + return account_policy_get(policy_index, value) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; +} + +static NTSTATUS pdb_default_set_account_policy(struct pdb_methods *methods, int policy_index, uint32 value) +{ + return account_policy_set(policy_index, value) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; +} + +static NTSTATUS pdb_default_get_seq_num(struct pdb_methods *methods, time_t *seq_num) +{ + *seq_num = time(NULL); + return NT_STATUS_OK; +} + static void add_uid_to_array_unique(TALLOC_CTX *mem_ctx, uid_t uid, uid_t **uids, int *num) { @@ -1908,6 +2004,10 @@ NTSTATUS make_pdb_methods(TALLOC_CTX *mem_ctx, PDB_METHODS **methods) (*methods)->enum_aliasmem = pdb_default_enum_aliasmem; (*methods)->enum_alias_memberships = pdb_default_alias_memberships; (*methods)->lookup_rids = pdb_default_lookup_rids; + (*methods)->get_account_policy = pdb_default_get_account_policy; + (*methods)->set_account_policy = pdb_default_set_account_policy; + (*methods)->get_seq_num = pdb_default_get_seq_num; + (*methods)->search_users = pdb_default_search_users; (*methods)->search_groups = pdb_default_search_groups; (*methods)->search_aliases = pdb_default_search_aliases; diff --git a/source3/passdb/pdb_ldap.c b/source3/passdb/pdb_ldap.c index 99f6670653b..e44ccc3bf98 100644 --- a/source3/passdb/pdb_ldap.c +++ b/source3/passdb/pdb_ldap.c @@ -178,6 +178,146 @@ static const char* get_objclass_filter( int schema_ver ) return objclass_filter; } +/***************************************************************** + Scan a sequence number off OpenLDAP's syncrepl contextCSN +******************************************************************/ + +static NTSTATUS ldapsam_get_seq_num(struct pdb_methods *my_methods, time_t *seq_num) +{ + struct ldapsam_privates *ldap_state = (struct ldapsam_privates *)my_methods->private_data; + NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL; + LDAPMessage *msg = NULL; + LDAPMessage *entry = NULL; + TALLOC_CTX *mem_ctx; + char **values = NULL; + int rc, num_result, num_values, rid; + pstring suffix; + fstring tok; + const char *p; + const char **attrs; + + /* Unfortunatly there is no proper way to detect syncrepl-support in + * smbldap_connect_system(). The syncrepl OIDs are submitted for publication + * but do not show up in the root-DSE yet. Neither we can query the + * subschema-context for the syncProviderSubentry or syncConsumerSubentry + * objectclass. Currently we require lp_ldap_suffix() to show up as + * namingContext. - Guenther + */ + + if (!lp_parm_bool(-1, "ldapsam", "syncrepl_seqnum", False)) { + return ntstatus; + } + + if (!seq_num) { + DEBUG(3,("ldapsam_get_seq_num: no sequence_number\n")); + return ntstatus; + } + + if (!smbldap_has_naming_context(ldap_state->smbldap_state, lp_ldap_suffix())) { + DEBUG(3,("ldapsam_get_seq_num: DIT not configured to hold %s " + "as top-level namingContext\n", lp_ldap_suffix())); + return ntstatus; + } + + mem_ctx = talloc_init("ldapsam_get_seq_num"); + + if (mem_ctx == NULL) + return NT_STATUS_NO_MEMORY; + + attrs = TALLOC_ARRAY(mem_ctx, const char *, 2); + + /* if we got a syncrepl-rid (up to three digits long) we speak with a consumer */ + rid = lp_parm_int(-1, "ldapsam", "syncrepl_rid", -1); + if (rid > 0) { + + /* consumer syncreplCookie: */ + /* csn=20050126161620Z#0000001#00#00000 */ + attrs[0] = talloc_strdup(mem_ctx, "syncreplCookie"); + attrs[1] = NULL; + pstr_sprintf( suffix, "cn=syncrepl%d,%s", rid, lp_ldap_suffix()); + + } else { + + /* provider contextCSN */ + /* 20050126161620Z#000009#00#000000 */ + attrs[0] = talloc_strdup(mem_ctx, "contextCSN"); + attrs[1] = NULL; + pstr_sprintf( suffix, "cn=ldapsync,%s", lp_ldap_suffix()); + + } + + rc = smbldap_search(ldap_state->smbldap_state, suffix, + LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, &msg); + + if (rc != LDAP_SUCCESS) { + + char *ld_error = NULL; + ldap_get_option(ldap_state->smbldap_state->ldap_struct, + LDAP_OPT_ERROR_STRING, &ld_error); + DEBUG(0,("ldapsam_get_seq_num: Failed search for suffix: %s, error: %s (%s)\n", + suffix,ldap_err2string(rc), ld_error?ld_error:"unknown")); + SAFE_FREE(ld_error); + goto done; + } + + num_result = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, msg); + if (num_result != 1) { + DEBUG(3,("ldapsam_get_seq_num: Expected one entry, got %d\n", num_result)); + goto done; + } + + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, msg); + if (entry == NULL) { + DEBUG(3,("ldapsam_get_seq_num: Could not retrieve entry\n")); + goto done; + } + + values = ldap_get_values(ldap_state->smbldap_state->ldap_struct, entry, attrs[0]); + if (values == NULL) { + DEBUG(3,("ldapsam_get_seq_num: no values\n")); + goto done; + } + + num_values = ldap_count_values(values); + if (num_values == 0) { + DEBUG(3,("ldapsam_get_seq_num: not a single value\n")); + goto done; + } + + p = values[0]; + if (!next_token(&p, tok, "#", sizeof(tok))) { + DEBUG(0,("ldapsam_get_seq_num: failed to parse sequence number\n")); + goto done; + } + + p = tok; + if (!strncmp(p, "csn=", strlen("csn="))) + p += strlen("csn="); + + DEBUG(10,("ldapsam_get_seq_num: got %s: %s\n", attrs[0], p)); + + *seq_num = generalized_to_unix_time(p); + + /* very basic sanity check */ + if (*seq_num <= 0) { + DEBUG(3,("ldapsam_get_seq_num: invalid sequence number: %d\n", + (int)*seq_num)); + goto done; + } + + ntstatus = NT_STATUS_OK; + + done: + if (values != NULL) + ldap_value_free(values); + if (msg != NULL) + ldap_msgfree(msg); + if (mem_ctx) + talloc_destroy(mem_ctx); + + return ntstatus; +} + /******************************************************************* Run the search by name. ******************************************************************/ @@ -694,9 +834,9 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state, if (ldap_state->is_nds_ldap) { char *user_dn; - int pwd_len; + size_t pwd_len; char clear_text_pw[512]; - + /* Make call to Novell eDirectory ldap extension to get clear text password. NOTE: This will only work if we have an SSL connection to eDirectory. */ user_dn = smbldap_get_dn(ldap_state->smbldap_state->ldap_struct, entry); @@ -717,7 +857,7 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state, } else { DEBUG(0, ("init_sam_from_ldap: failed to get user_dn for '%s'\n", username)); } - } + } if (use_samba_attrs) { if (!smbldap_get_single_pstring (ldap_state->smbldap_state->ldap_struct, entry, @@ -741,9 +881,11 @@ static BOOL init_sam_from_ldap(struct ldapsam_privates *ldap_state, return False; ZERO_STRUCT(smbntpwd); } - } + } + + pwHistLen = 0; - account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); + pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); if (pwHistLen > 0){ uint8 *pwhist = NULL; int i; @@ -1087,7 +1229,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, if (need_update(sampass, PDB_PWHISTORY)) { uint32 pwHistLen = 0; - account_policy_get(AP_PASSWORD_HISTORY, &pwHistLen); + pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHistLen); if (pwHistLen == 0) { /* Remove any password history from the LDAP store. */ memset(temp, '0', 64); /* NOTE !!!! '0' *NOT '\0' */ @@ -1153,7 +1295,7 @@ static BOOL init_ldap_from_sam (struct ldapsam_privates *ldap_state, uint16 badcount = pdb_get_bad_password_count(sampass); time_t badtime = pdb_get_bad_password_time(sampass); uint32 pol; - account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &pol); + pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &pol); DEBUG(3, ("updating bad password fields, policy=%u, count=%u, time=%u\n", (unsigned int)pol, (unsigned int)badcount, (unsigned int)badtime)); @@ -2158,10 +2300,10 @@ static NTSTATUS ldapsam_getgrgid(struct pdb_methods *methods, GROUP_MAP *map, { pstring filter; - pstr_sprintf(filter, "(&(objectClass=%s)(%s=%d))", + pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))", LDAP_OBJ_GROUPMAP, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), - gid); + (unsigned long)gid); return ldapsam_getgroup(methods, filter, map); } @@ -2312,7 +2454,7 @@ static NTSTATUS ldapsam_enum_group_members(struct pdb_methods *methods, { const char *attrs[] = { "memberUid", NULL }; - rc = smbldap_search(conn, lp_ldap_group_suffix(), + rc = smbldap_search(conn, lp_ldap_user_suffix(), LDAP_SCOPE_SUBTREE, filter, attrs, 0, &msg); } @@ -2536,10 +2678,10 @@ static int ldapsam_search_one_group_by_gid(struct ldapsam_privates *ldap_state, { pstring filter; - pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%d))", + pstr_sprintf(filter, "(&(|(objectClass=%s)(objectclass=%s))(%s=%lu))", LDAP_OBJ_POSIXGROUP, LDAP_OBJ_IDMAP_ENTRY, get_attr_key2string(groupmap_attr_list, LDAP_ATTR_GIDNUMBER), - gid); + (unsigned long)gid); return ldapsam_search_one_group(ldap_state, filter, result); } @@ -2589,7 +2731,7 @@ static NTSTATUS ldapsam_add_group_mapping_entry(struct pdb_methods *methods, ldap_msgfree(result); pstrcpy( suffix, lp_ldap_idmap_suffix() ); - pstr_sprintf(filter, "(&(objectClass=%s)(%s=%d))", + pstr_sprintf(filter, "(&(objectClass=%s)(%s=%u))", LDAP_OBJ_IDMAP_ENTRY, LDAP_ATTRIBUTE_GIDNUMBER, map->gid); @@ -3131,6 +3273,187 @@ static NTSTATUS ldapsam_alias_memberships(struct pdb_methods *methods, return NT_STATUS_OK; } +static NTSTATUS ldapsam_set_account_policy(struct pdb_methods *methods, int policy_index, uint32 value) +{ + NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL; + int rc; + LDAPMod **mods = NULL; + fstring value_string; + const char *policy_attr = NULL; + + struct ldapsam_privates *ldap_state = + (struct ldapsam_privates *)methods->private_data; + + const char *attrs[2]; + + DEBUG(10,("ldapsam_set_account_policy\n")); + + if (!ldap_state->domain_dn) { + return NT_STATUS_INVALID_PARAMETER; + } + + policy_attr = get_account_policy_attr(policy_index); + if (policy_attr == NULL) { + DEBUG(0,("ldapsam_set_account_policy: invalid policy\n")); + return ntstatus; + } + + attrs[0] = policy_attr; + attrs[1] = NULL; + + slprintf(value_string, sizeof(value_string) - 1, "%i", value); + + smbldap_set_mod(&mods, LDAP_MOD_REPLACE, policy_attr, value_string); + + rc = smbldap_modify(ldap_state->smbldap_state, ldap_state->domain_dn, mods); + + ldap_mods_free(mods, True); + + if (rc != LDAP_SUCCESS) { + char *ld_error = NULL; + ldap_get_option(ldap_state->smbldap_state->ldap_struct, + LDAP_OPT_ERROR_STRING,&ld_error); + + DEBUG(0, ("ldapsam_set_account_policy: Could not set account policy " + "for %s, error: %s (%s)\n", ldap_state->domain_dn, ldap_err2string(rc), + ld_error?ld_error:"unknown")); + SAFE_FREE(ld_error); + return ntstatus; + } + + if (!cache_account_policy_set(policy_index, value)) { + DEBUG(0,("ldapsam_set_account_policy: failed to update local tdb cache\n")); + return ntstatus; + } + + return NT_STATUS_OK; +} + +static NTSTATUS ldapsam_get_account_policy_from_ldap(struct pdb_methods *methods, int policy_index, uint32 *value) +{ + NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL; + LDAPMessage *result = NULL; + LDAPMessage *entry = NULL; + int count; + int rc; + char **vals = NULL; + const char *policy_attr = NULL; + + struct ldapsam_privates *ldap_state = + (struct ldapsam_privates *)methods->private_data; + + const char *attrs[2]; + + DEBUG(10,("ldapsam_get_account_policy_from_ldap\n")); + + if (!ldap_state->domain_dn) { + return NT_STATUS_INVALID_PARAMETER; + } + + policy_attr = get_account_policy_attr(policy_index); + if (!policy_attr) { + DEBUG(0,("ldapsam_get_account_policy_from_ldap: invalid policy index: %d\n", policy_index)); + return ntstatus; + } + + attrs[0] = policy_attr; + attrs[1] = NULL; + + rc = smbldap_search(ldap_state->smbldap_state, ldap_state->domain_dn, + LDAP_SCOPE_BASE, "(objectclass=*)", attrs, 0, &result); + + if (rc != LDAP_SUCCESS) { + char *ld_error = NULL; + ldap_get_option(ldap_state->smbldap_state->ldap_struct, + LDAP_OPT_ERROR_STRING,&ld_error); + + DEBUG(0, ("ldapsam_get_account_policy_from_ldap: Could not set account policy " + "for %s, error: %s (%s)\n", ldap_state->domain_dn, ldap_err2string(rc), + ld_error?ld_error:"unknown")); + SAFE_FREE(ld_error); + return ntstatus; + } + + count = ldap_count_entries(ldap_state->smbldap_state->ldap_struct, result); + if (count < 1) { + goto out; + } + + entry = ldap_first_entry(ldap_state->smbldap_state->ldap_struct, result); + if (entry == NULL) { + goto out; + } + + vals = ldap_get_values(ldap_state->smbldap_state->ldap_struct, entry, policy_attr); + if (vals == NULL) { + goto out; + } + + *value = (uint32)atol(vals[0]); + + ntstatus = NT_STATUS_OK; + +out: + if (vals) + ldap_value_free(vals); + ldap_msgfree(result); + + return ntstatus; +} + +/* wrapper around ldapsam_get_account_policy_from_ldap(), handles tdb as cache + + - if there is a valid cache entry, return that + - if there is an LDAP entry, update cache and return + - otherwise set to default, update cache and return + + Guenther +*/ +static NTSTATUS ldapsam_get_account_policy(struct pdb_methods *methods, int policy_index, uint32 *value) +{ + NTSTATUS ntstatus = NT_STATUS_UNSUCCESSFUL; + + if (cache_account_policy_get(policy_index, value)) { + DEBUG(11,("ldapsam_get_account_policy: got valid value from cache\n")); + return NT_STATUS_OK; + } + + ntstatus = ldapsam_get_account_policy_from_ldap(methods, policy_index, value); + if (NT_STATUS_IS_OK(ntstatus)) { + goto update_cache; + } + + DEBUG(10,("ldapsam_get_account_policy: failed to retrieve from ldap, returning default.\n")); + +#if 0 + /* should we automagically migrate old tdb value here ? */ + if (account_policy_get(policy_index, value)) + goto update_ldap; + + DEBUG(10,("ldapsam_get_account_policy: no tdb for %d, trying default\n", policy_index)); +#endif + + if (!account_policy_get_default(policy_index, value)) { + return ntstatus; + } + +/* update_ldap: */ + + ntstatus = ldapsam_set_account_policy(methods, policy_index, *value); + if (!NT_STATUS_IS_OK(ntstatus)) { + return ntstatus; + } + + update_cache: + + if (!cache_account_policy_set(policy_index, *value)) { + DEBUG(0,("ldapsam_get_account_policy: failed to update local tdb as a cache\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + return NT_STATUS_OK; +} + static NTSTATUS ldapsam_lookup_rids(struct pdb_methods *methods, TALLOC_CTX *mem_ctx, const DOM_SID *domain_sid, @@ -3890,6 +4213,11 @@ static NTSTATUS pdb_init_ldapsam_common(PDB_CONTEXT *pdb_context, PDB_METHODS ** (*pdb_method)->enum_group_memberships = ldapsam_enum_group_memberships; (*pdb_method)->lookup_rids = ldapsam_lookup_rids; + (*pdb_method)->get_account_policy = ldapsam_get_account_policy; + (*pdb_method)->set_account_policy = ldapsam_set_account_policy; + + (*pdb_method)->get_seq_num = ldapsam_get_seq_num; + /* TODO: Setup private data and free */ ldap_state = TALLOC_ZERO_P(pdb_context->mem_ctx, struct ldapsam_privates); diff --git a/source3/passdb/pdb_nds.c b/source3/passdb/pdb_nds.c index 3e5f8d1b930..599a198c5a4 100644 --- a/source3/passdb/pdb_nds.c +++ b/source3/passdb/pdb_nds.c @@ -550,7 +550,7 @@ static int nmasldap_get_password( LDAP *ld, char *objectDN, size_t *pwdSize, /* in bytes */ - char *pwd ) + unsigned char *pwd ) { int err = 0; diff --git a/source3/passdb/pdb_smbpasswd.c b/source3/passdb/pdb_smbpasswd.c index edb578b1e74..6eb4305409a 100644 --- a/source3/passdb/pdb_smbpasswd.c +++ b/source3/passdb/pdb_smbpasswd.c @@ -313,10 +313,11 @@ static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_s unsigned char *smbpwd = smbpasswd_state->smbpwd; unsigned char *smbntpwd = smbpasswd_state->smbntpwd; char linebuf[256]; - unsigned char c; + int c; unsigned char *p; long uidval; size_t linebuf_len; + char *status; if(fp == NULL) { DEBUG(0,("getsmbfilepwent: Bad password file pointer.\n")); @@ -329,11 +330,12 @@ static struct smb_passwd *getsmbfilepwent(struct smbpasswd_privates *smbpasswd_s /* * Scan the file, a line at a time and check if the name matches. */ - while (!feof(fp)) { + status = linebuf; + while (status && !feof(fp)) { linebuf[0] = '\0'; - fgets(linebuf, 256, fp); - if (ferror(fp)) { + status = fgets(linebuf, 256, fp); + if (status == NULL && ferror(fp)) { return NULL; } @@ -651,7 +653,7 @@ Error was %s\n", newpwd->smb_name, pfile, strerror(errno))); #ifdef DEBUG_PASSWORD DEBUG(100, ("add_smbfilepwd_entry(%d): new_entry_len %d made line |%s|", - fd, new_entry_length, new_entry)); + fd, (int)new_entry_length, new_entry)); #endif if ((wr_len = write(fd, new_entry, new_entry_length)) != new_entry_length) { @@ -689,9 +691,10 @@ static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, con /* Static buffers we will return. */ pstring user_name; + char *status; char linebuf[256]; char readbuf[1024]; - unsigned char c; + int c; fstring ascii_p16; fstring encode_bits; unsigned char *p = NULL; @@ -738,13 +741,14 @@ static BOOL mod_smbfilepwd_entry(struct smbpasswd_privates *smbpasswd_state, con /* * Scan the file, a line at a time and check if the name matches. */ - while (!feof(fp)) { + status = linebuf; + while (status && !feof(fp)) { pwd_seekpos = sys_ftell(fp); linebuf[0] = '\0'; - fgets(linebuf, sizeof(linebuf), fp); - if (ferror(fp)) { + status = fgets(linebuf, sizeof(linebuf), fp); + if (status == NULL && ferror(fp)) { pw_file_unlock(lockfd, &smbpasswd_state->pw_file_lock_depth); fclose(fp); return False; diff --git a/source3/passdb/secrets.c b/source3/passdb/secrets.c index 6144037200f..29437c35a87 100644 --- a/source3/passdb/secrets.c +++ b/source3/passdb/secrets.c @@ -30,6 +30,9 @@ static TDB_CONTEXT *tdb; +/* Urrrg. global.... */ +BOOL global_machine_password_needs_changing; + /** * Use a TDB to store an incrementing random seed. * @@ -294,12 +297,23 @@ BOOL secrets_fetch_trust_account_password(const char *domain, uint8 ret_pwd[16], return False; } - if (pass_last_set_time) *pass_last_set_time = pass->mod_time; + if (pass_last_set_time) { + *pass_last_set_time = pass->mod_time; + } memcpy(ret_pwd, pass->hash, 16); SAFE_FREE(pass); - if (channel) + if (channel) { *channel = get_default_sec_channel(); + } + + /* Test if machine password has expired and needs to be changed */ + if (lp_machine_password_timeout()) { + if (pass->mod_time > 0 && time(NULL) > (pass->mod_time + + lp_machine_password_timeout())) { + global_machine_password_needs_changing = True; + } + } return True; } @@ -454,11 +468,11 @@ BOOL secrets_store_machine_password(const char *pass, const char *domain, uint32 return ret; } - /************************************************************************ Routine to fetch the plaintext machine account password for a realm -the password is assumed to be a null terminated ascii string + the password is assumed to be a null terminated ascii string. ************************************************************************/ + char *secrets_fetch_machine_password(const char *domain, time_t *pass_last_set_time, uint32 *channel) @@ -503,7 +517,46 @@ char *secrets_fetch_machine_password(const char *domain, return ret; } +/******************************************************************* + Wrapper around retrieving the trust account password +*******************************************************************/ + +BOOL get_trust_pw(const char *domain, uint8 ret_pwd[16], uint32 *channel) +{ + DOM_SID sid; + char *pwd; + time_t last_set_time; + + /* if we are a DC and this is not our domain, then lookup an account + for the domain trust */ + + if ( IS_DC && !strequal(domain, lp_workgroup()) && lp_allow_trusted_domains() ) { + if (!secrets_fetch_trusted_domain_password(domain, &pwd, &sid, + &last_set_time)) { + DEBUG(0, ("get_trust_pw: could not fetch trust " + "account password for trusted domain %s\n", + domain)); + return False; + } + + *channel = SEC_CHAN_DOMAIN; + E_md4hash(pwd, ret_pwd); + SAFE_FREE(pwd); + + return True; + } + + /* Just get the account for the requested domain. In the future this + * might also cover to be member of more than one domain. */ + + if (secrets_fetch_trust_account_password(domain, ret_pwd, + &last_set_time, channel)) + return True; + DEBUG(5, ("get_trust_pw: could not fetch trust account " + "password for domain %s\n", domain)); + return False; +} /************************************************************************ Routine to delete the machine trust account password file for a domain. @@ -523,7 +576,6 @@ BOOL trusted_domain_password_delete(const char *domain) return secrets_delete(trustdom_keystr(domain)); } - BOOL secrets_store_ldap_pw(const char* dn, char* pw) { char *key = NULL; @@ -541,8 +593,9 @@ BOOL secrets_store_ldap_pw(const char* dn, char* pw) } /******************************************************************* - find the ldap password + Find the ldap password. ******************************************************************/ + BOOL fetch_ldap_pw(char **dn, char** pw) { char *key = NULL; @@ -605,7 +658,6 @@ BOOL fetch_ldap_pw(char **dn, char** pw) return True; } - /** * Get trusted domains info from secrets.tdb. * diff --git a/source3/passdb/util_sam_sid.c b/source3/passdb/util_sam_sid.c index a9e1921e0d0..42e4b6df967 100644 --- a/source3/passdb/util_sam_sid.c +++ b/source3/passdb/util_sam_sid.c @@ -30,15 +30,12 @@ typedef struct _known_sid_users { const char *known_user_name; } known_sid_users; -static struct sid_name_map_info +struct sid_name_map_info { const DOM_SID *sid; const char *name; const known_sid_users *known_users; -} sid_name_map[MAX_SID_NAMES]; - -static BOOL sid_name_map_initialized = False; -/* static known_sid_users no_users[] = {{0, 0, NULL}}; */ +}; static const known_sid_users everyone_users[] = { { 0, SID_NAME_WKN_GRP, "Everyone" }, @@ -83,64 +80,12 @@ static const known_sid_users builtin_groups[] = { { BUILTIN_ALIAS_RID_PRE_2K_ACCESS, SID_NAME_ALIAS, "Pre-Windows 2000 Compatible Access" }, { 0, (enum SID_NAME_USE)0, NULL}}; -/************************************************************************** - Quick init function. -*************************************************************************/ - -static void init_sid_name_map (void) -{ - int i = 0; - - if (sid_name_map_initialized) return; - - if ((lp_security() == SEC_USER) && lp_domain_logons()) { - sid_name_map[i].sid = get_global_sam_sid(); - /* This is not lp_workgroup() for good reason: - it must stay around longer than the lp_*() - strings do */ - sid_name_map[i].name = SMB_STRDUP(lp_workgroup()); - sid_name_map[i].known_users = NULL; - i++; - sid_name_map[i].sid = get_global_sam_sid(); - sid_name_map[i].name = SMB_STRDUP(global_myname()); - sid_name_map[i].known_users = NULL; - i++; - } else { - sid_name_map[i].sid = get_global_sam_sid(); - sid_name_map[i].name = SMB_STRDUP(global_myname()); - sid_name_map[i].known_users = NULL; - i++; - } - - sid_name_map[i].sid = &global_sid_Builtin; - sid_name_map[i].name = "BUILTIN"; - sid_name_map[i].known_users = &builtin_groups[0]; - i++; - - sid_name_map[i].sid = &global_sid_World_Domain; - sid_name_map[i].name = ""; - sid_name_map[i].known_users = &everyone_users[0]; - i++; - - sid_name_map[i].sid = &global_sid_Creator_Owner_Domain; - sid_name_map[i].name = ""; - sid_name_map[i].known_users = &creator_owner_users[0]; - i++; - - sid_name_map[i].sid = &global_sid_NT_Authority; - sid_name_map[i].name = "NT Authority"; - sid_name_map[i].known_users = &nt_authority_users[0]; - i++; - - /* End of array. */ - sid_name_map[i].sid = NULL; - sid_name_map[i].name = NULL; - sid_name_map[i].known_users = NULL; - - sid_name_map_initialized = True; - - return; -} +static struct sid_name_map_info special_domains[] = { + { &global_sid_Builtin, "BUILTIN", builtin_groups }, + { &global_sid_World_Domain, "", everyone_users }, + { &global_sid_Creator_Owner_Domain, "", creator_owner_users }, + { &global_sid_NT_Authority, "NT Authority", nt_authority_users }, + { NULL, NULL, NULL }}; /************************************************************************** Turns a domain SID into a name, returned in the nt_domain argument. @@ -153,101 +98,74 @@ BOOL map_domain_sid_to_name(DOM_SID *sid, fstring nt_domain) sid_to_string(sid_str, sid); - if (!sid_name_map_initialized) - init_sid_name_map(); - DEBUG(5,("map_domain_sid_to_name: %s\n", sid_str)); - if (nt_domain == NULL) - return False; + if (sid_check_is_domain(sid)) { + fstrcpy(nt_domain, get_global_sam_name()); + return True; + } - while (sid_name_map[i].sid != NULL) { - sid_to_string(sid_str, sid_name_map[i].sid); - DEBUG(5,("map_domain_sid_to_name: compare: %s\n", sid_str)); - if (sid_equal(sid_name_map[i].sid, sid)) { - fstrcpy(nt_domain, sid_name_map[i].name); - DEBUG(5,("map_domain_sid_to_name: found '%s'\n", nt_domain)); + while (special_domains[i].sid != NULL) { + DEBUG(5,("map_domain_sid_to_name: compare: %s\n", + sid_string_static(special_domains[i].sid))); + if (sid_equal(special_domains[i].sid, sid)) { + fstrcpy(nt_domain, special_domains[i].name); + DEBUG(5,("map_domain_sid_to_name: found '%s'\n", + nt_domain)); return True; } i++; } - DEBUG(5,("map_domain_sid_to_name: mapping for %s not found\n", sid_str)); - - return False; -} - -/************************************************************************** - Looks up a known username from one of the known domains. -***************************************************************************/ - -BOOL lookup_known_rid(DOM_SID *sid, uint32 rid, char *name, enum SID_NAME_USE *psid_name_use) -{ - int i = 0; - struct sid_name_map_info *psnm; - - if (!sid_name_map_initialized) - init_sid_name_map(); - - for(i = 0; sid_name_map[i].sid != NULL; i++) { - psnm = &sid_name_map[i]; - if(sid_equal(psnm->sid, sid)) { - int j; - for(j = 0; psnm->known_users && psnm->known_users[j].known_user_name != NULL; j++) { - if(rid == psnm->known_users[j].rid) { - DEBUG(5,("lookup_builtin_rid: rid = %u, domain = '%s', user = '%s'\n", - (unsigned int)rid, psnm->name, psnm->known_users[j].known_user_name )); - fstrcpy( name, psnm->known_users[j].known_user_name); - *psid_name_use = psnm->known_users[j].sid_name_use; - return True; - } - } - } - } + DEBUG(5,("map_domain_sid_to_name: mapping for %s not found\n", + sid_string_static(sid))); return False; } /************************************************************************** - Turns a domain name into a SID. - *** side-effect: if the domain name is NULL, it is set to our domain *** + Looks up a known username from one of the known domains. ***************************************************************************/ -BOOL map_domain_name_to_sid(DOM_SID *sid, char *nt_domain) +BOOL lookup_special_sid(const DOM_SID *sid, const char **domain, + const char **name, enum SID_NAME_USE *type) { - int i = 0; + int i; + DOM_SID dom_sid; + uint32 rid; + const known_sid_users *users = NULL; - if (nt_domain == NULL) { - DEBUG(5,("map_domain_name_to_sid: mapping NULL domain to our SID.\n")); - sid_copy(sid, get_global_sam_sid()); - return True; + sid_copy(&dom_sid, sid); + if (!sid_split_rid(&dom_sid, &rid)) { + DEBUG(2, ("Could not split rid from SID\n")); + return False; } - if (nt_domain[0] == 0) { - fstrcpy(nt_domain, global_myname()); - DEBUG(5,("map_domain_name_to_sid: overriding blank name to %s\n", nt_domain)); - sid_copy(sid, get_global_sam_sid()); - return True; + for (i=0; special_domains[i].sid != NULL; i++) { + if (sid_equal(&dom_sid, special_domains[i].sid)) { + *domain = special_domains[i].name; + users = special_domains[i].known_users; + break; + } } - DEBUG(5,("map_domain_name_to_sid: %s\n", nt_domain)); - - if (!sid_name_map_initialized) - init_sid_name_map(); + if (users == NULL) { + DEBUG(10, ("SID %s is no special sid\n", + sid_string_static(sid))); + return False; + } - while (sid_name_map[i].name != NULL) { - DEBUG(5,("map_domain_name_to_sid: compare: %s\n", sid_name_map[i].name)); - if (strequal(sid_name_map[i].name, nt_domain)) { - fstring sid_str; - sid_copy(sid, sid_name_map[i].sid); - sid_to_string(sid_str, sid_name_map[i].sid); - DEBUG(5,("map_domain_name_to_sid: found %s\n", sid_str)); + for (i=0; users[i].known_user_name != NULL; i++) { + if (rid == users[i].rid) { + *name = users[i].known_user_name; + *type = users[i].sid_name_use; return True; } - i++; } - DEBUG(0,("map_domain_name_to_sid: mapping to %s not found.\n", nt_domain)); + DEBUG(10, ("RID of special SID %s not found\n", + sid_string_static(sid))); + return False; } @@ -283,20 +201,17 @@ BOOL map_name_to_wellknown_sid(DOM_SID *sid, enum SID_NAME_USE *use, const char { int i, j; - if (!sid_name_map_initialized) - init_sid_name_map(); - DEBUG(10,("map_name_to_wellknown_sid: looking up %s\n", name)); - for (i=0; sid_name_map[i].sid != NULL; i++) { - const known_sid_users *users = sid_name_map[i].known_users; + for (i=0; special_domains[i].sid != NULL; i++) { + const known_sid_users *users = special_domains[i].known_users; if (users == NULL) continue; for (j=0; users[j].known_user_name != NULL; j++) { if ( strequal(users[j].known_user_name, name) ) { - sid_copy(sid, sid_name_map[i].sid); + sid_copy(sid, special_domains[i].sid); sid_append_rid(sid, users[j].rid); *use = users[j].sid_name_use; return True; diff --git a/source3/printing/notify.c b/source3/printing/notify.c index e289eba1b69..e71d9e6f259 100644 --- a/source3/printing/notify.c +++ b/source3/printing/notify.c @@ -176,13 +176,15 @@ static void print_notify_send_messages_to_printer(const char *printer, unsigned return; for (i = 0; i < num_pids; i++) { - unsigned int q_len = messages_pending_for_pid(pid_list[i]); + unsigned int q_len = messages_pending_for_pid(pid_to_procid(pid_list[i])); if (q_len > 1000) { DEBUG(5, ("print_notify_send_messages_to_printer: discarding notify to printer %s as queue length = %u\n", printer, q_len )); continue; } - message_send_pid_with_timeout(pid_list[i], MSG_PRINTER_NOTIFY2, buf, offset, True, timeout); + message_send_pid_with_timeout(pid_to_procid(pid_list[i]), + MSG_PRINTER_NOTIFY2, + buf, offset, True, timeout); } } @@ -328,7 +330,7 @@ static void send_notify_field_values(const char *sharename, uint32 type, static void send_notify_field_buffer(const char *sharename, uint32 type, uint32 field, uint32 id, uint32 len, - char *buffer) + const char *buffer) { struct spoolss_notify_msg *msg; @@ -349,7 +351,7 @@ static void send_notify_field_buffer(const char *sharename, uint32 type, msg->field = field; msg->id = id; msg->len = len; - msg->notify.data = buffer; + msg->notify.data = CONST_DISCARD(char *,buffer); send_spoolss_notify2_msg(msg); } @@ -484,7 +486,7 @@ void notify_printer_location(int snum, char *location) snum, strlen(location) + 1, location); } -void notify_printer_byname( const char *printername, uint32 change, char *value ) +void notify_printer_byname( const char *printername, uint32 change, const char *value ) { int snum = print_queue_snum(printername); int type = PRINTER_NOTIFY_TYPE; diff --git a/source3/printing/print_cups.c b/source3/printing/print_cups.c index e6064564dc8..8ae896fddf4 100644 --- a/source3/printing/print_cups.c +++ b/source3/printing/print_cups.c @@ -265,7 +265,7 @@ BOOL cups_cache_reload(void) * 'cups_job_delete()' - Delete a job. */ -static int cups_job_delete(int snum, struct printjob *pjob) +static int cups_job_delete(const char *sharename, const char *lprm_command, struct printjob *pjob) { int ret = 1; /* Return value */ http_t *http = NULL; /* HTTP connection to server */ @@ -275,7 +275,7 @@ static int cups_job_delete(int snum, struct printjob *pjob) char uri[HTTP_MAX_URI]; /* printer-uri attribute */ - DEBUG(5,("cups_job_delete(%d, %p (%d))\n", snum, pjob, pjob->sysjob)); + DEBUG(5,("cups_job_delete(%s, %p (%d))\n", sharename, pjob, pjob->sysjob)); /* * Make sure we don't ask for passwords... @@ -712,7 +712,7 @@ static int cups_queue_get(const char *sharename, *q = NULL; - /* HACK ALERT!!! The porblem with support the 'printer name' + /* HACK ALERT!!! The problem with support the 'printer name' option is that we key the tdb off the sharename. So we will overload the lpq_command string to pass in the printername (which is basically what we do for non-cups printers ... using diff --git a/source3/printing/print_generic.c b/source3/printing/print_generic.c index 256654179e6..b2484d5b433 100644 --- a/source3/printing/print_generic.c +++ b/source3/printing/print_generic.c @@ -27,7 +27,8 @@ run a given print command a null terminated list of value/substitute pairs is provided for local substitution strings ****************************************************************************/ -static int print_run_command(int snum, const char* printername, BOOL do_sub, char *command, int *outfd, ...) +static int print_run_command(int snum, const char* printername, BOOL do_sub, + const char *command, int *outfd, ...) { pstring syscmd; @@ -68,14 +69,13 @@ static int print_run_command(int snum, const char* printername, BOOL do_sub, cha /**************************************************************************** delete a print job ****************************************************************************/ -static int generic_job_delete(int snum, struct printjob *pjob) +static int generic_job_delete( const char *sharename, const char *lprm_command, struct printjob *pjob) { fstring jobstr; /* need to delete the spooled entry */ slprintf(jobstr, sizeof(jobstr)-1, "%d", pjob->sysjob); - return print_run_command(snum, PRINTERNAME(snum), True, - lp_lprmcommand(snum), NULL, + return print_run_command( -1, sharename, False, lprm_command, NULL, "%j", jobstr, "%T", http_timestring(pjob->starttime), NULL); diff --git a/source3/printing/print_iprint.c b/source3/printing/print_iprint.c index 33bbcb256ab..6193dbe2ca9 100644 --- a/source3/printing/print_iprint.c +++ b/source3/printing/print_iprint.c @@ -423,7 +423,7 @@ BOOL iprint_cache_reload(void) * 'iprint_job_delete()' - Delete a job. */ -static int iprint_job_delete(int snum, struct printjob *pjob) +static int iprint_job_delete(const char *sharename, const char *lprm_command, struct printjob *pjob) { int ret = 1; /* Return value */ http_t *http = NULL; /* HTTP connection to server */ @@ -434,7 +434,7 @@ static int iprint_job_delete(int snum, struct printjob *pjob) char httpPath[HTTP_MAX_URI]; /* path portion of the printer-uri */ - DEBUG(5,("iprint_job_delete(%d, %p (%d))\n", snum, pjob, pjob->sysjob)); + DEBUG(5,("iprint_job_delete(%s, %p (%d))\n", sharename, pjob, pjob->sysjob)); /* * Make sure we don't ask for passwords... @@ -476,7 +476,7 @@ static int iprint_job_delete(int snum, struct printjob *pjob) ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_LANGUAGE, "attributes-natural-language", NULL, language->language); - slprintf(uri, sizeof(uri) - 1, "ipp://%s/ipp/%s", iprint_server(), PRINTERNAME(snum)); + slprintf(uri, sizeof(uri) - 1, "ipp://%s/ipp/%s", iprint_server(), sharename); ippAddString(request, IPP_TAG_OPERATION, IPP_TAG_URI, "printer-uri", NULL, uri); @@ -489,7 +489,7 @@ static int iprint_job_delete(int snum, struct printjob *pjob) * Do the request and get back a response... */ - slprintf(httpPath, sizeof(httpPath) - 1, "/ipp/%s", PRINTERNAME(snum)); + slprintf(httpPath, sizeof(httpPath) - 1, "/ipp/%s", sharename); if ((response = cupsDoRequest(http, request, httpPath)) != NULL) { if (response->request.status.status_code >= IPP_OK_CONFLICT) { diff --git a/source3/printing/printing.c b/source3/printing/printing.c index 61470f15100..6e74095f719 100644 --- a/source3/printing/printing.c +++ b/source3/printing/printing.c @@ -691,6 +691,8 @@ struct traverse_struct { int qcount, snum, maxcount, total_jobs; const char *sharename; time_t lpq_time; + const char *lprm_command; + struct printif *print_if; }; /**************************************************************************** @@ -737,7 +739,7 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void /* if a job is not spooled and the process doesn't exist then kill it. This cleans up after smbd deaths */ - if (!process_exists(pjob.pid)) { + if (!process_exists_by_pid(pjob.pid)) { DEBUG(10,("traverse_fn_delete: pjob %u deleted due to !process_exists (%u)\n", (unsigned int)jobid, (unsigned int)pjob.pid )); pjob_delete(ts->sharename, jobid); @@ -750,9 +752,38 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void if ( pjob.smbjob ) { for (i=0;iqcount;i++) { - uint32 curr_jobid = print_parse_jobid(ts->queue[i].fs_file); - if (jobid == curr_jobid) + uint32 curr_jobid; + + if ( pjob.status == LPQ_DELETED ) + continue; + + curr_jobid = print_parse_jobid(ts->queue[i].fs_file); + + if (jobid == curr_jobid) { + + /* try to clean up any jobs that need to be deleted */ + + if ( pjob.status == LPQ_DELETING ) { + int result; + + result = (*(ts->print_if->job_delete))( + ts->sharename, ts->lprm_command, &pjob ); + + if ( result != 0 ) { + /* if we can't delete, then reset the job status */ + pjob.status = LPQ_QUEUED; + pjob_store(ts->sharename, jobid, &pjob); + } + else { + /* if we deleted the job, the remove the tdb record */ + pjob_delete(ts->sharename, jobid); + pjob.status = LPQ_DELETED; + } + + } + break; + } } } @@ -779,9 +810,10 @@ static int traverse_fn_delete(TDB_CONTEXT *t, TDB_DATA key, TDB_DATA data, void return 0; } - /* Save the pjob attributes we will store. */ - /* FIXME!!! This is the only place where queue->job + /* Save the pjob attributes we will store. + FIXME!!! This is the only place where queue->job represents the SMB jobid --jerry */ + ts->queue[i].job = jobid; ts->queue[i].size = pjob.size; ts->queue[i].page_count = pjob.page_count; @@ -840,7 +872,7 @@ static pid_t get_updating_pid(const char *sharename) updating_pid = IVAL(data.dptr, 0); SAFE_FREE(data.dptr); - if (process_exists(updating_pid)) + if (process_exists_by_pid(updating_pid)) return updating_pid; return (pid_t)-1; @@ -910,6 +942,7 @@ static int printjob_comp(print_queue_struct *j1, print_queue_struct *j2) /**************************************************************************** Store the sorted queue representation for later portmon retrieval. + Skip deleted jobs ****************************************************************************/ static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct *pts) @@ -923,13 +956,17 @@ static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct if (max_reported_jobs && (max_reported_jobs < pts->qcount)) pts->qcount = max_reported_jobs; - qcount = pts->qcount; + qcount = 0; /* Work out the size. */ data.dsize = 0; data.dsize += tdb_pack(NULL, 0, "d", qcount); for (i = 0; i < pts->qcount; i++) { + if ( queue[i].status == LPQ_DELETED ) + continue; + + qcount++; data.dsize += tdb_pack(NULL, 0, "ddddddff", (uint32)queue[i].job, (uint32)queue[i].size, @@ -947,6 +984,9 @@ static void store_queue_struct(struct tdb_print_db *pdb, struct traverse_struct len = 0; len += tdb_pack(data.dptr + len, data.dsize - len, "d", qcount); for (i = 0; i < pts->qcount; i++) { + if ( queue[i].status == LPQ_DELETED ) + continue; + len += tdb_pack(data.dptr + len, data.dsize - len, "ddddddff", (uint32)queue[i].job, (uint32)queue[i].size, @@ -1024,6 +1064,7 @@ static BOOL print_cache_expired(const char *sharename, BOOL check_pending) || (time_now - last_qscan_time) >= lp_lpqcachetime() || last_qscan_time > (time_now + MAX_CACHE_VALID_TIME)) { + uint32 u; time_t msg_pending_time; DEBUG(4, ("print_cache_expired: cache expired for queue %s " @@ -1039,8 +1080,8 @@ static BOOL print_cache_expired(const char *sharename, BOOL check_pending) snprintf(key, sizeof(key), "MSG_PENDING/%s", sharename); if ( check_pending - && tdb_fetch_uint32( pdb->tdb, key, (uint32*)&msg_pending_time ) - && msg_pending_time > 0 + && tdb_fetch_uint32( pdb->tdb, key, &u ) + && (msg_pending_time=u) > 0 && msg_pending_time <= time_now && (time_now - msg_pending_time) < 60 ) { @@ -1063,7 +1104,7 @@ done: static void print_queue_update_internal( const char *sharename, struct printif *current_printif, - char *lpq_command ) + char *lpq_command, char *lprm_command ) { int i, qcount; print_queue_struct *queue = NULL; @@ -1141,8 +1182,14 @@ static void print_queue_update_internal( const char *sharename, } pjob->sysjob = queue[i].job; - pjob->status = queue[i].status; + + /* don't reset the status on jobs to be deleted */ + + if ( pjob->status != LPQ_DELETING ) + pjob->status = queue[i].status; + pjob_store(sharename, jobid, pjob); + check_job_changed(sharename, jcdata, jobid); } @@ -1156,6 +1203,8 @@ static void print_queue_update_internal( const char *sharename, tstruct.total_jobs = 0; tstruct.lpq_time = time(NULL); tstruct.sharename = sharename; + tstruct.lprm_command = lprm_command; + tstruct.print_if = current_printif; tdb_traverse(pdb->tdb, traverse_fn_delete, (void *)&tstruct); @@ -1216,7 +1265,7 @@ static void print_queue_update_internal( const char *sharename, static void print_queue_update_with_lock( const char *sharename, struct printif *current_printif, - char *lpq_command ) + char *lpq_command, char *lprm_command ) { fstring keystr; struct tdb_print_db *pdb; @@ -1283,7 +1332,8 @@ static void print_queue_update_with_lock( const char *sharename, /* do the main work now */ - print_queue_update_internal( sharename, current_printif, lpq_command ); + print_queue_update_internal( sharename, current_printif, + lpq_command, lprm_command ); /* Delete our pid from the db. */ set_updating_pid(sharename, False); @@ -1293,17 +1343,19 @@ static void print_queue_update_with_lock( const char *sharename, /**************************************************************************** this is the receive function of the background lpq updater ****************************************************************************/ -static void print_queue_receive(int msg_type, pid_t src, void *buf, size_t msglen) +static void print_queue_receive(int msg_type, struct process_id src, + void *buf, size_t msglen) { fstring sharename; - pstring lpqcommand; + pstring lpqcommand, lprmcommand; int printing_type; size_t len; - len = tdb_unpack( buf, msglen, "fdP", + len = tdb_unpack( buf, msglen, "fdPP", sharename, &printing_type, - lpqcommand ); + lpqcommand, + lprmcommand ); if ( len == -1 ) { DEBUG(0,("print_queue_receive: Got invalid print queue update message\n")); @@ -1312,7 +1364,7 @@ static void print_queue_receive(int msg_type, pid_t src, void *buf, size_t msgle print_queue_update_with_lock(sharename, get_printer_fns_from_type(printing_type), - lpqcommand ); + lpqcommand, lprmcommand ); return; } @@ -1382,7 +1434,7 @@ static void print_queue_update(int snum, BOOL force) { fstring key; fstring sharename; - pstring lpqcommand; + pstring lpqcommand, lprmcommand; char *buffer = NULL; size_t len = 0; size_t newlen; @@ -1398,6 +1450,10 @@ static void print_queue_update(int snum, BOOL force) string_sub2( lpqcommand, "%p", PRINTERNAME(snum), sizeof(lpqcommand), False, False ); standard_sub_snum( snum, lpqcommand, sizeof(lpqcommand) ); + pstrcpy( lprmcommand, lp_lprmcommand(snum)); + string_sub2( lprmcommand, "%p", PRINTERNAME(snum), sizeof(lprmcommand), False, False ); + standard_sub_snum( snum, lprmcommand, sizeof(lprmcommand) ); + /* * Make sure that the background queue process exists. * Otherwise just do the update ourselves @@ -1406,7 +1462,7 @@ static void print_queue_update(int snum, BOOL force) if ( force || background_lpq_updater_pid == -1 ) { DEBUG(4,("print_queue_update: updating queue [%s] myself\n", sharename)); current_printif = get_printer_fns( snum ); - print_queue_update_with_lock( sharename, current_printif, lpqcommand ); + print_queue_update_with_lock( sharename, current_printif, lpqcommand, lprmcommand ); return; } @@ -1415,23 +1471,26 @@ static void print_queue_update(int snum, BOOL force) /* get the length */ - len = tdb_pack( buffer, len, "fdP", + len = tdb_pack( buffer, len, "fdPP", sharename, type, - lpqcommand ); + lpqcommand, + lprmcommand ); buffer = SMB_XMALLOC_ARRAY( char, len ); /* now pack the buffer */ - newlen = tdb_pack( buffer, len, "fdP", + newlen = tdb_pack( buffer, len, "fdPP", sharename, type, - lpqcommand ); + lpqcommand, + lprmcommand ); SMB_ASSERT( newlen == len ); DEBUG(10,("print_queue_update: Sending message -> printer = %s, " - "type = %d, lpq command = [%s]\n", sharename, type, lpqcommand )); + "type = %d, lpq command = [%s] lprm command = [%s]\n", + sharename, type, lpqcommand, lprmcommand )); /* here we set a msg pending record for other smbd processes to throttle the number of duplicate print_queue_update msgs @@ -1457,7 +1516,7 @@ static void print_queue_update(int snum, BOOL force) /* finally send the message */ become_root(); - message_send_pid(background_lpq_updater_pid, + message_send_pid(pid_to_procid(background_lpq_updater_pid), MSG_PRINTER_UPDATE, buffer, len, False); unbecome_root(); @@ -1806,8 +1865,6 @@ static BOOL print_job_delete1(int snum, uint32 jobid) int result = 0; struct printif *current_printif = get_printer_fns( snum ); - pjob = print_job_find(sharename, jobid); - if (!pjob) return False; @@ -1819,7 +1876,9 @@ static BOOL print_job_delete1(int snum, uint32 jobid) return True; /* Hrm - we need to be able to cope with deleting a job before it - has reached the spooler. */ + has reached the spooler. Just mark it as LPQ_DELETING and + let the print_queue_update() code rmeove the record */ + if (pjob->sysjob == -1) { DEBUG(5, ("attempt to delete job %u not seen by lpr\n", (unsigned int)jobid)); @@ -1830,24 +1889,31 @@ static BOOL print_job_delete1(int snum, uint32 jobid) pjob->status = LPQ_DELETING; pjob_store(sharename, jobid, pjob); - if (pjob->spooled && pjob->sysjob != -1) - result = (*(current_printif->job_delete))(snum, pjob); + if (pjob->spooled && pjob->sysjob != -1) + { + result = (*(current_printif->job_delete))( + PRINTERNAME(snum), + lp_lprmcommand(snum), + pjob); - /* Delete the tdb entry if the delete succeeded or the job hasn't - been spooled. */ + /* Delete the tdb entry if the delete succeeded or the job hasn't + been spooled. */ - if (result == 0) { - struct tdb_print_db *pdb = get_print_db_byname(sharename); - int njobs = 1; + if (result == 0) { + struct tdb_print_db *pdb = get_print_db_byname(sharename); + int njobs = 1; - if (!pdb) - return False; - pjob_delete(sharename, jobid); - /* Ensure we keep a rough count of the number of total jobs... */ - tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1); - release_print_db(pdb); + if (!pdb) + return False; + pjob_delete(sharename, jobid); + /* Ensure we keep a rough count of the number of total jobs... */ + tdb_change_int32_atomic(pdb->tdb, "INFO/total_jobs", &njobs, -1); + release_print_db(pdb); + } } + remove_from_jobs_changed( sharename, jobid ); + return (result == 0); } @@ -1877,7 +1943,8 @@ static BOOL is_owner(struct current_user *user, int snum, uint32 jobid) BOOL print_job_delete(struct current_user *user, int snum, uint32 jobid, WERROR *errcode) { const char* sharename = lp_const_servicename( snum ); - BOOL owner, deleted; + struct printjob *pjob; + BOOL owner; char *fname; *errcode = WERR_OK; @@ -1929,11 +1996,11 @@ pause, or resume print job. User name: %s. Printer name: %s.", print_queue_update(snum, True); - deleted = !print_job_exists(sharename, jobid); - if ( !deleted ) + pjob = print_job_find(sharename, jobid); + if ( pjob && (pjob->status != LPQ_DELETING) ) *errcode = WERR_ACCESS_DENIED; - return deleted; + return (pjob == NULL ); } /**************************************************************************** diff --git a/source3/printing/printing_db.c b/source3/printing/printing_db.c index b9b4b3c6b04..adea10dfa69 100644 --- a/source3/printing/printing_db.c +++ b/source3/printing/printing_db.c @@ -188,7 +188,7 @@ TDB_DATA get_printer_notify_pid_list(TDB_CONTEXT *tdb, const char *printer_name, /* Entry is dead if process doesn't exist or refcount is zero. */ - while ((i < data.dsize) && ((IVAL(data.dptr, i + 4) == 0) || !process_exists(pid))) { + while ((i < data.dsize) && ((IVAL(data.dptr, i + 4) == 0) || !process_exists_by_pid(pid))) { /* Refcount == zero is a logic error and should never happen. */ if (IVAL(data.dptr, i + 4) == 0) { diff --git a/source3/profile/profile.c b/source3/profile/profile.c index e6d34e68cda..0cf8c8e15bf 100644 --- a/source3/profile/profile.c +++ b/source3/profile/profile.c @@ -79,7 +79,8 @@ void profile_message(int msg_type, pid_t src, void *buf, size_t len) /**************************************************************************** receive a request profile level message ****************************************************************************/ -void reqprofile_message(int msg_type, pid_t src, void *buf, size_t len) +void reqprofile_message(int msg_type, struct process_id src, + void *buf, size_t len) { int level; @@ -88,7 +89,8 @@ void reqprofile_message(int msg_type, pid_t src, void *buf, size_t len) #else level = 0; #endif - DEBUG(1,("INFO: Received REQ_PROFILELEVEL message from PID %u\n",(unsigned int)src)); + DEBUG(1,("INFO: Received REQ_PROFILELEVEL message from PID %u\n", + (unsigned int)procid_to_pid(&src))); message_send_pid(src, MSG_PROFILELEVEL, &level, sizeof(int), True); } diff --git a/source3/registry/reg_db.c b/source3/registry/reg_db.c index afb5c613c80..ab8fc14d909 100644 --- a/source3/registry/reg_db.c +++ b/source3/registry/reg_db.c @@ -92,18 +92,10 @@ static BOOL init_registry_data( void ) fstring keyname, subkeyname; REGSUBKEY_CTR *subkeys; REGVAL_CTR *values; - uint32 *ctx; int i; const char *p, *p2; UNISTR2 data; - /* create a new top level talloc ctx */ - - if ( !(ctx = TALLOC_P( NULL, uint32 )) ) { - DEBUG(0,("init_registry_data: top level talloc() failure!\n")); - return False; - } - /* loop over all of the predefined paths and add each component */ for ( i=0; builtin_registry_paths[i] != NULL; i++ ) { @@ -140,7 +132,7 @@ static BOOL init_registry_data( void ) we are about to update the record. We just want any subkeys already present */ - if ( !(subkeys = TALLOC_ZERO_P( ctx, REGSUBKEY_CTR )) ) { + if ( !(subkeys = TALLOC_ZERO_P( NULL, REGSUBKEY_CTR )) ) { DEBUG(0,("talloc() failure!\n")); return False; } @@ -158,7 +150,7 @@ static BOOL init_registry_data( void ) /* loop over all of the predefined values and add each component */ for ( i=0; builtin_registry_values[i].path != NULL; i++ ) { - if ( !(values = TALLOC_ZERO_P( ctx, REGVAL_CTR )) ) { + if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) ) { DEBUG(0,("talloc() failure!\n")); return False; } diff --git a/source3/registry/reg_dynamic.c b/source3/registry/reg_dynamic.c index 7f8f664ec6e..b1a2a307554 100644 --- a/source3/registry/reg_dynamic.c +++ b/source3/registry/reg_dynamic.c @@ -37,7 +37,7 @@ static int netlogon_params( REGVAL_CTR *regvals ) { uint32 dwValue; - if ( !account_policy_get(AP_REFUSE_MACHINE_PW_CHANGE, &dwValue) ) + if ( !pdb_get_account_policy(AP_REFUSE_MACHINE_PW_CHANGE, &dwValue) ) dwValue = 0; regval_ctr_addvalue( regvals, "RefusePasswordChange", REG_DWORD, @@ -98,6 +98,99 @@ static int tcpip_params( REGVAL_CTR *regvals ) return regval_ctr_numvals( regvals ); } +/*********************************************************************** +***********************************************************************/ + +static int perflib_params( REGVAL_CTR *regvals ) +{ + int base_index = -1; + int last_counter = -1; + int last_help = -1; + int version = 0x00010001; + + base_index = reg_perfcount_get_base_index(); + regval_ctr_addvalue(regvals, "Base Index", REG_DWORD, (char *)&base_index, sizeof(base_index)); + last_counter = reg_perfcount_get_last_counter(base_index); + regval_ctr_addvalue(regvals, "Last Counter", REG_DWORD, (char *)&last_counter, sizeof(last_counter)); + last_help = reg_perfcount_get_last_help(last_counter); + regval_ctr_addvalue(regvals, "Last Help", REG_DWORD, (char *)&last_help, sizeof(last_help)); + regval_ctr_addvalue(regvals, "Version", REG_DWORD, (char *)&version, sizeof(version)); + + return regval_ctr_numvals( regvals ); +} + +/*********************************************************************** +***********************************************************************/ + +static int perflib_009_params( REGVAL_CTR *regvals ) +{ + int base_index; + int buffer_size; + char *buffer = NULL; + + base_index = reg_perfcount_get_base_index(); + buffer_size = reg_perfcount_get_counter_names(base_index, &buffer); + regval_ctr_addvalue(regvals, "Counter", REG_MULTI_SZ, buffer, buffer_size); + if(buffer_size > 0) + SAFE_FREE(buffer); + buffer_size = reg_perfcount_get_counter_help(base_index, &buffer); + regval_ctr_addvalue(regvals, "Help", REG_MULTI_SZ, buffer, buffer_size); + if(buffer_size > 0) + SAFE_FREE(buffer); + + return regval_ctr_numvals( regvals ); +} + +/*********************************************************************** +***********************************************************************/ + +static int hkpt_params( REGVAL_CTR *regvals ) +{ + uint32 base_index; + uint32 buffer_size; + char *buffer = NULL; + + /* This is ALMOST the same as perflib_009_params, but HKPT has + a "Counters" entry instead of a "Counter" key. */ + + base_index = reg_perfcount_get_base_index(); + buffer_size = reg_perfcount_get_counter_names(base_index, &buffer); + regval_ctr_addvalue(regvals, "Counters", REG_MULTI_SZ, buffer, buffer_size); + + if(buffer_size > 0) + SAFE_FREE(buffer); + + buffer_size = reg_perfcount_get_counter_help(base_index, &buffer); + regval_ctr_addvalue(regvals, "Help", REG_MULTI_SZ, buffer, buffer_size); + if(buffer_size > 0) + SAFE_FREE(buffer); + + return regval_ctr_numvals( regvals ); +} + +/*********************************************************************** +***********************************************************************/ + +static int current_version( REGVAL_CTR *values ) +{ + const char *sysroot_string = "c:\\Windows"; + fstring sysversion; + fstring value; + uint32 value_length; + + value_length = push_ucs2( value, value, sysroot_string, sizeof(value), + STR_TERMINATE|STR_NOALIGN ); + regval_ctr_addvalue( values, "SystemRoot", REG_SZ, value, value_length ); + + fstr_sprintf( sysversion, "%d.%d", lp_major_announce_version(), lp_minor_announce_version() ); + value_length = push_ucs2( value, value, sysversion, sizeof(value), + STR_TERMINATE|STR_NOALIGN ); + regval_ctr_addvalue( values, "CurrentVersion", REG_SZ, value, value_length ); + + + return regval_ctr_numvals( values ); +} + /*********************************************************************** Structure holding the registry paths and pointers to the value @@ -108,6 +201,10 @@ static struct reg_dyn_values dynamic_values[] = { { "HKLM/SYSTEM/CURRENTCONTROLSET/SERVICES/NETLOGON/PARAMETERS", &netlogon_params }, { "HKLM/SYSTEM/CURRENTCONTROLSET/CONTROL/PRODUCTOPTIONS", &prod_options }, { "HKLM/SYSTEM/CURRENTCONTROLSET/SERVICES/TCPIP/PARAMETERS", &tcpip_params }, + { "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PERFLIB", &perflib_params }, + { "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION/PERFLIB/009", &perflib_009_params }, + { "HKLM/SOFTWARE/MICROSOFT/WINDOWS NT/CURRENTVERSION", ¤t_version }, + { "HKPT", &hkpt_params }, { NULL, NULL } }; diff --git a/source3/registry/reg_eventlog.c b/source3/registry/reg_eventlog.c index b20eb046db8..bed9e1d59ae 100644 --- a/source3/registry/reg_eventlog.c +++ b/source3/registry/reg_eventlog.c @@ -1,7 +1,8 @@ /* * Unix SMB/CIFS implementation. * Virtual Windows Registry Layer - * Copyright (C) Marcin Krzysztof Porwit 2005. + * Copyright (C) Marcin Krzysztof Porwit 2005, + * Copyright (C) Gerald (Jerry) Carter 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 @@ -20,288 +21,168 @@ #include "includes.h" + /********************************************************************** - handle enumeration of values AT KEY_EVENTLOG - *********************************************************************/ - -static int eventlog_topkey_values( char *key, REGVAL_CTR *val ) + Enumerate registry subkey names given a registry path. +*********************************************************************/ + +static int elog_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys ) { - int num_values = 0; - char *keystr, *key2 = NULL; - char *base, *new_path; - fstring evtlogname; - UNISTR2 data; - int iDisplayNameId; - int iMaxSize; - - /* - * TODO - callout to get these values... - */ + const char **elogs = lp_eventlog_list(); + char *path; + int i; - if ( key ) - { - key2 = SMB_STRDUP( key ); - keystr = key2; - reg_split_path( keystr, &base, &new_path ); + path = reg_remaining_path( key + strlen(KEY_EVENTLOG) ); - iDisplayNameId = 0x00000100; - iMaxSize= 0x00080000; - - fstrcpy( evtlogname, base ); - DEBUG(10,("eventlog_topkey_values: subkey root=> [%s] subkey path=>[%s]\n", base,new_path)); - - if ( !new_path ) - { - iDisplayNameId = 0x01; - regval_ctr_addvalue( val, "ErrorControl", REG_DWORD, (char*)&iDisplayNameId, sizeof(int) ); - - init_unistr2( &data, "EventLog", UNI_STR_TERMINATE); - regval_ctr_addvalue( val, "DisplayName", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); - - num_values = regval_ctr_numvals( val ); - - - num_values = 0; - } - } + DEBUG(10,("elog_fetch_keys: entire key => [%s], subkey => [%s]\n", + key, path)); - SAFE_FREE( key2 ); - return num_values; -} + if ( !path ) { + + if ( !elogs || !*elogs ) + return 0; -/********************************************************************** - handle enumeration of values below KEY_EVENTLOG\ - *********************************************************************/ - -static int eventlog_subkey_values( char *key, REGVAL_CTR *val ) -{ - int num_values = 0; - char *keystr, *key2 = NULL; - char *base, *new_path; - fstring evtlogname; - UNISTR2 data; - int iDisplayNameId; - int iMaxSize; - int iRetention; - - /* - * TODO - callout to get these values... - */ - - if ( !key ) - return num_values; - - key2 = SMB_STRDUP( key ); - keystr = key2; - reg_split_path( keystr, &base, &new_path ); - - iDisplayNameId = 0x00000100; - /* MaxSize is limited to 0xFFFF0000 (UINT_MAX - USHRT_MAX) as per MSDN documentation */ - iMaxSize= 0xFFFF0000; - /* records in the samba log are not overwritten */ - iRetention = 0xFFFFFFFF; - - fstrcpy( evtlogname, base ); - DEBUG(10,("eventlog_subpath_values_printer: eventlogname [%s]\n", base)); - DEBUG(10,("eventlog_subpath_values_printer: new_path [%s]\n", new_path)); - if ( !new_path ) - { -#if 0 - regval_ctr_addvalue( val, "DisplayNameId", REG_DWORD, (char*)&iDisplayNameId, sizeof(int) ); - - init_unistr2( &data, "%SystemRoot%\\system32\\els.dll", UNI_STR_TERMINATE); - regval_ctr_addvalue( val, "DisplayNameFile", REG_EXPAND_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); -#endif - regval_ctr_addvalue( val, "MaxSize", REG_DWORD, (char*)&iMaxSize, sizeof(int)); - regval_ctr_addvalue( val, "Retention", REG_DWORD, (char *)&iRetention, sizeof(int)); -#if 0 - init_unistr2( &data, lp_logfile(), UNI_STR_TERMINATE); - regval_ctr_addvalue( val, "File", REG_EXPAND_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); -#endif - init_unistr2( &data, base, UNI_STR_TERMINATE); - regval_ctr_addvalue( val, "PrimaryModule", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); - - init_unistr2( &data, base, UNI_STR_TERMINATE); - regval_ctr_addvalue( val, "Sources", REG_MULTI_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); - - num_values = regval_ctr_numvals( val ); - - } - else - { - iDisplayNameId = 0x07; - regval_ctr_addvalue( val, "CategoryCount", REG_DWORD, (char*)&iDisplayNameId, sizeof(int) ); - - init_unistr2( &data, "%SystemRoot%\\system32\\eventlog.dll", UNI_STR_TERMINATE); - regval_ctr_addvalue( val, "CategoryMessageFile", REG_EXPAND_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); - - num_values = regval_ctr_numvals( val ); + DEBUG(10,("elog_fetch_keys: Adding eventlog subkeys from smb.conf\n")); + + for ( i=0; elogs[i]; i++ ) + regsubkey_ctr_addkey( subkeys, elogs[i] ); + + return regsubkey_ctr_numkeys( subkeys ); + } - num_values = 0; - } - - SAFE_FREE( key2 ); - return num_values; -} + /* if we get / then we don't add anymore */ + if ( strchr( path, '\\' ) ) { + DEBUG(10,("elog_fetch_keys: Not adding subkey to %s\n",path)); + return 0; + } -/********************************************************************** - It is safe to assume that every registry path passed into on of - the exported functions here begins with KEY_EVENTLOG else - these functions would have never been called. This is a small utility - function to strip the beginning of the path and make a copy that the - caller can modify. Note that the caller is responsible for releasing - the memory allocated here. - **********************************************************************/ + /* add in a subkey with the same name as the eventlog... */ -static char* trim_eventlog_reg_path( const char *path ) -{ - const char *p; - uint16 key_len = strlen(KEY_EVENTLOG); - - /* - * sanity check...this really should never be True. - * It is only here to prevent us from accessing outside - * the path buffer in the extreme case. - */ - - if ( strlen(path) < key_len ) { - DEBUG(0,("trim_reg_path: Registry path too short! [%s]\n", path)); - DEBUG(0,("trim_reg_path: KEY_EVENTLOG => [%s]!\n", KEY_EVENTLOG)); - return NULL; - } - - - p = path + strlen( KEY_EVENTLOG ); - - if ( *p == '\\' ) - p++; - - if ( *p ) - return SMB_STRDUP(p); - else - return NULL; -} -/********************************************************************** - Enumerate registry subkey names given a registry path. - Caller is responsible for freeing memory to **subkeys - *********************************************************************/ -static int eventlog_subkey_info( const char *key, REGSUBKEY_CTR *subkey_ctr ) -{ - char *path; - BOOL top_level = False; - int num_subkeys = 0; - const char **evtlog_list; - - path = trim_eventlog_reg_path( key ); - DEBUG(10,("eventlog_subkey_info: entire key=>[%s] SUBkey=>[%s]\n", key,path)); - - /* check to see if we are dealing with the top level key */ - num_subkeys = 0; - - if ( !path ) - top_level = True; - - num_subkeys = 0; - if ( !(evtlog_list = lp_eventlog_list()) ) { - SAFE_FREE(path); - return num_subkeys; - } + DEBUG(10,("elog_fetch_keys: Looking to add eventlog subkey to %s\n",path)); - - if ( top_level ) - { - /* todo - get the eventlog subkey values from the smb.conf file - for ( num_subkeys=0; num_subkeys[%s]\n",*evtlog_list)); - regsubkey_ctr_addkey( subkey_ctr, *evtlog_list); - evtlog_list++; - num_subkeys++; - } - } - else - { - while (*evtlog_list && (0==num_subkeys) ) - { - if (0 == StrCaseCmp(path,*evtlog_list)) - { - DEBUG(10,("eventlog_subkey_info: Adding subkey [%s] for key =>[%s]\n",path,*evtlog_list)); - regsubkey_ctr_addkey( subkey_ctr, *evtlog_list); - num_subkeys = 1; - } - evtlog_list++; + /* look for a match */ + + if ( !elogs ) + return -1; + + for ( i=0; elogs[i]; i++ ) { + /* just verify that the keyname is a valid log name */ + if ( strequal( path, elogs[i] ) ) + return 0; } - if (0==num_subkeys) - DEBUG(10,("eventlog_subkey_info: No match on SUBkey=>[%s]\n", path)); - } - - SAFE_FREE( path ); - return num_subkeys; + return -1; } /********************************************************************** Enumerate registry values given a registry path. Caller is responsible for freeing memory - *********************************************************************/ +*********************************************************************/ -static int eventlog_value_info( const char *key, REGVAL_CTR *val ) +static int elog_fetch_values( const char *key, REGVAL_CTR *values ) { - char *path; - BOOL top_level = False; - int num_values = 0; + char *path; + uint32 uiDisplayNameId, uiMaxSize, uiRetention; + char *base, *new_path; + UNISTR2 data; - DEBUG(10,("eventlog_value_info: key=>[%s]\n", key)); + DEBUG(10,("elog_fetch_values: key=>[%s]\n", key)); - path = trim_eventlog_reg_path( key ); + path = reg_remaining_path( key + strlen(KEY_EVENTLOG) ); /* check to see if we are dealing with the top level key */ - if ( !path ) - top_level = True; - if ( top_level ) - num_values = eventlog_topkey_values(path,val); - else - { - DEBUG(10,("eventlog_value_info: SUBkey=>[%s]\n", path)); - num_values = eventlog_subkey_values(path,val); - } - return num_values; + if ( !path ) + return regdb_fetch_values( KEY_EVENTLOG, values ); + + /* deal with a log name */ + + reg_split_path( path, &base, &new_path ); + + /* MaxSize is limited to 0xFFFF0000 (UINT_MAX - USHRT_MAX) as per MSDN documentation */ + + + if ( !new_path ) { + + /* try to fetch from the registry */ + + regdb_fetch_values( key, values ); + + /* just verify one of the important keys. If this + fails, then assume the values have not been initialized */ + + if ( regval_ctr_getvalue( values, "Retention" ) ) + return regval_ctr_numvals( values ); + + /* hard code some initial values */ + + uiDisplayNameId = 0x00000100; + uiMaxSize = 0x00080000; + uiRetention = 0x93A80; + + regval_ctr_addvalue( values, "MaxSize", REG_DWORD, (char*)&uiMaxSize, sizeof(uint32)); + regval_ctr_addvalue( values, "Retention", REG_DWORD, (char *)&uiRetention, sizeof(uint32)); + + init_unistr2( &data, base, UNI_STR_TERMINATE); + regval_ctr_addvalue( values, "PrimaryModule", REG_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); + + init_unistr2( &data, base, UNI_STR_TERMINATE); + regval_ctr_addvalue( values, "Sources", REG_MULTI_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); + + /* store them for later updates. Complain if this fails but continue on */ + + if ( !regdb_store_values( key, values ) ) { + DEBUG(0,("elog_fetch_values: Failed to store initial values for log [%s]\n", + base )); + } + + return regval_ctr_numvals( values ); + } + +#if 0 + /* hmmm....what to do here? A subkey underneath the log name ? */ + + uiDisplayNameId = 0x07; + regval_ctr_addvalue( values, "CategoryCount", REG_DWORD, (char*)&uiDisplayNameId, sizeof(uint32) ); + + init_unistr2( &data, "%SystemRoot%\\system32\\eventlog.dll", UNI_STR_TERMINATE); + regval_ctr_addvalue( values, "CategoryMessageFile", REG_EXPAND_SZ, (char*)data.buffer, data.uni_str_len*sizeof(uint16) ); +#endif + + return regval_ctr_numvals( values ); } /********************************************************************** - Stub function which always returns failure since we don't want - people storing eventlog information directly via registry calls - (for now at least) - *********************************************************************/ -static BOOL eventlog_store_subkey( const char *key, REGSUBKEY_CTR *subkeys ) +*********************************************************************/ + +static BOOL elog_store_keys( const char *key, REGSUBKEY_CTR *subkeys ) { + /* cannot create any subkeys here */ + return False; } /********************************************************************** - Stub function which always returns failure since we don't want - people storing eventlog information directly via registry calls - (for now at least) - *********************************************************************/ -static BOOL eventlog_store_value( const char *key, REGVAL_CTR *val ) + Allow storing of particular values related to eventlog operation. +*********************************************************************/ + +static BOOL elog_store_value( const char *key, REGVAL_CTR *values ) { - return False; + /* the client had to have a valid handle to get here + so just hand off to the registry tdb */ + + return regdb_store_values( key, values ); } -/* - * Table of function pointers for accessing eventlog data - */ +/******************************************************************** + Table of function pointers for accessing eventlog data + *******************************************************************/ + REGISTRY_OPS eventlog_ops = { - eventlog_subkey_info, - eventlog_value_info, - eventlog_store_subkey, - eventlog_store_value, + elog_fetch_keys, + elog_fetch_values, + elog_store_keys, + elog_store_value, NULL }; diff --git a/source3/registry/reg_frontend.c b/source3/registry/reg_frontend.c index d6e02884616..f41c5885bc4 100644 --- a/source3/registry/reg_frontend.c +++ b/source3/registry/reg_frontend.c @@ -38,15 +38,70 @@ REGISTRY_HOOK reg_hooks[] = { { KEY_PRINTING, &printing_ops }, { KEY_PRINTING_2K, &printing_ops }, { KEY_PRINTING_PORTS, &printing_ops }, -#if 0 { KEY_EVENTLOG, &eventlog_ops }, -#endif { KEY_SHARES, &shares_reg_ops }, #endif { NULL, NULL } }; +static struct generic_mapping reg_generic_map = + { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL }; + +/******************************************************************** +********************************************************************/ + +static NTSTATUS registry_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token, + uint32 access_desired, uint32 *access_granted ) +{ + NTSTATUS result; + + if ( geteuid() == sec_initial_uid() ) { + DEBUG(5,("registry_access_check: using root's token\n")); + token = get_root_nt_token(); + } + + se_map_generic( &access_desired, ®_generic_map ); + se_access_check( sec_desc, token, access_desired, access_granted, &result ); + + return result; +} + +/******************************************************************** +********************************************************************/ + +static SEC_DESC* construct_registry_sd( TALLOC_CTX *ctx ) +{ + SEC_ACE ace[2]; + SEC_ACCESS mask; + size_t i = 0; + SEC_DESC *sd; + SEC_ACL *acl; + size_t sd_size; + + /* basic access for Everyone */ + + init_sec_access(&mask, REG_KEY_READ ); + init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + /* Full Access 'BUILTIN\Administrators' */ + + init_sec_access(&mask, REG_KEY_ALL ); + init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + + /* create the security descriptor */ + + if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) ) + return NULL; + + if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) ) + return NULL; + + return sd; +} + + /*********************************************************************** Open the registry database and initialize the REGISTRY_HOOK cache ***********************************************************************/ @@ -55,11 +110,12 @@ BOOL init_registry( void ) { int i; + if ( !init_registry_db() ) { DEBUG(0,("init_registry: failed to initialize the registry tdb!\n")); return False; } - + /* build the cache tree of registry hooks */ reghook_cache_init(); @@ -72,6 +128,14 @@ BOOL init_registry( void ) if ( DEBUGLEVEL >= 20 ) reghook_dump_cache(20); + /* inform the external eventlog machinery of the change */ + + eventlog_refresh_external_parameters( get_root_nt_token() ); + + /* add any services keys */ + + svcctl_init_keys(); + return True; } @@ -277,4 +341,70 @@ BOOL regkey_access_check( REGISTRY_KEY *key, uint32 requested, uint32 *granted, return key->hook->ops->reg_access_check( key->name, requested, granted, token ); } +/*********************************************************************** +***********************************************************************/ + +WERROR regkey_open_internal( REGISTRY_KEY **regkey, const char *path, + NT_USER_TOKEN *token, uint32 access_desired ) +{ + WERROR result = WERR_OK; + REGISTRY_KEY *keyinfo; + REGSUBKEY_CTR *subkeys = NULL; + uint32 access_granted; + + DEBUG(7,("regkey_open_internal: name = [%s]\n", path)); + if ( !(*regkey = TALLOC_ZERO_P(NULL, REGISTRY_KEY)) ) + return WERR_NOMEM; + + keyinfo = *regkey; + + /* initialization */ + + keyinfo->type = REG_KEY_GENERIC; + keyinfo->name = talloc_strdup( keyinfo, path ); + + + /* Tag this as a Performance Counter Key */ + + if( StrnCaseCmp(path, KEY_HKPD, strlen(KEY_HKPD)) == 0 ) + keyinfo->type = REG_KEY_HKPD; + + /* Look up the table of registry I/O operations */ + + if ( !(keyinfo->hook = reghook_cache_find( keyinfo->name )) ) { + DEBUG(0,("open_registry_key: Failed to assigned a REGISTRY_HOOK to [%s]\n", + keyinfo->name )); + result = WERR_BADFILE; + goto done; + } + + /* check if the path really exists; failed is indicated by -1 */ + /* if the subkey count failed, bail out */ + + if ( !(subkeys = TALLOC_ZERO_P( keyinfo, REGSUBKEY_CTR )) ) { + result = WERR_NOMEM; + goto done; + } + + if ( fetch_reg_keys( keyinfo, subkeys ) == -1 ) { + result = WERR_BADFILE; + goto done; + } + + TALLOC_FREE( subkeys ); + + if ( !regkey_access_check( keyinfo, access_desired, &access_granted, token ) ) { + result = WERR_ACCESS_DENIED; + goto done; + } + + keyinfo->access_granted = access_granted; + +done: + if ( !W_ERROR_IS_OK(result) ) { + TALLOC_FREE( *regkey ); + } + + return result; +} diff --git a/source3/registry/reg_objects.c b/source3/registry/reg_objects.c index 70410a67409..05567d561c6 100644 --- a/source3/registry/reg_objects.c +++ b/source3/registry/reg_objects.c @@ -236,7 +236,7 @@ uint32 regval_type( REGISTRY_VALUE *val ) /*********************************************************************** Retreive a pointer to a specific value. Caller shoud dup the structure - since this memory may go away with a regval_ctr_destroy() + since this memory will go away when the ctr is free()'d **********************************************************************/ REGISTRY_VALUE* regval_ctr_specific_value( REGVAL_CTR *ctr, uint32 idx ) @@ -385,3 +385,29 @@ REGISTRY_VALUE* regval_ctr_getvalue( REGVAL_CTR *ctr, const char *name ) return NULL; } +/*********************************************************************** + return the data_p as a uint32 + **********************************************************************/ + +uint32 regval_dword( REGISTRY_VALUE *val ) +{ + uint32 data; + + data = IVAL( regval_data_p(val), 0 ); + + return data; +} + +/*********************************************************************** + return the data_p as a character string + **********************************************************************/ + +char* regval_sz( REGISTRY_VALUE *val ) +{ + static pstring data; + + rpcstr_pull( data, regval_data_p(val), sizeof(data), regval_size(val), 0 ); + + return data; +} + diff --git a/source3/registry/reg_perfcount.c b/source3/registry/reg_perfcount.c new file mode 100644 index 00000000000..609f86da6cb --- /dev/null +++ b/source3/registry/reg_perfcount.c @@ -0,0 +1,1225 @@ +#include "includes.h" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_SRV + +#define PERFCOUNT_MAX_LEN 256 + +uint32 reg_perfcount_get_base_index(void) +{ + pstring fname; + TDB_CONTEXT *names; + TDB_DATA kbuf, dbuf; + char key[] = "1"; + uint32 retval = 0; + char buf[PERFCOUNT_MAX_LEN]; + const char *counter_dir = lp_counters_dir(); + + + if ( !*counter_dir ) + return 0; + + pstr_sprintf( fname, "%s/names.tdb", counter_dir ); + + names = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444); + + if ( !names ) { + DEBUG(1, ("reg_perfcount_get_base_index: unable to open [%s].\n", fname)); + return 0; + } + /* needs to read the value of key "1" from the counter_names.tdb file, as that is + where the total number of counters is stored. We're assuming no holes in the + enumeration. + The format for the counter_names.tdb file is: + key value + 1 num_counters + 2 perf_counter1 + 3 perf_counter1_help + 4 perf_counter2 + 5 perf_counter2_help + even_num perf_counter + even_num+1 perf_counter_help + and so on. + So last_counter becomes num_counters*2, and last_help will be last_counter+1 */ + kbuf.dptr = key; + kbuf.dsize = strlen(key); + dbuf = tdb_fetch(names, kbuf); + if(dbuf.dptr == NULL) + { + DEBUG(1, ("reg_perfcount_get_base_index: failed to find key \'1\' in [%s].\n", fname)); + tdb_close(names); + return 0; + } + else + { + tdb_close(names); + memset(buf, 0, PERFCOUNT_MAX_LEN); + memcpy(buf, dbuf.dptr, dbuf.dsize); + retval = (uint32)atoi(buf); + SAFE_FREE(dbuf.dptr); + return retval; + } + return 0; +} + +uint32 reg_perfcount_get_last_counter(uint32 base_index) +{ + uint32 retval; + + if(base_index == 0) + retval = 0; + else + retval = base_index * 2; + + return retval; +} + +uint32 reg_perfcount_get_last_help(uint32 last_counter) +{ + uint32 retval; + + if(last_counter == 0) + retval = 0; + else + retval = last_counter + 1; + + return retval; +} + +static uint32 _reg_perfcount_multi_sz_from_tdb(TDB_CONTEXT *tdb, + int keyval, + char **retbuf, + uint32 buffer_size) +{ + TDB_DATA kbuf, dbuf; + char temp[256]; + char *buf1 = *retbuf, *buf2 = NULL; + uint32 working_size = 0; + UNISTR2 name_index, name; + + memset(temp, 0, sizeof(temp)); + snprintf(temp, sizeof(temp), "%d", keyval); + kbuf.dptr = temp; + kbuf.dsize = strlen(temp); + dbuf = tdb_fetch(tdb, kbuf); + if(dbuf.dptr == NULL) + { + /* If a key isn't there, just bypass it -- this really shouldn't + happen unless someone's mucking around with the tdb */ + DEBUG(3, ("_reg_perfcount_multi_sz_from_tdb: failed to find key [%s] in [%s].\n", + temp, tdb->name)); + return buffer_size; + } + /* First encode the name_index */ + working_size = (kbuf.dsize + 1)*sizeof(uint16); + buf2 = SMB_REALLOC(buf1, buffer_size + working_size); + if(!buf2) + { + SAFE_FREE(buf1); + buffer_size = 0; + return buffer_size; + } + buf1 = buf2; + init_unistr2(&name_index, kbuf.dptr, UNI_STR_TERMINATE); + memcpy(buf1+buffer_size, (char *)name_index.buffer, working_size); + buffer_size += working_size; + /* Now encode the actual name */ + working_size = (dbuf.dsize + 1)*sizeof(uint16); + buf2 = SMB_REALLOC(buf1, buffer_size + working_size); + if(!buf2) + { + SAFE_FREE(buf1); + buffer_size = 0; + return buffer_size; + } + buf1 = buf2; + memset(temp, 0, sizeof(temp)); + memcpy(temp, dbuf.dptr, dbuf.dsize); + SAFE_FREE(dbuf.dptr); + init_unistr2(&name, temp, UNI_STR_TERMINATE); + memcpy(buf1+buffer_size, (char *)name.buffer, working_size); + buffer_size += working_size; + + *retbuf = buf1; + + return buffer_size; +} + +uint32 reg_perfcount_get_counter_help(uint32 base_index, char **retbuf) +{ + char *buf1 = NULL, *buf2 = NULL; + uint32 buffer_size = 0; + TDB_CONTEXT *names; + pstring fname; + int i; + + if(base_index == 0) + return 0; + + pstrcpy(fname, lp_counters_dir()); + pstrcat(fname, "/names.tdb"); + + names = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444); + + if(names == NULL) + { + DEBUG(1, ("reg_perfcount_get_counter_help: unable to open [%s].\n", fname)); + return 0; + } + + for(i = 1; i <= base_index; i++) + { + buffer_size = _reg_perfcount_multi_sz_from_tdb(names, (i*2)+1, retbuf, buffer_size); + } + tdb_close(names); + + /* Now terminate the MULTI_SZ with a double unicode NULL */ + buf1 = *retbuf; + buf2 = SMB_REALLOC(buf1, buffer_size + 2); + if(!buf2) + { + SAFE_FREE(buf1); + buffer_size = 0; + } + else + { + buf1 = buf2; + buf1[buffer_size++] = '\0'; + buf1[buffer_size++] = '\0'; + } + + *retbuf = buf1; + + return buffer_size; +} + +uint32 reg_perfcount_get_counter_names(uint32 base_index, char **retbuf) +{ + char *buf1 = NULL, *buf2 = NULL; + uint32 buffer_size = 0; + TDB_CONTEXT *names; + pstring fname; + int i; + + if(base_index == 0) + return 0; + + pstrcpy(fname, lp_counters_dir()); + pstrcat(fname, "/names.tdb"); + + names = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444); + + if(names == NULL) + { + DEBUG(1, ("reg_perfcount_get_counter_names: unable to open [%s].\n", fname)); + return 0; + } + + buffer_size = _reg_perfcount_multi_sz_from_tdb(names, 1, retbuf, buffer_size); + + for(i = 1; i <= base_index; i++) + { + buffer_size = _reg_perfcount_multi_sz_from_tdb(names, i*2, retbuf, buffer_size); + } + tdb_close(names); + + /* Now terminate the MULTI_SZ with a double unicode NULL */ + buf1 = *retbuf; + buf2 = SMB_REALLOC(buf1, buffer_size + 2); + if(!buf2) + { + SAFE_FREE(buf1); + buffer_size = 0; + } + else + { + buf1 = buf2; + buf1[buffer_size++] = '\0'; + buf1[buffer_size++] = '\0'; + } + + *retbuf=buf1; + + return buffer_size; +} + +static void _reg_perfcount_make_key(TDB_DATA *key, + char *buf, + int buflen, + int key_part1, + const char *key_part2) +{ + memset(buf, 0, buflen); + if(key_part2 != NULL) + snprintf(buf, buflen,"%d%s", key_part1, key_part2); + else + snprintf(buf, buflen, "%d", key_part1); + + key->dptr = buf; + key->dsize = strlen(buf); + + return; +} + +static BOOL _reg_perfcount_isparent(TDB_DATA data) +{ + if(data.dsize > 0) + { + if(data.dptr[0] == 'p') + return True; + else + return False; + } + return False; +} + +static BOOL _reg_perfcount_ischild(TDB_DATA data) +{ + if(data.dsize > 0) + { + if(data.dptr[0] == 'c') + return True; + else + return False; + } + return False; +} + +static uint32 _reg_perfcount_get_numinst(int objInd, TDB_CONTEXT *names) +{ + TDB_DATA key, data; + char buf[PERFCOUNT_MAX_LEN]; + + _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, objInd, "inst"); + data = tdb_fetch(names, key); + + if(data.dptr == NULL) + return (uint32)PERF_NO_INSTANCES; + + memset(buf, 0, PERFCOUNT_MAX_LEN); + memcpy(buf, data.dptr, data.dsize); + return (uint32)atoi(buf); +} + +static BOOL _reg_perfcount_add_object(PERF_DATA_BLOCK *block, + prs_struct *ps, + int num, + TDB_DATA data, + TDB_CONTEXT *names) +{ + int i; + BOOL success = False; + PERF_OBJECT_TYPE *obj; + + block->objects = (PERF_OBJECT_TYPE *)TALLOC_REALLOC_ARRAY(ps->mem_ctx, + block->objects, + PERF_OBJECT_TYPE, + block->NumObjectTypes+1); + if(block->objects == NULL) + return False; + obj = &(block->objects[block->NumObjectTypes]); + memset((void *)&(block->objects[block->NumObjectTypes]), 0, sizeof(PERF_OBJECT_TYPE)); + block->objects[block->NumObjectTypes].ObjectNameTitleIndex = num; + block->objects[block->NumObjectTypes].ObjectNameTitlePointer = 0; + block->objects[block->NumObjectTypes].ObjectHelpTitleIndex = num+1; + block->objects[block->NumObjectTypes].ObjectHelpTitlePointer = 0; + block->objects[block->NumObjectTypes].NumCounters = 0; + block->objects[block->NumObjectTypes].DefaultCounter = 0; + block->objects[block->NumObjectTypes].NumInstances = _reg_perfcount_get_numinst(num, names); + block->objects[block->NumObjectTypes].counters = NULL; + block->objects[block->NumObjectTypes].instances = NULL; + block->objects[block->NumObjectTypes].counter_data.ByteLength = sizeof(uint32); + block->objects[block->NumObjectTypes].counter_data.data = NULL; + block->objects[block->NumObjectTypes].DetailLevel = PERF_DETAIL_NOVICE; + block->NumObjectTypes+=1; + + for(i = 0; i < (int)obj->NumInstances; i++) + { + success = _reg_perfcount_add_instance(obj, ps, i, names); + } + + return True; +} + +BOOL _reg_perfcount_get_counter_data(TDB_DATA key, TDB_DATA *data) +{ + TDB_CONTEXT *counters; + + pstring fname; + + pstrcpy(fname, lp_counters_dir()); + pstrcat(fname, "/data.tdb"); + + counters = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444); + + if(counters == NULL) + { + DEBUG(1, ("reg_perfcount_get_counter_data: unable to open [%s].\n", fname)); + return False; + } + + *data = tdb_fetch(counters, key); + + tdb_close(counters); + + return True; +} + +static uint32 _reg_perfcount_get_size_field(uint32 CounterType) +{ + uint32 retval; + + retval = CounterType; + + /* First mask out reserved lower 8 bits */ + retval = retval & 0xFFFFFF00; + retval = retval << 22; + retval = retval >> 22; + + return retval; +} + +static uint32 _reg_perfcount_compute_scale(long long int data) +{ + int scale = 0; + if(data == 0) + return scale; + while(data > 100) + { + data /= 10; + scale--; + } + while(data < 10) + { + data *= 10; + scale++; + } + + return (uint32)scale; +} + +static BOOL _reg_perfcount_get_counter_info(PERF_DATA_BLOCK *block, + prs_struct *ps, + int CounterIndex, + PERF_OBJECT_TYPE *obj, + TDB_CONTEXT *names) +{ + TDB_DATA key, data; + char buf[PERFCOUNT_MAX_LEN]; + size_t dsize, padding; + long int data32, dbuf[2]; + long long int data64; + uint32 counter_size; + + obj->counters[obj->NumCounters].DefaultScale = 0; + dbuf[0] = dbuf[1] = 0; + padding = 0; + + _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, CounterIndex, "type"); + data = tdb_fetch(names, key); + if(data.dptr == NULL) + { + DEBUG(3, ("_reg_perfcount_get_counter_info: No type data for counter [%d].\n", CounterIndex)); + return False; + } + memset(buf, 0, PERFCOUNT_MAX_LEN); + memcpy(buf, data.dptr, data.dsize); + obj->counters[obj->NumCounters].CounterType = atoi(buf); + DEBUG(10, ("_reg_perfcount_get_counter_info: Got type [%d] for counter [%d].\n", + obj->counters[obj->NumCounters].CounterType, CounterIndex)); + free(data.dptr); + + /* Fetch the actual data */ + _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, CounterIndex, ""); + _reg_perfcount_get_counter_data(key, &data); + if(data.dptr == NULL) + { + DEBUG(3, ("_reg_perfcount_get_counter_info: No counter data for counter [%d].\n", CounterIndex)); + return False; + } + + counter_size = _reg_perfcount_get_size_field(obj->counters[obj->NumCounters].CounterType); + + if(counter_size == PERF_SIZE_DWORD) + { + dsize = sizeof(data32); + memset(buf, 0, PERFCOUNT_MAX_LEN); + memcpy(buf, data.dptr, data.dsize); + data32 = strtol(buf, NULL, 0); + if((obj->counters[obj->NumCounters].CounterType & 0x00000F00) == PERF_TYPE_NUMBER) + obj->counters[obj->NumCounters].DefaultScale = _reg_perfcount_compute_scale((long long int)data32); + else + obj->counters[obj->NumCounters].DefaultScale = 0; + dbuf[0] = data32; + padding = (dsize - (obj->counter_data.ByteLength%dsize)) % dsize; + } + else if(counter_size == PERF_SIZE_LARGE) + { + dsize = sizeof(data64); + memset(buf, 0, PERFCOUNT_MAX_LEN); + memcpy(buf, data.dptr, data.dsize); + data64 = strtoll(buf, NULL, 0); + if((obj->counters[obj->NumCounters].CounterType & 0x00000F00) == PERF_TYPE_NUMBER) + obj->counters[obj->NumCounters].DefaultScale = _reg_perfcount_compute_scale(data64); + else + obj->counters[obj->NumCounters].DefaultScale = 0; + memcpy((void *)dbuf, (const void *)&data64, dsize); + padding = (dsize - (obj->counter_data.ByteLength%dsize)) % dsize; + } + else /* PERF_SIZE_VARIABLE_LEN */ + { + dsize = data.dsize; + memset(buf, 0, PERFCOUNT_MAX_LEN); + memcpy(buf, data.dptr, data.dsize); + } + free(data.dptr); + + obj->counter_data.ByteLength += dsize + padding; + obj->counter_data.data = TALLOC_REALLOC_ARRAY(ps->mem_ctx, + obj->counter_data.data, + uint8, + obj->counter_data.ByteLength - sizeof(uint32)); + if(obj->counter_data.data == NULL) + return False; + if(dbuf[0] != 0 || dbuf[1] != 0) + { + memcpy((void *)(obj->counter_data.data + + (obj->counter_data.ByteLength - (sizeof(uint32) + dsize))), + (const void *)dbuf, dsize); + } + else + { + /* Handling PERF_SIZE_VARIABLE_LEN */ + memcpy((void *)(obj->counter_data.data + + (obj->counter_data.ByteLength - (sizeof(uint32) + dsize))), + (const void *)buf, dsize); + } + obj->counters[obj->NumCounters].CounterOffset = obj->counter_data.ByteLength - dsize; + if(obj->counters[obj->NumCounters].CounterOffset % dsize != 0) + { + DEBUG(3,("Improperly aligned counter [%d]\n", obj->NumCounters)); + } + obj->counters[obj->NumCounters].CounterSize = dsize; + + return True; +} + +PERF_OBJECT_TYPE *_reg_perfcount_find_obj(PERF_DATA_BLOCK *block, int objind) +{ + int i; + + PERF_OBJECT_TYPE *obj = NULL; + + for(i = 0; i < block->NumObjectTypes; i++) + { + if(block->objects[i].ObjectNameTitleIndex == objind) + { + obj = &(block->objects[i]); + } + } + + return obj; +} + +static BOOL _reg_perfcount_add_counter(PERF_DATA_BLOCK *block, + prs_struct *ps, + int num, + TDB_DATA data, + TDB_CONTEXT *names) +{ + char *begin, *end, *start, *stop; + int parent; + PERF_OBJECT_TYPE *obj; + BOOL success = False; + char buf[PERFCOUNT_MAX_LEN]; + + obj = NULL; + memset(buf, 0, PERFCOUNT_MAX_LEN); + memcpy(buf, data.dptr, data.dsize); + begin = index(buf, '['); + end = index(buf, ']'); + if(begin == NULL || end == NULL) + return False; + start = begin+1; + + while(start < end) + { + stop = index(start, ','); + if(stop == NULL) + stop = end; + *stop = '\0'; + parent = atoi(start); + + obj = _reg_perfcount_find_obj(block, parent); + if(obj == NULL) + { + /* At this point we require that the parent object exist. + This can probably be handled better at some later time */ + DEBUG(3, ("_reg_perfcount_add_counter: Could not find parent object [%d] for counter [%d].\n", + parent, num)); + return False; + } + obj->counters = (PERF_COUNTER_DEFINITION *)TALLOC_REALLOC_ARRAY(ps->mem_ctx, + obj->counters, + PERF_COUNTER_DEFINITION, + obj->NumCounters+1); + if(obj->counters == NULL) + return False; + memset((void *)&(obj->counters[obj->NumCounters]), 0, sizeof(PERF_COUNTER_DEFINITION)); + obj->counters[obj->NumCounters].CounterNameTitleIndex=num; + obj->counters[obj->NumCounters].CounterHelpTitleIndex=num+1; + obj->counters[obj->NumCounters].DetailLevel = PERF_DETAIL_NOVICE; + obj->counters[obj->NumCounters].ByteLength = sizeof(PERF_COUNTER_DEFINITION); + success = _reg_perfcount_get_counter_info(block, ps, num, obj, names); + obj->NumCounters += 1; + start = stop + 1; + } + + /* Handle case of Objects/Counters without any counter data, which would suggest + that the required instances are not there yet, so change NumInstances from + PERF_NO_INSTANCES to 0 */ + + return True; +} + +BOOL _reg_perfcount_get_instance_info(PERF_INSTANCE_DEFINITION *inst, + prs_struct *ps, + int instId, + PERF_OBJECT_TYPE *obj, + TDB_CONTEXT *names) +{ + TDB_DATA key, data; + char buf[PERFCOUNT_MAX_LEN], temp[PERFCOUNT_MAX_LEN]; + wpstring name; + int pad; + + /* First grab the instance data from the data file */ + memset(temp, 0, PERFCOUNT_MAX_LEN); + snprintf(temp, PERFCOUNT_MAX_LEN, "i%d", instId); + _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, obj->ObjectNameTitleIndex, temp); + _reg_perfcount_get_counter_data(key, &data); + if(data.dptr == NULL) + { + DEBUG(3, ("_reg_perfcount_get_instance_info: No instance data for instance [%s].\n", + buf)); + return False; + } + inst->counter_data.ByteLength = data.dsize + sizeof(inst->counter_data.ByteLength); + inst->counter_data.data = TALLOC_REALLOC_ARRAY(ps->mem_ctx, + inst->counter_data.data, + uint8, + data.dsize); + if(inst->counter_data.data == NULL) + return False; + memset(inst->counter_data.data, 0, data.dsize); + memcpy(inst->counter_data.data, data.dptr, data.dsize); + free(data.dptr); + + /* Fetch instance name */ + memset(temp, 0, PERFCOUNT_MAX_LEN); + snprintf(temp, PERFCOUNT_MAX_LEN, "i%dname", instId); + _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, obj->ObjectNameTitleIndex, temp); + data = tdb_fetch(names, key); + if(data.dptr == NULL) + { + /* Not actually an error, but possibly unintended? -- just logging FYI */ + DEBUG(3, ("_reg_perfcount_get_instance_info: No instance name for instance [%s].\n", + buf)); + inst->NameLength = 0; + } + else + { + memset(buf, 0, PERFCOUNT_MAX_LEN); + memcpy(buf, data.dptr, data.dsize); + rpcstr_push((void *)name, buf, sizeof(name), STR_TERMINATE); + inst->NameLength = (strlen_w(name) * 2) + 2; + inst->data = TALLOC_REALLOC_ARRAY(ps->mem_ctx, + inst->data, + uint8, + inst->NameLength); + memcpy(inst->data, name, inst->NameLength); + free(data.dptr); + } + + inst->ParentObjectTitleIndex = 0; + inst->ParentObjectTitlePointer = 0; + inst->UniqueID = PERF_NO_UNIQUE_ID; + inst->NameOffset = 6 * sizeof(uint32); + + inst->ByteLength = inst->NameOffset + inst->NameLength; + /* Need to be aligned on a 64-bit boundary here for counter_data */ + if((pad = (inst->ByteLength % 8))) + { + pad = 8 - pad; + inst->data = TALLOC_REALLOC_ARRAY(ps->mem_ctx, + inst->data, + uint8, + inst->NameLength + pad); + memset(inst->data + inst->NameLength, 0, pad); + inst->ByteLength += pad; + } + + return True; +} + +BOOL _reg_perfcount_add_instance(PERF_OBJECT_TYPE *obj, + prs_struct *ps, + int instInd, + TDB_CONTEXT *names) +{ + BOOL success; + PERF_INSTANCE_DEFINITION *inst; + + success = False; + + if(obj->instances == NULL) + { + obj->instances = TALLOC_REALLOC_ARRAY(ps->mem_ctx, + obj->instances, + PERF_INSTANCE_DEFINITION, + obj->NumInstances); + } + if(obj->instances == NULL) + return False; + + memset(&(obj->instances[instInd]), 0, sizeof(PERF_INSTANCE_DEFINITION)); + inst = &(obj->instances[instInd]); + success = _reg_perfcount_get_instance_info(inst, ps, instInd, obj, names); + + return True; +} + +static int _reg_perfcount_assemble_global(PERF_DATA_BLOCK *block, + prs_struct *ps, + int base_index, + TDB_CONTEXT *names) +{ + BOOL success; + int i, j, retval = 0; + char keybuf[PERFCOUNT_MAX_LEN]; + TDB_DATA key, data; + + for(i = 1; i <= base_index; i++) + { + j = i*2; + _reg_perfcount_make_key(&key, keybuf, PERFCOUNT_MAX_LEN, j, "rel"); + data = tdb_fetch(names, key); + if(data.dptr != NULL) + { + if(_reg_perfcount_isparent(data)) + success = _reg_perfcount_add_object(block, ps, j, data, names); + else if(_reg_perfcount_ischild(data)) + success = _reg_perfcount_add_counter(block, ps, j, data, names); + else + { + DEBUG(3, ("Bogus relationship [%s] for counter [%d].\n", data.dptr, j)); + success = False; + } + if(success == False) + { + DEBUG(3, ("_reg_perfcount_assemble_global: Failed to add new relationship for counter [%d].\n", j)); + retval = -1; + } + free(data.dptr); + } + else + DEBUG(3, ("NULL relationship for counter [%d] using key [%s].\n", j, keybuf)); + } + return retval; +} + +static BOOL _reg_perfcount_get_64(unsigned long long *retval, + TDB_CONTEXT *tdb, + int key_part1, + const char *key_part2) +{ + TDB_DATA key, data; + char buf[PERFCOUNT_MAX_LEN]; + + _reg_perfcount_make_key(&key, buf, PERFCOUNT_MAX_LEN, key_part1, key_part2); + + data = tdb_fetch(tdb, key); + if(data.dptr == NULL) + { + DEBUG(3,("_reg_perfcount_get_64: No data found for key [%s].\n", key.dptr)); + return False; + } + + memset(buf, 0, PERFCOUNT_MAX_LEN); + memcpy(buf, data.dptr, data.dsize); + free(data.dptr); + + *retval = strtoll(buf, NULL, 0); + + return True; +} + +static BOOL _reg_perfcount_init_data_block_perf(PERF_DATA_BLOCK *block, + TDB_CONTEXT *names) +{ + unsigned long long PerfFreq, PerfTime, PerfTime100nSec; + TDB_CONTEXT *counters; + BOOL status; + pstring fname; + + status = False; + + pstrcpy(fname, lp_counters_dir()); + pstrcat(fname, "/data.tdb"); + + counters = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444); + + if(counters == NULL) + { + DEBUG(1, ("reg_perfcount_init_data_block_perf: unable to open [%s].\n", fname)); + return False; + } + + status = _reg_perfcount_get_64(&PerfFreq, names, 0, "PerfFreq"); + if(status == False) + { + tdb_close(counters); + return status; + } + memcpy((void *)&(block->PerfFreq), (const void *)&PerfFreq, sizeof(PerfFreq)); + + status = _reg_perfcount_get_64(&PerfTime, counters, 0, "PerfTime"); + if(status == False) + { + tdb_close(counters); + return status; + } + memcpy((void *)&(block->PerfTime), (const void *)&PerfTime, sizeof(PerfTime)); + + status = _reg_perfcount_get_64(&PerfTime100nSec, counters, 0, "PerfTime100nSec"); + if(status == False) + { + tdb_close(counters); + return status; + } + memcpy((void *)&(block->PerfTime100nSec), (const void *)&PerfTime100nSec, sizeof(PerfTime100nSec)); + + tdb_close(counters); + return True; +} + +static void _reg_perfcount_init_data_block(PERF_DATA_BLOCK *block, prs_struct *ps, TDB_CONTEXT *names) +{ + wpstring temp; + time_t tm; + + memset(temp, 0, sizeof(temp)); + rpcstr_push((void *)temp, "PERF", sizeof(temp), STR_TERMINATE); + memcpy(block->Signature, temp, strlen_w(temp) *2); + + if(ps->bigendian_data == RPC_BIG_ENDIAN) + block->LittleEndian = 0; + else + block->LittleEndian = 1; + block->Version = 1; + block->Revision = 1; + block->TotalByteLength = 0; + block->NumObjectTypes = 0; + block->DefaultObject = -1; + block->objects = NULL; + tm = time(NULL); + make_systemtime(&(block->SystemTime), gmtime(&tm)); + _reg_perfcount_init_data_block_perf(block, names); + memset(temp, 0, sizeof(temp)); + rpcstr_push((void *)temp, global_myname(), sizeof(temp), STR_TERMINATE); + block->SystemNameLength = (strlen_w(temp) * 2) + 2; + block->data = TALLOC_ZERO_ARRAY(ps->mem_ctx, uint8, block->SystemNameLength + (8 - (block->SystemNameLength % 8))); + memcpy(block->data, temp, block->SystemNameLength); + block->SystemNameOffset = sizeof(PERF_DATA_BLOCK) - sizeof(block->objects) - sizeof(block->data); + block->HeaderLength = block->SystemNameOffset + block->SystemNameLength; + /* Make sure to adjust for 64-bit alignment for when we finish writing the system name, + so that the PERF_OBJECT_TYPE struct comes out 64-bit aligned */ + block->HeaderLength += 8 - (block->HeaderLength % 8); + + return; +} + +static uint32 _reg_perfcount_perf_data_block_fixup(PERF_DATA_BLOCK *block, prs_struct *ps) +{ + int obj, cnt, inst, pad, i; + PERF_OBJECT_TYPE *object; + PERF_INSTANCE_DEFINITION *instance; + PERF_COUNTER_DEFINITION *counter; + PERF_COUNTER_BLOCK *counter_data; + char *temp = NULL, *src_addr, *dst_addr; + + block->TotalByteLength = 0; + object = block->objects; + for(obj = 0; obj < block->NumObjectTypes; obj++) + { + object[obj].TotalByteLength = 0; + object[obj].DefinitionLength = 0; + instance = object[obj].instances; + counter = object[obj].counters; + for(cnt = 0; cnt < object[obj].NumCounters; cnt++) + { + object[obj].TotalByteLength += counter[cnt].ByteLength; + object[obj].DefinitionLength += counter[cnt].ByteLength; + } + if(object[obj].NumInstances != PERF_NO_INSTANCES) + { + for(inst = 0; inst < object[obj].NumInstances; inst++) + { + instance = &(object[obj].instances[inst]); + object[obj].TotalByteLength += instance->ByteLength; + counter_data = &(instance->counter_data); + counter = &(object[obj].counters[object[obj].NumCounters - 1]); + counter_data->ByteLength = counter->CounterOffset + counter->CounterSize + sizeof(counter_data->ByteLength); + temp = TALLOC_REALLOC_ARRAY(ps->mem_ctx, + temp, + uint8, + counter_data->ByteLength- sizeof(counter_data->ByteLength)); + memset(temp, 0, counter_data->ByteLength - sizeof(counter_data->ByteLength)); + src_addr = counter_data->data; + for(i = 0; i < object[obj].NumCounters; i++) + { + counter = &(object[obj].counters[i]); + dst_addr = temp + counter->CounterOffset - sizeof(counter_data->ByteLength); + memcpy(dst_addr, src_addr, counter->CounterSize); + src_addr += counter->CounterSize; + } + /* Make sure to be 64-bit aligned */ + if((pad = (counter_data->ByteLength % 8))) + { + pad = 8 - pad; + } + counter_data->data = TALLOC_REALLOC_ARRAY(ps->mem_ctx, + counter_data->data, + uint8, + counter_data->ByteLength - sizeof(counter_data->ByteLength) + pad); + memset(counter_data->data, 0, counter_data->ByteLength - sizeof(counter_data->ByteLength) + pad); + memcpy(counter_data->data, temp, counter_data->ByteLength - sizeof(counter_data->ByteLength)); + counter_data->ByteLength += pad; + object[obj].TotalByteLength += counter_data->ByteLength; + } + } + else + { + /* Need to be 64-bit aligned at the end of the counter_data block, so pad counter_data to a 64-bit boundary, + so that the next PERF_OBJECT_TYPE can start on a 64-bit alignment */ + if((pad = (object[obj].counter_data.ByteLength % 8))) + { + pad = 8 - pad; + object[obj].counter_data.data = TALLOC_REALLOC_ARRAY(ps->mem_ctx, + object[obj].counter_data.data, + uint8, + object[obj].counter_data.ByteLength + pad); + memset((void *)(object[obj].counter_data.data + object[obj].counter_data.ByteLength), 0, pad); + object[obj].counter_data.ByteLength += pad; + } + object[obj].TotalByteLength += object[obj].counter_data.ByteLength; + } + object[obj].HeaderLength = sizeof(*object) - (sizeof(counter) + sizeof(instance) + sizeof(PERF_COUNTER_BLOCK)); + object[obj].TotalByteLength += object[obj].HeaderLength; + object[obj].DefinitionLength += object[obj].HeaderLength; + + block->TotalByteLength += object[obj].TotalByteLength; + } + + return block->TotalByteLength; +} + +uint32 reg_perfcount_get_perf_data_block(uint32 base_index, + prs_struct *ps, + PERF_DATA_BLOCK *block, + char *object_ids) +{ + uint32 buffer_size = 0, last_counter; + pstring fname; + TDB_CONTEXT *names; + int retval; + + pstrcpy(fname, lp_counters_dir()); + pstrcat(fname, "/names.tdb"); + + names = tdb_open_log(fname, 0, TDB_DEFAULT, O_RDONLY, 0444); + + if(names == NULL) + { + DEBUG(1, ("reg_perfcount_get_perf_data_block: unable to open [%s].\n", fname)); + return 0; + } + + _reg_perfcount_init_data_block(block, ps, names); + + last_counter = reg_perfcount_get_last_counter(base_index); + + if(object_ids == NULL) + { + /* we're getting a request for "Global" here */ + retval = _reg_perfcount_assemble_global(block, ps, base_index, names); + } + else + { + /* we're getting a request for a specific set of PERF_OBJECT_TYPES */ + retval = _reg_perfcount_assemble_global(block, ps, base_index, names); + } + buffer_size = _reg_perfcount_perf_data_block_fixup(block, ps); + + tdb_close(names); + + return buffer_size + block->HeaderLength; +} + +static BOOL _reg_perfcount_marshall_perf_data_block(prs_struct *ps, PERF_DATA_BLOCK block, int depth) +{ + int i; + prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_data_block"); + depth++; + + if(!prs_align(ps)) + return False; + for(i = 0; i < 4; i++) + { + if(!prs_uint16("Signature", ps, depth, &block.Signature[i])) + return False; + } + if(!prs_uint32("Little Endian", ps, depth, &block.LittleEndian)) + return False; + if(!prs_uint32("Version", ps, depth, &block.Version)) + return False; + if(!prs_uint32("Revision", ps, depth, &block.Revision)) + return False; + if(!prs_uint32("TotalByteLength", ps, depth, &block.TotalByteLength)) + return False; + if(!prs_uint32("HeaderLength", ps, depth, &block.HeaderLength)) + return False; + if(!prs_uint32("NumObjectTypes", ps, depth, &block.NumObjectTypes)) + return False; + if(!prs_uint32("DefaultObject", ps, depth, &block.DefaultObject)) + return False; + if(!spoolss_io_system_time("SystemTime", ps, depth, &block.SystemTime)) + return False; + if(!prs_uint32("Padding", ps, depth, &block.Padding)) + return False; + if(!prs_align_uint64(ps)) + return False; + if(!prs_uint64("PerfTime", ps, depth, &block.PerfTime)) + return False; + if(!prs_uint64("PerfFreq", ps, depth, &block.PerfFreq)) + return False; + if(!prs_uint64("PerfTime100nSec", ps, depth, &block.PerfTime100nSec)) + return False; + if(!prs_uint32("SystemNameLength", ps, depth, &block.SystemNameLength)) + return False; + if(!prs_uint32("SystemNameOffset", ps, depth, &block.SystemNameOffset)) + return False; + /* hack to make sure we're 64-bit aligned at the end of this whole mess */ + if(!prs_uint8s(False, "SystemName", ps, depth, block.data, + block.HeaderLength - block.SystemNameOffset)) + return False; + + return True; +} + +static BOOL _reg_perfcount_marshall_perf_counters(prs_struct *ps, + PERF_OBJECT_TYPE object, + int depth) +{ + int cnt; + PERF_COUNTER_DEFINITION counter; + + prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_counters"); + depth++; + + for(cnt = 0; cnt < object.NumCounters; cnt++) + { + counter = object.counters[cnt]; + + if(!prs_align(ps)) + return False; + if(!prs_uint32("ByteLength", ps, depth, &counter.ByteLength)) + return False; + if(!prs_uint32("CounterNameTitleIndex", ps, depth, &counter.CounterNameTitleIndex)) + return False; + if(!prs_uint32("CounterNameTitlePointer", ps, depth, &counter.CounterNameTitlePointer)) + return False; + if(!prs_uint32("CounterHelpTitleIndex", ps, depth, &counter.CounterHelpTitleIndex)) + return False; + if(!prs_uint32("CounterHelpTitlePointer", ps, depth, &counter.CounterHelpTitlePointer)) + return False; + if(!prs_uint32("DefaultScale", ps, depth, &counter.DefaultScale)) + return False; + if(!prs_uint32("DetailLevel", ps, depth, &counter.DetailLevel)) + return False; + if(!prs_uint32("CounterType", ps, depth, &counter.CounterType)) + return False; + if(!prs_uint32("CounterSize", ps, depth, &counter.CounterSize)) + return False; + if(!prs_uint32("CounterOffset", ps, depth, &counter.CounterOffset)) + return False; + } + + return True; +} + +static BOOL _reg_perfcount_marshall_perf_counter_data(prs_struct *ps, + PERF_COUNTER_BLOCK counter_data, + int depth) +{ + prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_counter_data"); + depth++; + + if(!prs_align_uint64(ps)) + return False; + + if(!prs_uint32("ByteLength", ps, depth, &counter_data.ByteLength)) + return False; + if(!prs_uint8s(False, "CounterData", ps, depth, counter_data.data, counter_data.ByteLength - sizeof(uint32))) + return False; + if(!prs_align_uint64(ps)) + return False; + + return True; +} + +static BOOL _reg_perfcount_marshall_perf_instances(prs_struct *ps, + PERF_OBJECT_TYPE object, + int depth) +{ + PERF_INSTANCE_DEFINITION instance; + int inst; + + prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_instances"); + depth++; + + for(inst = 0; inst < object.NumInstances; inst++) + { + instance = object.instances[inst]; + + if(!prs_align(ps)) + return False; + if(!prs_uint32("ByteLength", ps, depth, &instance.ByteLength)) + return False; + if(!prs_uint32("ParentObjectTitleIndex", ps, depth, &instance.ParentObjectTitleIndex)) + return False; + if(!prs_uint32("ParentObjectTitlePointer", ps, depth, &instance.ParentObjectTitlePointer)) + return False; + if(!prs_uint32("UniqueID", ps, depth, &instance.UniqueID)) + return False; + if(!prs_uint32("NameOffset", ps, depth, &instance.NameOffset)) + return False; + if(!prs_uint32("NameLength", ps, depth, &instance.NameLength)) + return False; + if(!prs_uint8s(False, "InstanceName", ps, depth, instance.data, + instance.ByteLength - instance.NameOffset)) + return False; + if(_reg_perfcount_marshall_perf_counter_data(ps, instance.counter_data, depth) == False) + return False; + } + + return True; +} + +static BOOL _reg_perfcount_marshall_perf_objects(prs_struct *ps, PERF_DATA_BLOCK block, int depth) +{ + int obj; + + PERF_OBJECT_TYPE object; + + prs_debug(ps, depth, "", "_reg_perfcount_marshall_perf_objects"); + depth++; + + for(obj = 0; obj < block.NumObjectTypes; obj++) + { + object = block.objects[obj]; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("TotalByteLength", ps, depth, &object.TotalByteLength)) + return False; + if(!prs_uint32("DefinitionLength", ps, depth, &object.DefinitionLength)) + return False; + if(!prs_uint32("HeaderLength", ps, depth, &object.HeaderLength)) + return False; + if(!prs_uint32("ObjectNameTitleIndex", ps, depth, &object.ObjectNameTitleIndex)) + return False; + if(!prs_uint32("ObjectNameTitlePointer", ps, depth, &object.ObjectNameTitlePointer)) + return False; + if(!prs_uint32("ObjectHelpTitleIndex", ps, depth, &object.ObjectHelpTitleIndex)) + return False; + if(!prs_uint32("ObjectHelpTitlePointer", ps, depth, &object.ObjectHelpTitlePointer)) + return False; + if(!prs_uint32("DetailLevel", ps, depth, &object.DetailLevel)) + return False; + if(!prs_uint32("NumCounters", ps, depth, &object.NumCounters)) + return False; + if(!prs_uint32("DefaultCounter", ps, depth, &object.DefaultCounter)) + return False; + if(!prs_uint32("NumInstances", ps, depth, &object.NumInstances)) + return False; + if(!prs_uint32("CodePage", ps, depth, &object.CodePage)) + return False; + if(!prs_align_uint64(ps)) + return False; + if(!prs_uint64("PerfTime", ps, depth, &object.PerfTime)) + return False; + if(!prs_uint64("PerfFreq", ps, depth, &object.PerfFreq)) + return False; + + /* Now do the counters */ + /* If no instances, encode counter_data */ + /* If instances, encode instace plus counter data for each instance */ + if(_reg_perfcount_marshall_perf_counters(ps, object, depth) == False) + return False; + if(object.NumInstances == PERF_NO_INSTANCES) + { + if(_reg_perfcount_marshall_perf_counter_data(ps, object.counter_data, depth) == False) + return False; + } + else + { + if(_reg_perfcount_marshall_perf_instances(ps, object, depth) == False) + return False; + } + } + + return True; +} + +static BOOL _reg_perfcount_marshall_hkpd(prs_struct *ps, PERF_DATA_BLOCK block) +{ + int depth = 0; + if(_reg_perfcount_marshall_perf_data_block(ps, block, depth) == True) + { + if(_reg_perfcount_marshall_perf_objects(ps, block, depth) == True) + return True; + } + return False; +} +WERROR reg_perfcount_get_hkpd(prs_struct *ps, uint32 max_buf_size, uint32 *outbuf_len, char *object_ids) +{ + /* + * For a detailed description of the layout of this structure, + * see http://msdn.microsoft.com/library/default.asp?url=/library/en-us/perfmon/base/performance_data_format.asp + */ + PERF_DATA_BLOCK block; + uint32 buffer_size, base_index; + + buffer_size = 0; + base_index = reg_perfcount_get_base_index(); + ZERO_STRUCT(block); + + buffer_size = reg_perfcount_get_perf_data_block(base_index, ps, &block, object_ids); + + if(buffer_size < max_buf_size) + { + *outbuf_len = buffer_size; + if(_reg_perfcount_marshall_hkpd(ps, block) == True) + return WERR_OK; + else + return WERR_NOMEM; + } + else + { + *outbuf_len = max_buf_size; + _reg_perfcount_marshall_perf_data_block(ps, block, 0); + return WERR_INSUFFICIENT_BUFFER; + } +} diff --git a/source3/registry/reg_printing.c b/source3/registry/reg_printing.c index d0f7daa926d..b07c8e9644f 100644 --- a/source3/registry/reg_printing.c +++ b/source3/registry/reg_printing.c @@ -55,34 +55,6 @@ struct reg_dyn_tree { ********************************************************************* *********************************************************************/ -/********************************************************************** - move to next non-delimter character -*********************************************************************/ - -static char* remaining_path( const char *key ) -{ - static pstring new_path; - char *p; - - if ( !key || !*key ) - return NULL; - - pstrcpy( new_path, key ); - /* normalize_reg_path( new_path ); */ - - if ( !(p = strchr( new_path, '\\' )) ) - { - if ( !(p = strchr( new_path, '/' )) ) - p = new_path; - else - p++; - } - else - p++; - - return p; -} - /*********************************************************************** simple function to prune a pathname down to the basename of a file **********************************************************************/ @@ -107,7 +79,7 @@ static char* dos_basename ( char *path ) static int key_forms_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys ) { - char *p = remaining_path( key + strlen(KEY_FORMS) ); + char *p = reg_remaining_path( key + strlen(KEY_FORMS) ); /* no keys below Forms */ @@ -204,9 +176,9 @@ static char* strip_printers_prefix( const char *key ) /* normalizing the path does not change length, just key delimiters and case */ if ( strncmp( path, KEY_WINNT_PRINTERS, strlen(KEY_WINNT_PRINTERS) ) == 0 ) - subkeypath = remaining_path( key + strlen(KEY_WINNT_PRINTERS) ); + subkeypath = reg_remaining_path( key + strlen(KEY_WINNT_PRINTERS) ); else - subkeypath = remaining_path( key + strlen(KEY_CONTROL_PRINTERS) ); + subkeypath = reg_remaining_path( key + strlen(KEY_CONTROL_PRINTERS) ); return subkeypath; } @@ -445,7 +417,7 @@ static void fill_in_printer_values( NT_PRINTER_INFO_LEVEL_2 *info2, REGVAL_CTR * /* use a prs_struct for converting the devmode and security descriptor to REG_BINARY */ - prs_init( &prs, MAX_PDU_FRAG_LEN, values, MARSHALL); + prs_init( &prs, RPC_MAX_PDU_FRAG_LEN, values, MARSHALL); /* stream the device mode */ @@ -754,7 +726,7 @@ static int key_driver_fetch_keys( const char *key, REGSUBKEY_CTR *subkeys ) DEBUG(10,("key_driver_fetch_keys key=>[%s]\n", key ? key : "NULL" )); - keystr = remaining_path( key + strlen(KEY_ENVIRONMENTS) ); + keystr = reg_remaining_path( key + strlen(KEY_ENVIRONMENTS) ); /* list all possible architectures */ @@ -1044,7 +1016,7 @@ static int key_driver_fetch_values( const char *key, REGVAL_CTR *values ) /* no values in the Environments key */ - if ( !(keystr = remaining_path( key + strlen(KEY_ENVIRONMENTS) )) ) + if ( !(keystr = reg_remaining_path( key + strlen(KEY_ENVIRONMENTS) )) ) return 0; pstrcpy( subkey, keystr); diff --git a/source3/registry/reg_util.c b/source3/registry/reg_util.c index 165292cf2fe..9f19db2646a 100644 --- a/source3/registry/reg_util.c +++ b/source3/registry/reg_util.c @@ -97,3 +97,31 @@ void normalize_reg_path( pstring keyname ) strupper_m( keyname ); } +/********************************************************************** + move to next non-delimter character +*********************************************************************/ + +char* reg_remaining_path( const char *key ) +{ + static pstring new_path; + char *p; + + if ( !key || !*key ) + return NULL; + + pstrcpy( new_path, key ); + /* normalize_reg_path( new_path ); */ + + if ( !(p = strchr( new_path, '\\' )) ) + { + if ( !(p = strchr( new_path, '/' )) ) + p = new_path; + else + p++; + } + else + p++; + + return p; +} + diff --git a/source3/registry/regfio.c b/source3/registry/regfio.c index e7b8cdc8bb2..954f4ae7bd0 100644 --- a/source3/registry/regfio.c +++ b/source3/registry/regfio.c @@ -561,7 +561,7 @@ static REGF_HBIN* lookup_hbin_block( REGF_FILE *file, uint32 offset ) /* start with the open list */ for ( hbin=file->block_list; hbin; hbin=hbin->next ) { - DEBUG(10,("lookup_hbin_block: address = 0x%x [0x%x]\n", hbin->file_off, (uint32)hbin )); + DEBUG(10,("lookup_hbin_block: address = 0x%x [0x%lx]\n", hbin->file_off, (unsigned long)hbin )); if ( hbin_contains_offset( hbin, offset ) ) return hbin; } diff --git a/source3/rpc_client/cli_dfs.c b/source3/rpc_client/cli_dfs.c index 79335191183..78df220ac2a 100644 --- a/source3/rpc_client/cli_dfs.c +++ b/source3/rpc_client/cli_dfs.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. RPC pipe client Copyright (C) Tim Potter 2000-2001, + Copyright (C) Jeremy Allison 2005. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,7 +23,7 @@ /* Query DFS support */ -NTSTATUS cli_dfs_exist(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_dfs_exist(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, BOOL *dfs_exists) { prs_struct qbuf, rbuf; @@ -33,25 +34,16 @@ NTSTATUS cli_dfs_exist(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_dfs_q_dfs_exist(&q); - if (!dfs_io_q_dfs_exist("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_NETDFS, DFS_EXIST, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!dfs_io_r_dfs_exist("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_EXIST, + q, r, + qbuf, rbuf, + dfs_io_q_dfs_exist, + dfs_io_r_dfs_exist, + NT_STATUS_UNSUCCESSFUL); /* Return result */ @@ -59,14 +51,10 @@ NTSTATUS cli_dfs_exist(struct cli_state *cli, TALLOC_CTX *mem_ctx, result = NT_STATUS_OK; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_dfs_add(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_dfs_add(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *entrypath, const char *servername, const char *sharename, const char *comment, uint32 flags) { @@ -78,39 +66,26 @@ NTSTATUS cli_dfs_add(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_dfs_q_dfs_add(&q, entrypath, servername, sharename, comment, flags); - if (!dfs_io_q_dfs_add("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_NETDFS, DFS_ADD, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!dfs_io_r_dfs_add("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_ADD, + q, r, + qbuf, rbuf, + dfs_io_q_dfs_add, + dfs_io_r_dfs_add, + NT_STATUS_UNSUCCESSFUL); /* Return result */ result = werror_to_ntstatus(r.status); - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_dfs_remove(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_dfs_remove(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *entrypath, const char *servername, const char *sharename) { @@ -122,38 +97,25 @@ NTSTATUS cli_dfs_remove(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_dfs_q_dfs_remove(&q, entrypath, servername, sharename); - if (!dfs_io_q_dfs_remove("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_NETDFS, DFS_REMOVE, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!dfs_io_r_dfs_remove("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_REMOVE, + q, r, + qbuf, rbuf, + dfs_io_q_dfs_remove, + dfs_io_r_dfs_remove, + NT_STATUS_UNSUCCESSFUL); /* Return result */ result = werror_to_ntstatus(r.status); - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_dfs_get_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_dfs_get_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *entrypath, const char *servername, const char *sharename, uint32 info_level, DFS_INFO_CTR *ctr) @@ -167,42 +129,29 @@ NTSTATUS cli_dfs_get_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_dfs_q_dfs_get_info(&q, entrypath, servername, sharename, info_level); - if (!dfs_io_q_dfs_get_info("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_NETDFS, DFS_GET_INFO, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!dfs_io_r_dfs_get_info("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_GET_INFO, + q, r, + qbuf, rbuf, + dfs_io_q_dfs_get_info, + dfs_io_r_dfs_get_info, + NT_STATUS_UNSUCCESSFUL); /* Return result */ result = werror_to_ntstatus(r.status); *ctr = r.ctr; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } /* Enumerate dfs shares */ -NTSTATUS cli_dfs_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_dfs_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 info_level, DFS_INFO_CTR *ctr) { prs_struct qbuf, rbuf; @@ -213,35 +162,22 @@ NTSTATUS cli_dfs_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_dfs_q_dfs_enum(&q, info_level, ctr); - if (!dfs_io_q_dfs_enum("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_NETDFS, DFS_ENUM, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - r.ctr = ctr; - if (!dfs_io_r_dfs_enum("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_NETDFS, DFS_ENUM, + q, r, + qbuf, rbuf, + dfs_io_q_dfs_enum, + dfs_io_r_dfs_enum, + NT_STATUS_UNSUCCESSFUL); /* Return result */ result = werror_to_ntstatus(r.status); - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } diff --git a/source3/rpc_client/cli_ds.c b/source3/rpc_client/cli_ds.c index 41063a5d7fb..8d1945f7698 100644 --- a/source3/rpc_client/cli_ds.c +++ b/source3/rpc_client/cli_ds.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. RPC pipe client Copyright (C) Gerald Carter 2002, + Copyright (C) Jeremy Allison 2005. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -38,30 +39,14 @@ NTSTATUS rpccli_ds_getprimarydominfo(struct rpc_pipe_client *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - if (!prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) { - return NT_STATUS_NO_MEMORY; - } - if (!prs_init(&rbuf, 0, mem_ctx, UNMARSHALL)) { - prs_mem_free(&qbuf); - return NT_STATUS_NO_MEMORY; - } - q.level = level; - if (!ds_io_q_getprimdominfo("", &qbuf, 0, &q) - || !rpc_api_pipe_req_int(cli, DS_GETPRIMDOMINFO, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!ds_io_r_getprimdominfo("", &rbuf, 0, &r)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC_DS, DS_GETPRIMDOMINFO, + q, r, + qbuf, rbuf, + ds_io_q_getprimdominfo, + ds_io_r_getprimdominfo, + NT_STATUS_UNSUCCESSFUL); /* Return basic info - if we are requesting at info != 1 then there could be trouble. */ @@ -76,20 +61,10 @@ NTSTATUS rpccli_ds_getprimarydominfo(struct rpc_pipe_client *cli, } done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } -NTSTATUS cli_ds_getprimarydominfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, - uint16 level, DS_DOMINFO_CTR *ctr) -{ - return rpccli_ds_getprimarydominfo(&cli->pipes[PI_LSARPC_DS], mem_ctx, - level, ctr); -} - - /******************************************************************** Enumerate trusted domains in an AD forest ********************************************************************/ @@ -108,30 +83,14 @@ NTSTATUS rpccli_ds_enum_domain_trusts(struct rpc_pipe_client *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - if (!prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) { - return NT_STATUS_NO_MEMORY;; - } - if (!prs_init(&rbuf, 0, mem_ctx, UNMARSHALL)) { - prs_mem_free(&qbuf); - return NT_STATUS_NO_MEMORY; - } - init_q_ds_enum_domain_trusts( &q, server, flags ); - if (!ds_io_q_enum_domain_trusts("", &qbuf, 0, &q) - || !rpc_api_pipe_req_int(cli, DS_ENUM_DOM_TRUSTS, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!ds_io_r_enum_domain_trusts("", &rbuf, 0, &r)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC_DS, DS_ENUM_DOM_TRUSTS, + q, r, + qbuf, rbuf, + ds_io_q_enum_domain_trusts, + ds_io_r_enum_domain_trusts, + NT_STATUS_UNSUCCESSFUL); result = r.status; @@ -168,19 +127,5 @@ NTSTATUS rpccli_ds_enum_domain_trusts(struct rpc_pipe_client *cli, } } -done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } - -NTSTATUS cli_ds_enum_domain_trusts(struct cli_state *cli, TALLOC_CTX *mem_ctx, - const char *server, uint32 flags, - struct ds_domain_trust **trusts, - uint32 *num_domains) -{ - return rpccli_ds_enum_domain_trusts(&cli->pipes[PI_NETLOGON], mem_ctx, - server, flags, trusts, - num_domains); -} diff --git a/source3/rpc_client/cli_echo.c b/source3/rpc_client/cli_echo.c index cd7e21f918f..89de6cec941 100644 --- a/source3/rpc_client/cli_echo.c +++ b/source3/rpc_client/cli_echo.c @@ -4,6 +4,7 @@ RPC pipe client Copyright (C) Tim Potter 2003 + Copyright (C) Jeremy Allison 2005. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -22,7 +23,7 @@ #include "includes.h" -NTSTATUS cli_echo_add_one(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_echo_add_one(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 request, uint32 *response) { prs_struct qbuf, rbuf; @@ -33,42 +34,26 @@ NTSTATUS cli_echo_add_one(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - if (!prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) { - return NT_STATUS_NO_MEMORY; - } - if (!prs_init(&rbuf, 0, mem_ctx, UNMARSHALL)) { - prs_mem_free(&qbuf); - return NT_STATUS_NO_MEMORY; - } - /* Marshall data and send request */ init_echo_q_add_one(&q, request); - if (!echo_io_q_add_one("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_ECHO, ECHO_ADD_ONE, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!echo_io_r_add_one("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC( cli, mem_ctx, PI_ECHO, ECHO_ADD_ONE, + q, r, + qbuf, rbuf, + echo_io_q_add_one, + echo_io_r_add_one, + NT_STATUS_UNSUCCESSFUL); if (response) *response = r.response; result = True; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } -NTSTATUS cli_echo_data(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_echo_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 size, char *in_data, char **out_data) { prs_struct qbuf, rbuf; @@ -79,28 +64,16 @@ NTSTATUS cli_echo_data(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - if (!prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) { - return NT_STATUS_NO_MEMORY; - } - if (!prs_init(&rbuf, 0, mem_ctx, UNMARSHALL)) { - prs_mem_free(&qbuf); - return NT_STATUS_NO_MEMORY; - } - /* Marshall data and send request */ init_echo_q_echo_data(&q, size, in_data); - if (!echo_io_q_echo_data("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_ECHO, ECHO_DATA, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!echo_io_r_echo_data("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC( cli, mem_ctx, PI_ECHO, ECHO_DATA, + q, r, + qbuf, rbuf, + echo_io_q_echo_data, + echo_io_r_echo_data, + NT_STATUS_UNSUCCESSFUL); result = True; @@ -109,14 +82,10 @@ NTSTATUS cli_echo_data(struct cli_state *cli, TALLOC_CTX *mem_ctx, memcpy(*out_data, r.data, size); } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } -NTSTATUS cli_echo_sink_data(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_echo_sink_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 size, char *in_data) { prs_struct qbuf, rbuf; @@ -127,41 +96,23 @@ NTSTATUS cli_echo_sink_data(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - if (!prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) { - return NT_STATUS_NO_MEMORY; - } - if (!prs_init(&rbuf, 0, mem_ctx, UNMARSHALL)) { - prs_mem_free(&qbuf); - return NT_STATUS_NO_MEMORY; - } - /* Marshall data and send request */ init_echo_q_sink_data(&q, size, in_data); - if (!echo_io_q_sink_data("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_ECHO, ECHO_SINK_DATA, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!echo_io_r_sink_data("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_ECHO, ECHO_SINK_DATA, + q, r, + qbuf, rbuf, + echo_io_q_sink_data, + echo_io_r_sink_data, + NT_STATUS_UNSUCCESSFUL); result = True; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } -NTSTATUS cli_echo_source_data(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_echo_source_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 size, char **out_data) { prs_struct qbuf, rbuf; @@ -172,36 +123,18 @@ NTSTATUS cli_echo_source_data(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - if (!prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) { - return NT_STATUS_NO_MEMORY; - } - if (!prs_init(&rbuf, 0, mem_ctx, UNMARSHALL)) { - prs_mem_free(&qbuf); - return NT_STATUS_NO_MEMORY; - } - /* Marshall data and send request */ init_echo_q_source_data(&q, size); - if (!echo_io_q_source_data("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_ECHO, ECHO_SOURCE_DATA, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!echo_io_r_source_data("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_ECHO, ECHO_SOURCE_DATA, + q, r, + qbuf, rbuf, + echo_io_q_source_data, + echo_io_r_source_data, + NT_STATUS_UNSUCCESSFUL); result = True; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } diff --git a/source3/rpc_client/cli_lsarpc.c b/source3/rpc_client/cli_lsarpc.c index 26f82cdfbe3..d7dcda72e3f 100644 --- a/source3/rpc_client/cli_lsarpc.c +++ b/source3/rpc_client/cli_lsarpc.c @@ -3,10 +3,8 @@ RPC pipe client Copyright (C) Tim Potter 2000-2001, Copyright (C) Andrew Tridgell 1992-1997,2000, - Copyright (C) Luke Kenneth Casson Leighton 1996-1997,2000, - Copyright (C) Paul Ashton 1997,2000, - Copyright (C) Elrond 2000, Copyright (C) Rafal Szczesniak 2002 + Copyright (C) Jeremy Allison 2005. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -24,7 +22,6 @@ */ #include "includes.h" -#include "rpc_client.h" /** @defgroup lsa LSA - Local Security Architecture * @ingroup rpc_client @@ -54,16 +51,9 @@ NTSTATUS rpccli_lsa_open_policy(struct rpc_pipe_client *cli, LSA_SEC_QOS qos; NTSTATUS result; - SMB_ASSERT(cli->pipe_idx == PI_LSARPC); - ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Initialise input parameters */ if (sec_qos) { @@ -75,18 +65,12 @@ NTSTATUS rpccli_lsa_open_policy(struct rpc_pipe_client *cli, /* Marshall data and send request */ - if (!lsa_io_q_open_pol("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, LSA_OPENPOLICY, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_open_pol("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_OPENPOLICY, + q, r, + qbuf, rbuf, + lsa_io_q_open_pol, + lsa_io_r_open_pol, + NT_STATUS_UNSUCCESSFUL ); /* Return output parameters */ @@ -97,20 +81,9 @@ NTSTATUS rpccli_lsa_open_policy(struct rpc_pipe_client *cli, #endif } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_lsa_open_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx, - BOOL sec_qos, uint32 des_access, POLICY_HND *pol) -{ - return rpccli_lsa_open_policy(&cli->pipes[PI_LSARPC], mem_ctx, - sec_qos, des_access, pol); -} - /** Open a LSA policy handle * * @param cli Handle on an initialised SMB connection @@ -125,40 +98,24 @@ NTSTATUS rpccli_lsa_open_policy2(struct rpc_pipe_client *cli, LSA_R_OPEN_POL2 r; LSA_SEC_QOS qos; NTSTATUS result; + char *srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", cli->cli->desthost); ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - - /* Initialise input parameters */ - if (sec_qos) { init_lsa_sec_qos(&qos, 2, 1, 0); - init_q_open_pol2(&q, cli->cli->srv_name_slash, 0, des_access, - &qos); + init_q_open_pol2(&q, srv_name_slash, 0, des_access, &qos); } else { - init_q_open_pol2(&q, cli->cli->srv_name_slash, 0, des_access, - NULL); + init_q_open_pol2(&q, srv_name_slash, 0, des_access, NULL); } - /* Marshall data and send request */ - - if (!lsa_io_q_open_pol2("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, LSA_OPENPOLICY2, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_open_pol2("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_OPENPOLICY2, + q, r, + qbuf, rbuf, + lsa_io_q_open_pol2, + lsa_io_r_open_pol2, + NT_STATUS_UNSUCCESSFUL ); /* Return output parameters */ @@ -169,21 +126,9 @@ NTSTATUS rpccli_lsa_open_policy2(struct rpc_pipe_client *cli, #endif } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_lsa_open_policy2(struct cli_state *cli, TALLOC_CTX *mem_ctx, - BOOL sec_qos, uint32 des_access, POLICY_HND *pol) -{ - return rpccli_lsa_open_policy2(&cli->pipes[PI_LSARPC], mem_ctx, - sec_qos, des_access, pol); -} - - /** Close a LSA policy handle */ NTSTATUS rpccli_lsa_close(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, @@ -194,32 +139,17 @@ NTSTATUS rpccli_lsa_close(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, LSA_R_CLOSE r; NTSTATUS result; - SMB_ASSERT(cli->pipe_idx == PI_LSARPC); - ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - - /* Marshall data and send request */ - init_lsa_q_close(&q, pol); - if (!lsa_io_q_close("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, LSA_CLOSE, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_close("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_CLOSE, + q, r, + qbuf, rbuf, + lsa_io_q_close, + lsa_io_r_close, + NT_STATUS_UNSUCCESSFUL ); /* Return output parameters */ @@ -230,19 +160,9 @@ NTSTATUS rpccli_lsa_close(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, *pol = r.pol; } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_lsa_close(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *pol) -{ - return rpccli_lsa_close(&cli->pipes[PI_LSARPC], mem_ctx, pol); -} - /** Lookup a list of sids */ NTSTATUS rpccli_lsa_lookup_sids(struct rpc_pipe_client *cli, @@ -256,46 +176,32 @@ NTSTATUS rpccli_lsa_lookup_sids(struct rpc_pipe_client *cli, LSA_R_LOOKUP_SIDS r; DOM_R_REF ref; LSA_TRANS_NAME_ENUM t_names; - NTSTATUS result; + NTSTATUS result = NT_STATUS_OK; int i; ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - - /* Marshall data and send request */ - init_q_lookup_sids(mem_ctx, &q, pol, num_sids, sids, 1); - if (!lsa_io_q_lookup_sids("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, LSA_LOOKUPSIDS, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - ZERO_STRUCT(ref); ZERO_STRUCT(t_names); r.dom_ref = &ref; r.names = &t_names; - if (!lsa_io_r_lookup_sids("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - result = r.status; + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_LOOKUPSIDS, + q, r, + qbuf, rbuf, + lsa_io_q_lookup_sids, + lsa_io_r_lookup_sids, + NT_STATUS_UNSUCCESSFUL ); - if (!NT_STATUS_IS_OK(result) && - NT_STATUS_V(result) != NT_STATUS_V(STATUS_SOME_UNMAPPED)) { + if (!NT_STATUS_IS_OK(r.status) && + NT_STATUS_V(r.status) != NT_STATUS_V(STATUS_SOME_UNMAPPED)) { /* An actual error occured */ + result = r.status; goto done; } @@ -356,22 +262,10 @@ NTSTATUS rpccli_lsa_lookup_sids(struct rpc_pipe_client *cli, } done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } -NTSTATUS cli_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *pol, int num_sids, - const DOM_SID *sids, - char ***domains, char ***names, uint32 **types) -{ - return rpccli_lsa_lookup_sids(&cli->pipes[PI_LSARPC], mem_ctx, - pol, num_sids, sids, - domains, names, types); -} - /** Lookup a list of names */ NTSTATUS rpccli_lsa_lookup_names(struct rpc_pipe_client *cli, @@ -390,30 +284,17 @@ NTSTATUS rpccli_lsa_lookup_names(struct rpc_pipe_client *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - - /* Marshall data and send request */ - - init_q_lookup_names(mem_ctx, &q, pol, num_names, names); - - if (!lsa_io_q_lookup_names("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, LSA_LOOKUPNAMES, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - ZERO_STRUCT(ref); r.dom_ref = &ref; - if (!lsa_io_r_lookup_names("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + init_q_lookup_names(mem_ctx, &q, pol, num_names, names); + + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_LOOKUPNAMES, + q, r, + qbuf, rbuf, + lsa_io_q_lookup_names, + lsa_io_r_lookup_names, + NT_STATUS_UNSUCCESSFUL); result = r.status; @@ -468,21 +349,10 @@ NTSTATUS rpccli_lsa_lookup_names(struct rpc_pipe_client *cli, } done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } -NTSTATUS cli_lsa_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *pol, int num_names, - const char **names, DOM_SID **sids, - uint32 **types) -{ - return rpccli_lsa_lookup_names(&cli->pipes[PI_LSARPC], mem_ctx, - pol, num_names, names, sids, types); -} - /** Query info policy * * @param domain_sid - returned remote server's domain sid */ @@ -497,32 +367,17 @@ NTSTATUS rpccli_lsa_query_info_policy(struct rpc_pipe_client *cli, LSA_R_QUERY_INFO r; NTSTATUS result; - SMB_ASSERT(cli->pipe_idx == PI_LSARPC); - ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - - /* Marshall data and send request */ - init_q_query(&q, pol, info_class); - if (!lsa_io_q_query("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, LSA_QUERYINFOPOLICY, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_query("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_LSARPC, LSA_QUERYINFOPOLICY, + q, r, + qbuf, rbuf, + lsa_io_q_query, + lsa_io_r_query, + NT_STATUS_UNSUCCESSFUL); if (!NT_STATUS_IS_OK(result = r.status)) { goto done; @@ -570,21 +425,10 @@ NTSTATUS rpccli_lsa_query_info_policy(struct rpc_pipe_client *cli, } done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } -NTSTATUS cli_lsa_query_info_policy(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *pol, uint16 info_class, - char **domain_name, DOM_SID **domain_sid) -{ - return rpccli_lsa_query_info_policy(&cli->pipes[PI_LSARPC], mem_ctx, - pol, info_class, domain_name, - domain_sid); -} - /** Query info policy2 * * @param domain_name - returned remote server's domain name @@ -612,27 +456,14 @@ NTSTATUS rpccli_lsa_query_info_policy2(struct rpc_pipe_client *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - - /* Marshall data and send request */ - init_q_query2(&q, pol, info_class); - if (!lsa_io_q_query_info2("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, LSA_QUERYINFO2, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_query_info2("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_QUERYINFO2, + q, r, + qbuf, rbuf, + lsa_io_q_query_info2, + lsa_io_r_query_info2, + NT_STATUS_UNSUCCESSFUL); if (!NT_STATUS_IS_OK(result = r.status)) { goto done; @@ -674,25 +505,10 @@ NTSTATUS rpccli_lsa_query_info_policy2(struct rpc_pipe_client *cli, } done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } -NTSTATUS cli_lsa_query_info_policy2(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *pol, uint16 info_class, - char **domain_name, char **dns_name, - char **forest_name, - struct uuid **domain_guid, - DOM_SID **domain_sid) -{ - return rpccli_lsa_query_info_policy2(&cli->pipes[PI_LSARPC], mem_ctx, - pol, info_class, domain_name, - dns_name, forest_name, - domain_guid, domain_sid); -} - /** * Enumerate list of trusted domains * @@ -720,7 +536,6 @@ NTSTATUS rpccli_lsa_enum_trust_dom(struct rpc_pipe_client *cli, int i; fstring tmp; - ZERO_STRUCT(in); ZERO_STRUCT(out); @@ -728,7 +543,7 @@ NTSTATUS rpccli_lsa_enum_trust_dom(struct rpc_pipe_client *cli, init_q_enum_trust_dom(&in, pol, *enum_ctx, 0x10000); - CLI_DO_RPC_EX( cli, mem_ctx, PI_LSARPC, LSA_ENUMTRUSTDOM, + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUMTRUSTDOM, in, out, qbuf, rbuf, lsa_io_q_enum_trust_dom, @@ -779,19 +594,9 @@ NTSTATUS rpccli_lsa_enum_trust_dom(struct rpc_pipe_client *cli, return out.status; } -NTSTATUS cli_lsa_enum_trust_dom(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *pol, uint32 *enum_ctx, - uint32 *num_domains, - char ***domain_names, DOM_SID **domain_sids) -{ - return rpccli_lsa_enum_trust_dom(&cli->pipes[PI_LSARPC], mem_ctx, - pol, enum_ctx, num_domains, - domain_names, domain_sids); -} - /** Enumerate privileges*/ -NTSTATUS cli_lsa_enum_privilege(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_lsa_enum_privilege(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint32 *enum_context, uint32 pref_max_length, uint32 *count, char ***privs_name, uint32 **privs_high, uint32 **privs_low) { @@ -804,27 +609,14 @@ NTSTATUS cli_lsa_enum_privilege(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - - /* Marshall data and send request */ - init_q_enum_privs(&q, pol, *enum_context, pref_max_length); - if (!lsa_io_q_enum_privs("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_LSARPC, LSA_ENUM_PRIVS, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_enum_privs("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUM_PRIVS, + q, r, + qbuf, rbuf, + lsa_io_q_enum_privs, + lsa_io_r_enum_privs, + NT_STATUS_UNSUCCESSFUL); if (!NT_STATUS_IS_OK(result = r.status)) { goto done; @@ -865,15 +657,13 @@ NTSTATUS cli_lsa_enum_privilege(struct cli_state *cli, TALLOC_CTX *mem_ctx, } done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } /** Get privilege name */ -NTSTATUS cli_lsa_get_dispname(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_lsa_get_dispname(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, const char *name, uint16 lang_id, uint16 lang_id_sys, fstring description, uint16 *lang_id_desc) @@ -886,27 +676,14 @@ NTSTATUS cli_lsa_get_dispname(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - - /* Marshall data and send request */ - init_lsa_priv_get_dispname(&q, pol, name, lang_id, lang_id_sys); - if (!lsa_io_q_priv_get_dispname("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_LSARPC, LSA_PRIV_GET_DISPNAME, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_priv_get_dispname("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_PRIV_GET_DISPNAME, + q, r, + qbuf, rbuf, + lsa_io_q_priv_get_dispname, + lsa_io_r_priv_get_dispname, + NT_STATUS_UNSUCCESSFUL); if (!NT_STATUS_IS_OK(result = r.status)) { goto done; @@ -918,15 +695,13 @@ NTSTATUS cli_lsa_get_dispname(struct cli_state *cli, TALLOC_CTX *mem_ctx, *lang_id_desc = r.lang_id; done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } /** Enumerate list of SIDs */ -NTSTATUS cli_lsa_enum_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_lsa_enum_sids(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint32 *enum_ctx, uint32 pref_max_length, uint32 *num_sids, DOM_SID **sids) { @@ -939,27 +714,14 @@ NTSTATUS cli_lsa_enum_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - - /* Marshall data and send request */ - init_lsa_q_enum_accounts(&q, pol, *enum_ctx, pref_max_length); - if (!lsa_io_q_enum_accounts("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_LSARPC, LSA_ENUM_ACCOUNTS, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_enum_accounts("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUM_ACCOUNTS, + q, r, + qbuf, rbuf, + lsa_io_q_enum_accounts, + lsa_io_r_enum_accounts, + NT_STATUS_UNSUCCESSFUL); result = r.status; @@ -989,8 +751,6 @@ NTSTATUS cli_lsa_enum_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx, *enum_ctx = r.enum_context; done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } @@ -1004,7 +764,7 @@ NTSTATUS cli_lsa_enum_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx, * * */ -NTSTATUS cli_lsa_create_account(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_lsa_create_account(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *dom_pol, DOM_SID *sid, uint32 desired_access, POLICY_HND *user_pol) { @@ -1016,29 +776,16 @@ NTSTATUS cli_lsa_create_account(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Initialise input parameters */ init_lsa_q_create_account(&q, dom_pol, sid, desired_access); - /* Marshall data and send request */ - - if (!lsa_io_q_create_account("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_LSARPC, LSA_CREATEACCOUNT, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_create_account("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_CREATEACCOUNT, + q, r, + qbuf, rbuf, + lsa_io_q_create_account, + lsa_io_r_create_account, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -1046,10 +793,6 @@ NTSTATUS cli_lsa_create_account(struct cli_state *cli, TALLOC_CTX *mem_ctx, *user_pol = r.pol; } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } @@ -1057,7 +800,7 @@ NTSTATUS cli_lsa_create_account(struct cli_state *cli, TALLOC_CTX *mem_ctx, * * @param cli Handle on an initialised SMB connection */ -NTSTATUS cli_lsa_open_account(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_lsa_open_account(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *dom_pol, DOM_SID *sid, uint32 des_access, POLICY_HND *user_pol) { @@ -1069,29 +812,16 @@ NTSTATUS cli_lsa_open_account(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Initialise input parameters */ init_lsa_q_open_account(&q, dom_pol, sid, des_access); - /* Marshall data and send request */ - - if (!lsa_io_q_open_account("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_LSARPC, LSA_OPENACCOUNT, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_open_account("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_OPENACCOUNT, + q, r, + qbuf, rbuf, + lsa_io_q_open_account, + lsa_io_r_open_account, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -1099,10 +829,6 @@ NTSTATUS cli_lsa_open_account(struct cli_state *cli, TALLOC_CTX *mem_ctx, *user_pol = r.pol; } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } @@ -1110,7 +836,7 @@ NTSTATUS cli_lsa_open_account(struct cli_state *cli, TALLOC_CTX *mem_ctx, * * @param cli Handle on an initialised SMB connection */ -NTSTATUS cli_lsa_enum_privsaccount(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_lsa_enum_privsaccount(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint32 *count, LUID_ATTR **set) { prs_struct qbuf, rbuf; @@ -1122,29 +848,16 @@ NTSTATUS cli_lsa_enum_privsaccount(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Initialise input parameters */ init_lsa_q_enum_privsaccount(&q, pol); - /* Marshall data and send request */ - - if (!lsa_io_q_enum_privsaccount("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_LSARPC, LSA_ENUMPRIVSACCOUNT, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_enum_privsaccount("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUMPRIVSACCOUNT, + q, r, + qbuf, rbuf, + lsa_io_q_enum_privsaccount, + lsa_io_r_enum_privsaccount, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -1169,15 +882,13 @@ NTSTATUS cli_lsa_enum_privsaccount(struct cli_state *cli, TALLOC_CTX *mem_ctx, *count=r.count; done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } /** Get a privilege value given its name */ -NTSTATUS cli_lsa_lookup_priv_value(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_lsa_lookup_priv_value(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, const char *name, LUID *luid) { prs_struct qbuf, rbuf; @@ -1188,27 +899,16 @@ NTSTATUS cli_lsa_lookup_priv_value(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_lsa_q_lookup_priv_value(&q, pol, name); - if (!lsa_io_q_lookup_priv_value("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_LSARPC, LSA_LOOKUPPRIVVALUE, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_lookup_priv_value("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_LOOKUPPRIVVALUE, + q, r, + qbuf, rbuf, + lsa_io_q_lookup_priv_value, + lsa_io_r_lookup_priv_value, + NT_STATUS_UNSUCCESSFUL); if (!NT_STATUS_IS_OK(result = r.status)) { goto done; @@ -1220,15 +920,13 @@ NTSTATUS cli_lsa_lookup_priv_value(struct cli_state *cli, TALLOC_CTX *mem_ctx, (*luid).high=r.luid.high; done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } /** Query LSA security object */ -NTSTATUS cli_lsa_query_secobj(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_lsa_query_secobj(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint32 sec_info, SEC_DESC_BUF **psdb) { @@ -1240,27 +938,16 @@ NTSTATUS cli_lsa_query_secobj(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_q_query_sec_obj(&q, pol, sec_info); - if (!lsa_io_q_query_sec_obj("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_LSARPC, LSA_QUERYSECOBJ, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_query_sec_obj("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_QUERYSECOBJ, + q, r, + qbuf, rbuf, + lsa_io_q_query_sec_obj, + lsa_io_r_query_sec_obj, + NT_STATUS_UNSUCCESSFUL); if (!NT_STATUS_IS_OK(result = r.status)) { goto done; @@ -1272,8 +959,6 @@ NTSTATUS cli_lsa_query_secobj(struct cli_state *cli, TALLOC_CTX *mem_ctx, *psdb = r.buf; done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } @@ -1283,7 +968,7 @@ NTSTATUS cli_lsa_query_secobj(struct cli_state *cli, TALLOC_CTX *mem_ctx, takes a SID directly, avoiding the open_account call. */ -NTSTATUS cli_lsa_enum_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_lsa_enum_account_rights(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, DOM_SID *sid, uint32 *count, char ***priv_names) { @@ -1298,24 +983,15 @@ NTSTATUS cli_lsa_enum_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_q_enum_acct_rights(&q, pol, 2, sid); - if (!lsa_io_q_enum_acct_rights("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_LSARPC, LSA_ENUMACCTRIGHTS, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - if (!lsa_io_r_enum_acct_rights("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ENUMACCTRIGHTS, + q, r, + qbuf, rbuf, + lsa_io_q_enum_acct_rights, + lsa_io_r_enum_acct_rights, + NT_STATUS_UNSUCCESSFUL); if (!NT_STATUS_IS_OK(result = r.status)) { goto done; @@ -1353,10 +1029,9 @@ done: /* add account rights to an account. */ -NTSTATUS cli_lsa_add_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_lsa_add_account_rights(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, DOM_SID sid, - -uint32 count, const char **privs_name) + uint32 count, const char **privs_name) { prs_struct qbuf, rbuf; LSA_Q_ADD_ACCT_RIGHTS q; @@ -1364,26 +1039,17 @@ uint32 count, const char **privs_name) NTSTATUS result; ZERO_STRUCT(q); - - /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + ZERO_STRUCT(r); /* Marshall data and send request */ init_q_add_acct_rights(&q, pol, &sid, count, privs_name); - if (!lsa_io_q_add_acct_rights("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_LSARPC, LSA_ADDACCTRIGHTS, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_add_acct_rights("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_ADDACCTRIGHTS, + q, r, + qbuf, rbuf, + lsa_io_q_add_acct_rights, + lsa_io_r_add_acct_rights, + NT_STATUS_UNSUCCESSFUL); if (!NT_STATUS_IS_OK(result = r.status)) { goto done; @@ -1396,7 +1062,7 @@ done: /* remove account rights for an account. */ -NTSTATUS cli_lsa_remove_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_lsa_remove_account_rights(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, DOM_SID sid, BOOL removeall, uint32 count, const char **privs_name) { @@ -1406,26 +1072,17 @@ NTSTATUS cli_lsa_remove_account_rights(struct cli_state *cli, TALLOC_CTX *mem_ct NTSTATUS result; ZERO_STRUCT(q); - - /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + ZERO_STRUCT(r); /* Marshall data and send request */ init_q_remove_acct_rights(&q, pol, &sid, removeall?1:0, count, privs_name); - if (!lsa_io_q_remove_acct_rights("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_LSARPC, LSA_REMOVEACCTRIGHTS, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_remove_acct_rights("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_REMOVEACCTRIGHTS, + q, r, + qbuf, rbuf, + lsa_io_q_remove_acct_rights, + lsa_io_r_remove_acct_rights, + NT_STATUS_UNSUCCESSFUL); if (!NT_STATUS_IS_OK(result = r.status)) { goto done; @@ -1539,7 +1196,7 @@ Error was : %s.\n", remote_machine, cli_errstr(&cli) )); #endif -NTSTATUS cli_lsa_open_trusted_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_lsa_open_trusted_domain(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, DOM_SID *dom_sid, uint32 access_mask, POLICY_HND *trustdom_pol) { @@ -1551,29 +1208,18 @@ NTSTATUS cli_lsa_open_trusted_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Initialise input parameters */ init_lsa_q_open_trusted_domain(&q, pol, dom_sid, access_mask); /* Marshall data and send request */ - if (!lsa_io_q_open_trusted_domain("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_LSARPC, LSA_OPENTRUSTDOM, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_open_trusted_domain("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_OPENTRUSTDOM, + q, r, + qbuf, rbuf, + lsa_io_q_open_trusted_domain, + lsa_io_r_open_trusted_domain, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -1581,14 +1227,10 @@ NTSTATUS cli_lsa_open_trusted_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx, *trustdom_pol = r.handle; } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_lsa_query_trusted_domain_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_lsa_query_trusted_domain_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint16 info_class, DOM_SID *dom_sid, LSA_TRUSTED_DOMAIN_INFO **info) @@ -1601,27 +1243,16 @@ NTSTATUS cli_lsa_query_trusted_domain_info(struct cli_state *cli, TALLOC_CTX *me ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_q_query_trusted_domain_info(&q, pol, info_class); - if (!lsa_io_q_query_trusted_domain_info("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_LSARPC, LSA_QUERYTRUSTDOMINFO, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_query_trusted_domain_info("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_QUERYTRUSTDOMINFO, + q, r, + qbuf, rbuf, + lsa_io_q_query_trusted_domain_info, + lsa_io_r_query_trusted_domain_info, + NT_STATUS_UNSUCCESSFUL); if (!NT_STATUS_IS_OK(result = r.status)) { goto done; @@ -1630,14 +1261,11 @@ NTSTATUS cli_lsa_query_trusted_domain_info(struct cli_state *cli, TALLOC_CTX *me *info = r.info; done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_lsa_query_trusted_domain_info_by_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_lsa_query_trusted_domain_info_by_sid(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint16 info_class, DOM_SID *dom_sid, LSA_TRUSTED_DOMAIN_INFO **info) @@ -1650,27 +1278,16 @@ NTSTATUS cli_lsa_query_trusted_domain_info_by_sid(struct cli_state *cli, TALLOC_ ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_q_query_trusted_domain_info_by_sid(&q, pol, info_class, dom_sid); - if (!lsa_io_q_query_trusted_domain_info_by_sid("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_LSARPC, LSA_QUERYTRUSTDOMINFOBYSID, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_query_trusted_domain_info("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_QUERYTRUSTDOMINFOBYSID, + q, r, + qbuf, rbuf, + lsa_io_q_query_trusted_domain_info_by_sid, + lsa_io_r_query_trusted_domain_info, + NT_STATUS_UNSUCCESSFUL); if (!NT_STATUS_IS_OK(result = r.status)) { goto done; @@ -1679,13 +1296,11 @@ NTSTATUS cli_lsa_query_trusted_domain_info_by_sid(struct cli_state *cli, TALLOC_ *info = r.info; done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } -NTSTATUS cli_lsa_query_trusted_domain_info_by_name(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_lsa_query_trusted_domain_info_by_name(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint16 info_class, const char *domain_name, LSA_TRUSTED_DOMAIN_INFO **info) @@ -1698,27 +1313,16 @@ NTSTATUS cli_lsa_query_trusted_domain_info_by_name(struct cli_state *cli, TALLOC ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_q_query_trusted_domain_info_by_name(&q, pol, info_class, domain_name); - if (!lsa_io_q_query_trusted_domain_info_by_name("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_LSARPC, LSA_QUERYTRUSTDOMINFOBYNAME, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!lsa_io_r_query_trusted_domain_info("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC( cli, mem_ctx, PI_LSARPC, LSA_QUERYTRUSTDOMINFOBYNAME, + q, r, + qbuf, rbuf, + lsa_io_q_query_trusted_domain_info_by_name, + lsa_io_r_query_trusted_domain_info, + NT_STATUS_UNSUCCESSFUL); if (!NT_STATUS_IS_OK(result = r.status)) { goto done; @@ -1727,11 +1331,6 @@ NTSTATUS cli_lsa_query_trusted_domain_info_by_name(struct cli_state *cli, TALLOC *info = r.info; done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } - -/** @} **/ - diff --git a/source3/rpc_client/cli_netlogon.c b/source3/rpc_client/cli_netlogon.c index fad60dbc20d..88b6c792ebf 100644 --- a/source3/rpc_client/cli_netlogon.c +++ b/source3/rpc_client/cli_netlogon.c @@ -2,12 +2,9 @@ Unix SMB/CIFS implementation. NT Domain Authentication SMB / MSRPC client Copyright (C) Andrew Tridgell 1992-2000 - Copyright (C) Luke Kenneth Casson Leighton 1996-2000 - Copyright (C) Tim Potter 2001 - Copyright (C) Paul Ashton 1997. Copyright (C) Jeremy Allison 1998. - Copyright (C) Andrew Bartlett 2001. - + Largely re-written by Jeremy Allison (C) 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 @@ -26,104 +23,52 @@ #include "includes.h" /* LSA Request Challenge. Sends our challenge to server, then gets - server response. These are used to generate the credentials. */ - -NTSTATUS cli_net_req_chal(struct cli_state *cli, DOM_CHAL *clnt_chal, - DOM_CHAL *srv_chal) -{ - prs_struct qbuf, rbuf; - NET_Q_REQ_CHAL q; - NET_R_REQ_CHAL r; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api NET_REQCHAL */ - - DEBUG(4,("cli_net_req_chal: LSA Request Challenge from %s to %s: %s\n", - global_myname(), cli->desthost, credstr(clnt_chal->data))); - - /* store the parameters */ - init_q_req_chal(&q, cli->srv_name_slash, global_myname(), clnt_chal); - - /* Marshall data and send request */ - - if (!net_io_q_req_chal("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_NETLOGON, NET_REQCHAL, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarhall response */ - - if (!net_io_r_req_chal("", &r, &rbuf, 0)) { - goto done; - } - - result = r.status; - - /* Return result */ - - if (NT_STATUS_IS_OK(result)) { - memcpy(srv_chal, r.srv_chal.data, sizeof(srv_chal->data)); - } - - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - - return result; -} + server response. These are used to generate the credentials. + The sent and received challenges are stored in the netlog pipe + private data. Only call this via rpccli_netlogon_setup_creds(). JRA. +*/ -NTSTATUS rpccli_net_req_chal(struct rpc_pipe_client *cli, - const char *server_name, - const char *computer_name, - DOM_CHAL *clnt_chal, DOM_CHAL *srv_chal) +static NTSTATUS rpccli_net_req_chal(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *server_name, + const char *clnt_name, + const DOM_CHAL *clnt_chal_in, + DOM_CHAL *srv_chal_out) { - prs_struct qbuf, rbuf; - NET_Q_REQ_CHAL q; - NET_R_REQ_CHAL r; - NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + prs_struct qbuf, rbuf; + NET_Q_REQ_CHAL q; + NET_R_REQ_CHAL r; + NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->cli->mem_ctx, UNMARSHALL); - - /* create and send a MSRPC command with api NET_REQCHAL */ + /* create and send a MSRPC command with api NET_REQCHAL */ - DEBUG(4,("cli_net_req_chal: LSA Request Challenge from %s to %s\n", - computer_name, server_name)); - - /* store the parameters */ - init_q_req_chal(&q, server_name, computer_name, clnt_chal); + DEBUG(4,("cli_net_req_chal: LSA Request Challenge from %s to %s\n", + clnt_name, server_name)); - /* Marshall data and send request */ + /* store the parameters */ + init_q_req_chal(&q, server_name, clnt_name, clnt_chal_in); - if (!net_io_q_req_chal("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, NET_REQCHAL, &qbuf, &rbuf)) { - goto done; - } + /* Marshall data and send request */ + CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_REQCHAL, + q, r, + qbuf, rbuf, + net_io_q_req_chal, + net_io_r_req_chal, + NT_STATUS_UNSUCCESSFUL); - /* Unmarhall response */ + result = r.status; - if (!net_io_r_req_chal("", &r, &rbuf, 0)) { - goto done; - } + /* Return result */ - result = r.status; - - /* Return result */ + if (NT_STATUS_IS_OK(result)) { + /* Store the returned server challenge. */ + *srv_chal_out = r.srv_chal; + } - if (NT_STATUS_IS_OK(result)) { - memcpy(srv_chal, r.srv_chal.data, sizeof(srv_chal->data)); - } - - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - - return result; + return result; } +#if 0 /**************************************************************************** LSA Authenticate 2 @@ -132,7 +77,7 @@ Ensure that the server credential returned matches the session key encrypt of the server challenge originally received. JRA. ****************************************************************************/ -NTSTATUS cli_net_auth2(struct cli_state *cli, + NTSTATUS rpccli_net_auth2(struct rpc_pipe_client *cli, uint16 sec_chan, uint32 *neg_flags, DOM_CHAL *srv_chal) { @@ -142,9 +87,6 @@ NTSTATUS cli_net_auth2(struct cli_state *cli, NTSTATUS result = NT_STATUS_UNSUCCESSFUL; fstring machine_acct; - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - if ( sec_chan == SEC_CHAN_DOMAIN ) fstr_sprintf( machine_acct, "%s$", lp_workgroup() ); else @@ -164,16 +106,12 @@ NTSTATUS cli_net_auth2(struct cli_state *cli, /* turn parameters into data stream */ - if (!net_io_q_auth_2("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_NETLOGON, NET_AUTH2, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!net_io_r_auth_2("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_AUTH2, + q, r, + qbuf, rbuf, + net_io_q_auth_2, + net_io_r_auth_2, + NT_STATUS_UNSUCCESSFUL); result = r.status; @@ -186,259 +124,257 @@ NTSTATUS cli_net_auth2(struct cli_state *cli, */ zerotime.time = 0; - if (cred_assert( &r.srv_chal, cli->sess_key, srv_chal, - zerotime) == 0) { + if (cred_assert( &r.srv_chal, cli->sess_key, srv_chal, zerotime) == 0) { /* * Server replied with bad credential. Fail. */ DEBUG(0,("cli_net_auth2: server %s replied with bad credential (bad machine \ -password ?).\n", cli->desthost )); - result = NT_STATUS_ACCESS_DENIED; - goto done; +password ?).\n", cli->cli->desthost )); + return NT_STATUS_ACCESS_DENIED; } *neg_flags = r.srv_flgs.neg_flags; } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } +#endif + +/**************************************************************************** + LSA Authenticate 2 -NTSTATUS rpccli_net_auth2(struct rpc_pipe_client *cli, - const char *server_name, - const char *account_name, - uint16 sec_chan_type, - const char *computer_name, - const DOM_CHAL *credentials, - uint32 *neg_flags, - DOM_CHAL *srv_chal) + Send the client credential, receive back a server credential. + The caller *must* ensure that the server credential returned matches the session key + encrypt of the server challenge originally received. JRA. +****************************************************************************/ + +static NTSTATUS rpccli_net_auth2(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *server_name, + const char *account_name, + uint16 sec_chan_type, + const char *computer_name, + uint32 *neg_flags_inout, + const DOM_CHAL *clnt_chal_in, + DOM_CHAL *srv_chal_out) { prs_struct qbuf, rbuf; NET_Q_AUTH_2 q; NET_R_AUTH_2 r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - /* create and send a MSRPC command with api NET_AUTH2 */ DEBUG(4,("cli_net_auth2: srv:%s acct:%s sc:%x mc: %s neg: %x\n", server_name, account_name, sec_chan_type, computer_name, - *neg_flags)); + *neg_flags_inout)); /* store the parameters */ init_q_auth_2(&q, server_name, account_name, sec_chan_type, - computer_name, credentials, *neg_flags); + computer_name, clnt_chal_in, *neg_flags_inout); /* turn parameters into data stream */ - if (!net_io_q_auth_2("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, NET_AUTH2, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!net_io_r_auth_2("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_AUTH2, + q, r, + qbuf, rbuf, + net_io_q_auth_2, + net_io_r_auth_2, + NT_STATUS_UNSUCCESSFUL); result = r.status; if (NT_STATUS_IS_OK(result)) { - *srv_chal = r.srv_chal; - *neg_flags = r.srv_flgs.neg_flags; + *srv_chal_out = r.srv_chal; + *neg_flags_inout = r.srv_flgs.neg_flags; } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } +#if 0 /* not currebntly used */ /**************************************************************************** -LSA Authenticate 3 + LSA Authenticate 3 -Send the client credential, receive back a server credential. -Ensure that the server credential returned matches the session key -encrypt of the server challenge originally received. JRA. + Send the client credential, receive back a server credential. + The caller *must* ensure that the server credential returned matches the session key + encrypt of the server challenge originally received. JRA. ****************************************************************************/ -NTSTATUS cli_net_auth3(struct cli_state *cli, - uint16 sec_chan, - uint32 *neg_flags, DOM_CHAL *srv_chal) +static NTSTATUS rpccli_net_auth3(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *server_name, + const char *account_name, + uint16 sec_chan_type, + const char *computer_name, + uint32 *neg_flags_inout, + const DOM_CHAL *clnt_chal_in, + DOM_CHAL *srv_chal_out) { prs_struct qbuf, rbuf; NET_Q_AUTH_3 q; NET_R_AUTH_3 r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - prs_init(&qbuf, MAX_PDU_FRAG_LEN, cli->mem_ctx, MARSHALL); - prs_init(&rbuf, 0, cli->mem_ctx, UNMARSHALL); - /* create and send a MSRPC command with api NET_AUTH2 */ DEBUG(4,("cli_net_auth3: srv:%s acct:%s sc:%x mc: %s chal %s neg: %x\n", - cli->srv_name_slash, cli->mach_acct, sec_chan, global_myname(), - credstr(cli->clnt_cred.challenge.data), *neg_flags)); + server_name, account_name, sec_chan_type, computer_name, + credstr(clnt_chal_in->data), *neg_flags_inout)); /* store the parameters */ - init_q_auth_3(&q, cli->srv_name_slash, cli->mach_acct, - sec_chan, global_myname(), &cli->clnt_cred.challenge, - *neg_flags); + init_q_auth_3(&q, server_name, account_name, sec_chan_type, + computer_name, clnt_chal_in, *neg_flags_inout); /* turn parameters into data stream */ - if (!net_io_q_auth_3("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_NETLOGON, NET_AUTH3, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!net_io_r_auth_3("", &r, &rbuf, 0)) { - goto done; - } - - result = r.status; + CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_AUTH3, + q, r, + qbuf, rbuf, + net_io_q_auth_3, + net_io_r_auth_3, + NT_STATUS_UNSUCCESSFUL); if (NT_STATUS_IS_OK(result)) { - UTIME zerotime; - - /* - * Check the returned value using the initial - * server received challenge. - */ - - zerotime.time = 0; - if (cred_assert( &r.srv_chal, cli->sess_key, srv_chal, - zerotime) == 0) { - - /* - * Server replied with bad credential. Fail. - */ - DEBUG(0,("cli_net_auth3: server %s replied with bad credential (bad machine \ -password ?).\n", cli->desthost )); - result = NT_STATUS_ACCESS_DENIED; - goto done; - } - *neg_flags = r.srv_flgs.neg_flags; + *srv_chal_out = r.srv_chal; + *neg_flags_inout = r.srv_flgs.neg_flags; } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } +#endif /* not currebntly used */ -/* Initialize domain session credentials */ +/**************************************************************************** + Wrapper function that uses the auth and auth2 calls to set up a NETLOGON + credentials chain. Stores the credentials in the struct dcinfo in the + netlogon pipe struct. +****************************************************************************/ -NTSTATUS cli_nt_setup_creds(struct cli_state *cli, - uint16 sec_chan, - const unsigned char mach_pwd[16], uint32 *neg_flags, int level) +NTSTATUS rpccli_netlogon_setup_creds(struct rpc_pipe_client *cli, + const char *server_name, + const char *domain, + const char *machine_account, + const char machine_pwd[16], + uint32 sec_chan_type, + uint32 *neg_flags_inout) { - DOM_CHAL clnt_chal; - DOM_CHAL srv_chal; - UTIME zerotime; - NTSTATUS result; + NTSTATUS result; + DOM_CHAL clnt_chal_send; + DOM_CHAL srv_chal_recv; + struct dcinfo *dc; - /******************* Request Challenge ********************/ + SMB_ASSERT(cli->pipe_idx == PI_NETLOGON); - generate_random_buffer(clnt_chal.data, 8); - - /* send a client challenge; receive a server challenge */ - result = cli_net_req_chal(cli, &clnt_chal, &srv_chal); + dc = cli->dc; + if (!dc) { + return NT_STATUS_INVALID_PARAMETER; + } - if (!NT_STATUS_IS_OK(result)) { - DEBUG(0,("cli_nt_setup_creds: request challenge failed\n")); - return result; - } - - /**************** Long-term Session key **************/ + /* Ensure we don't reuse any of this state. */ + ZERO_STRUCTP(dc); + + /* Store the machine account password we're going to use. */ + memcpy(dc->mach_pw, machine_pwd, 16); - /* calculate the session key */ - cred_session_key(&clnt_chal, &srv_chal, mach_pwd, - cli->sess_key); - memset((char *)cli->sess_key+8, '\0', 8); + fstrcpy(dc->remote_machine, "\\\\"); + fstrcat(dc->remote_machine, server_name); - /******************* Authenticate 2/3 ********************/ + fstrcpy(dc->domain, domain); - /* calculate auth-2/3 credentials */ - zerotime.time = 0; - cred_create(cli->sess_key, &clnt_chal, zerotime, &cli->clnt_cred.challenge); + fstr_sprintf( dc->mach_acct, "%s$", machine_account); + + /* Create the client challenge. */ + generate_random_buffer(clnt_chal_send.data, 8); + + /* Get the server challenge. */ + result = rpccli_net_req_chal(cli, + cli->mem_ctx, + dc->remote_machine, + machine_account, + &clnt_chal_send, + &srv_chal_recv); + + if (!NT_STATUS_IS_OK(result)) { + return result; + } + + /* Calculate the session key and client credentials */ + creds_client_init(dc, + &clnt_chal_send, + &srv_chal_recv, + machine_pwd, + &clnt_chal_send); /* - * Send client auth-2/3 challenge. - * Receive an auth-2/3 challenge response and check it. + * Send client auth-2 challenge and receive server repy. */ - switch (level) { - case 2: - result = cli_net_auth2(cli, sec_chan, neg_flags, &srv_chal); - break; - case 3: - result = cli_net_auth3(cli, sec_chan, neg_flags, &srv_chal); - break; - default: - DEBUG(1,("cli_nt_setup_creds: unsupported auth level: %d\n", level)); - break; + + result = rpccli_net_auth2(cli, + cli->mem_ctx, + dc->remote_machine, + dc->mach_acct, + sec_chan_type, + machine_account, + neg_flags_inout, + &clnt_chal_send, /* input. */ + &srv_chal_recv); /* output */ + + if (!NT_STATUS_IS_OK(result)) { + return result; } - if (!NT_STATUS_IS_OK(result)) - DEBUG(3,("cli_nt_setup_creds: auth%d challenge failed %s\n", level, nt_errstr(result))); + /* + * Check the returned value using the initial + * server received challenge. + */ - return result; + if (!creds_client_check(dc, &srv_chal_recv)) { + /* + * Server replied with bad credential. Fail. + */ + DEBUG(0,("rpccli_netlogon_setup_creds: server %s " + "replied with bad credential\n", + cli->cli->desthost )); + return NT_STATUS_ACCESS_DENIED; + } + + DEBUG(5,("rpccli_netlogon_setup_creds: server %s credential " + "chain established.\n", + cli->cli->desthost )); + + return NT_STATUS_OK; } /* Logon Control 2 */ -NTSTATUS cli_netlogon_logon_ctrl2(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_netlogon_logon_ctrl2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 query_level) { prs_struct qbuf, rbuf; NET_Q_LOGON_CTRL2 q; NET_R_LOGON_CTRL2 r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; + fstring server; ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Initialise input parameters */ - init_net_q_logon_ctrl2(&q, cli->srv_name_slash, query_level); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); + init_net_q_logon_ctrl2(&q, server, query_level); /* Marshall data and send request */ - if (!net_io_q_logon_ctrl2("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_NETLOGON, NET_LOGON_CTRL2, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!net_io_r_logon_ctrl2("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_LOGON_CTRL2, + q, r, + qbuf, rbuf, + net_io_q_logon_ctrl2, + net_io_r_logon_ctrl2, + NT_STATUS_UNSUCCESSFUL); result = r.status; - - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } @@ -456,72 +392,29 @@ NTSTATUS rpccli_netlogon_getdcname(struct rpc_pipe_client *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Initialise input parameters */ init_net_q_getdcname(&q, mydcname, domainname); /* Marshall data and send request */ - if (!net_io_q_getdcname("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, NET_GETDCNAME, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!net_io_r_getdcname("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - result = r.status; + CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_GETDCNAME, + q, r, + qbuf, rbuf, + net_io_q_getdcname, + net_io_r_getdcname, + NT_STATUS_UNSUCCESSFUL); - if (NT_STATUS_IS_OK(result)) + if (NT_STATUS_IS_OK(result)) { rpcstr_pull_unistr2_fstring(newdcname, &r.uni_dcname); - - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); + } return result; } -NTSTATUS cli_netlogon_getdcname(struct cli_state *cli, TALLOC_CTX *mem_ctx, - const char *domainname, fstring dcname) -{ - return rpccli_netlogon_getdcname(&cli->pipes[PI_NETLOGON], mem_ctx, - cli->srv_name_slash, domainname, - dcname); -} - -/**************************************************************************** -Generate the next creds to use. -****************************************************************************/ - -static void gen_next_creds( struct cli_state *cli, DOM_CRED *new_clnt_cred) -{ - /* - * Create the new client credentials. - */ - - cli->clnt_cred.timestamp.time = time(NULL); - - memcpy(new_clnt_cred, &cli->clnt_cred, sizeof(*new_clnt_cred)); - - /* Calculate the new credentials. */ - cred_create(cli->sess_key, &(cli->clnt_cred.challenge), - new_clnt_cred->timestamp, &(new_clnt_cred->challenge)); -} - /* Sam synchronisation */ -NTSTATUS cli_netlogon_sam_sync(struct cli_state *cli, TALLOC_CTX *mem_ctx, DOM_CRED *ret_creds, +NTSTATUS rpccli_netlogon_sam_sync(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 database_id, uint32 next_rid, uint32 *num_deltas, SAM_DELTA_HDR **hdr_deltas, SAM_DELTA_CTR **deltas) @@ -531,36 +424,31 @@ NTSTATUS cli_netlogon_sam_sync(struct cli_state *cli, TALLOC_CTX *mem_ctx, DOM_C NET_R_SAM_SYNC r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; DOM_CRED clnt_creds; + DOM_CRED ret_creds; ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + ZERO_STRUCT(ret_creds); /* Initialise input parameters */ - gen_next_creds(cli, &clnt_creds); + creds_client_step(cli->dc, &clnt_creds); - init_net_q_sam_sync(&q, cli->srv_name_slash, cli->clnt_name_slash + 2, - &clnt_creds, ret_creds, database_id, next_rid); + prs_set_session_key(&qbuf, cli->dc->sess_key); + prs_set_session_key(&rbuf, cli->dc->sess_key); - /* Marshall data and send request */ - - if (!net_io_q_sam_sync("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_NETLOGON, NET_SAM_SYNC, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + init_net_q_sam_sync(&q, cli->dc->remote_machine, global_myname(), + &clnt_creds, &ret_creds, database_id, next_rid); - /* Unmarshall response */ + /* Marshall data and send request */ - if (!net_io_r_sam_sync("", cli->sess_key, &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAM_SYNC, + q, r, + qbuf, rbuf, + net_io_q_sam_sync, + net_io_r_sam_sync, + NT_STATUS_UNSUCCESSFUL); /* Return results */ @@ -569,18 +457,20 @@ NTSTATUS cli_netlogon_sam_sync(struct cli_state *cli, TALLOC_CTX *mem_ctx, DOM_C *hdr_deltas = r.hdr_deltas; *deltas = r.deltas; - memcpy(ret_creds, &r.srv_creds, sizeof(*ret_creds)); - - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); + if (!NT_STATUS_IS_ERR(result)) { + /* Check returned credentials. */ + if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) { + DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n")); + return NT_STATUS_ACCESS_DENIED; + } + } return result; } /* Sam synchronisation */ -NTSTATUS cli_netlogon_sam_deltas(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_netlogon_sam_deltas(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 database_id, UINT64_S seqnum, uint32 *num_deltas, SAM_DELTA_HDR **hdr_deltas, @@ -595,33 +485,22 @@ NTSTATUS cli_netlogon_sam_deltas(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Initialise input parameters */ - gen_next_creds(cli, &clnt_creds); + creds_client_step(cli->dc, &clnt_creds); - init_net_q_sam_deltas(&q, cli->srv_name_slash, - cli->clnt_name_slash + 2, &clnt_creds, + init_net_q_sam_deltas(&q, cli->dc->remote_machine, + global_myname(), &clnt_creds, database_id, seqnum); /* Marshall data and send request */ - if (!net_io_q_sam_deltas("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_NETLOGON, NET_SAM_DELTAS, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!net_io_r_sam_deltas("", cli->sess_key, &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAM_DELTAS, + q, r, + qbuf, rbuf, + net_io_q_sam_deltas, + net_io_r_sam_deltas, + NT_STATUS_UNSUCCESSFUL); /* Return results */ @@ -630,47 +509,49 @@ NTSTATUS cli_netlogon_sam_deltas(struct cli_state *cli, TALLOC_CTX *mem_ctx, *hdr_deltas = r.hdr_deltas; *deltas = r.deltas; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); + if (!NT_STATUS_IS_ERR(result)) { + /* Check returned credentials. */ + if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) { + DEBUG(0,("cli_netlogon_sam_sync: credentials chain check failed\n")); + return NT_STATUS_ACCESS_DENIED; + } + } return result; } /* Logon domain user */ -NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx, - DOM_CRED *ret_creds, - const char *username, const char *password, +NTSTATUS rpccli_netlogon_sam_logon(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + const char *domain, + const char *username, + const char *password, int logon_type) { prs_struct qbuf, rbuf; NET_Q_SAM_LOGON q; NET_R_SAM_LOGON r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - DOM_CRED clnt_creds, dummy_rtn_creds; + DOM_CRED clnt_creds; + DOM_CRED ret_creds; NET_ID_INFO_CTR ctr; NET_USER_INFO_3 user; int validation_level = 3; + fstring clnt_name_slash; ZERO_STRUCT(q); ZERO_STRUCT(r); - ZERO_STRUCT(dummy_rtn_creds); - - /* Initialise parse structures */ + ZERO_STRUCT(ret_creds); - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + fstr_sprintf( clnt_name_slash, "\\\\%s", global_myname() ); /* Initialise input parameters */ - gen_next_creds(cli, &clnt_creds); + creds_client_step(cli->dc, &clnt_creds); q.validation_level = validation_level; - if (ret_creds == NULL) - ret_creds = &dummy_rtn_creds; - ctr.switch_value = logon_type; switch (logon_type) { @@ -679,11 +560,11 @@ NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx, nt_lm_owf_gen(password, nt_owf_user_pwd, lm_owf_user_pwd); - init_id_info1(&ctr.auth.id1, lp_workgroup(), + init_id_info1(&ctr.auth.id1, domain, 0, /* param_ctrl */ 0xdead, 0xbeef, /* LUID? */ - username, cli->clnt_name_slash, - (const char *)cli->sess_key, lm_owf_user_pwd, + username, clnt_name_slash, + cli->dc->sess_key, lm_owf_user_pwd, nt_owf_user_pwd); break; @@ -698,46 +579,45 @@ NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx, SMBencrypt(password, chal, local_lm_response); SMBNTencrypt(password, chal, local_nt_response); - init_id_info2(&ctr.auth.id2, lp_workgroup(), + init_id_info2(&ctr.auth.id2, domain, 0, /* param_ctrl */ 0xdead, 0xbeef, /* LUID? */ - username, cli->clnt_name_slash, chal, + username, clnt_name_slash, chal, local_lm_response, 24, local_nt_response, 24); break; } default: DEBUG(0, ("switch value %d not supported\n", ctr.switch_value)); - goto done; + return NT_STATUS_INVALID_INFO_CLASS; } - init_sam_info(&q.sam_id, cli->srv_name_slash, global_myname(), - &clnt_creds, ret_creds, logon_type, + r.user = &user; + + init_sam_info(&q.sam_id, cli->dc->remote_machine, global_myname(), + &clnt_creds, &ret_creds, logon_type, &ctr); /* Marshall data and send request */ - if (!net_io_q_sam_logon("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_NETLOGON, NET_SAMLOGON, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - r.user = &user; - - if (!net_io_r_sam_logon("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON, + q, r, + qbuf, rbuf, + net_io_q_sam_logon, + net_io_r_sam_logon, + NT_STATUS_UNSUCCESSFUL); /* Return results */ result = r.status; - memcpy(ret_creds, &r.srv_creds, sizeof(*ret_creds)); - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); + if (r.buffer_creds) { + /* Check returned credentials if present. */ + if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) { + DEBUG(0,("rpccli_netlogon_sam_logon: credentials chain check failed\n")); + return NT_STATUS_ACCESS_DENIED; + } + } return result; } @@ -751,52 +631,55 @@ NTSTATUS cli_netlogon_sam_logon(struct cli_state *cli, TALLOC_CTX *mem_ctx, NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, - const char *server_name_slash, - DOM_CRED *clnt_creds, - DOM_CRED *ret_creds, + const char *server, const char *username, const char *domain, const char *workstation, const uint8 chal[8], DATA_BLOB lm_response, DATA_BLOB nt_response, - NET_USER_INFO_3 *info3, - const uint8 *session_key) + NET_USER_INFO_3 *info3) { prs_struct qbuf, rbuf; NET_Q_SAM_LOGON q; NET_R_SAM_LOGON r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - DOM_CRED dummy_rtn_creds; NET_ID_INFO_CTR ctr; int validation_level = 3; - char *workstation_name_slash; - uint8 netlogon_sess_key[16]; + const char *workstation_name_slash; + const char *server_name_slash; static uint8 zeros[16]; + DOM_CRED clnt_creds; + DOM_CRED ret_creds; int i; ZERO_STRUCT(q); ZERO_STRUCT(r); - ZERO_STRUCT(dummy_rtn_creds); + ZERO_STRUCT(ret_creds); - workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation); - if (!workstation_name_slash) { - DEBUG(0, ("talloc_asprintf failed!\n")); - return NT_STATUS_NO_MEMORY; + creds_client_step(cli->dc, &clnt_creds); + + if (server[0] != '\\' && server[1] != '\\') { + server_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", server); + } else { + server_name_slash = server; } - /* Initialise parse structures */ + if (workstation[0] != '\\' && workstation[1] != '\\') { + workstation_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", workstation); + } else { + workstation_name_slash = workstation; + } - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + if (!workstation_name_slash || !server_name_slash) { + DEBUG(0, ("talloc_asprintf failed!\n")); + return NT_STATUS_NO_MEMORY; + } /* Initialise input parameters */ q.validation_level = validation_level; - if (ret_creds == NULL) - ret_creds = &dummy_rtn_creds; - ctr.switch_value = NET_LOGON_TYPE; init_id_info2(&ctr.auth.id2, domain, @@ -806,35 +689,28 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, lm_response.data, lm_response.length, nt_response.data, nt_response.length); init_sam_info(&q.sam_id, server_name_slash, global_myname(), - clnt_creds, ret_creds, NET_LOGON_TYPE, + &clnt_creds, &ret_creds, NET_LOGON_TYPE, &ctr); - /* Marshall data and send request */ - - if (!net_io_q_sam_logon("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, NET_SAMLOGON, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - r.user = info3; - if (!net_io_r_sam_logon("", &r, &rbuf, 0)) { - goto done; - } + /* Marshall data and send request */ + + CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SAMLOGON, + q, r, + qbuf, rbuf, + net_io_q_sam_logon, + net_io_r_sam_logon, + NT_STATUS_UNSUCCESSFUL); - ZERO_STRUCT(netlogon_sess_key); - memcpy(netlogon_sess_key, session_key, 8); - if (memcmp(zeros, info3->user_sess_key, 16) != 0) { - SamOEMhash(info3->user_sess_key, netlogon_sess_key, 16); + SamOEMhash(info3->user_sess_key, cli->dc->sess_key, 16); } else { memset(info3->user_sess_key, '\0', 16); } if (memcmp(zeros, info3->lm_sess_key, 8) != 0) { - SamOEMhash(info3->lm_sess_key, netlogon_sess_key, 8); + SamOEMhash(info3->lm_sess_key, cli->dc->sess_key, 8); } else { memset(info3->lm_sess_key, '\0', 8); } @@ -847,108 +723,62 @@ NTSTATUS rpccli_netlogon_sam_network_logon(struct rpc_pipe_client *cli, /* Return results */ result = r.status; - memcpy(ret_creds, &r.srv_creds, sizeof(*ret_creds)); - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); + if (r.buffer_creds) { + /* Check returned credentials if present. */ + if (!creds_client_check(cli->dc, &r.srv_creds.challenge)) { + DEBUG(0,("rpccli_netlogon_sam_network_logon: credentials chain check failed\n")); + return NT_STATUS_ACCESS_DENIED; + } + } return result; } -NTSTATUS cli_netlogon_sam_network_logon(struct cli_state *cli, - TALLOC_CTX *mem_ctx, - DOM_CRED *ret_creds, - const char *username, - const char *domain, - const char *workstation, - const uint8 chal[8], - DATA_BLOB lm_response, - DATA_BLOB nt_response, - NET_USER_INFO_3 *info3) -{ - DOM_CRED clnt_creds; - - gen_next_creds(cli, &clnt_creds); - - return rpccli_netlogon_sam_network_logon(&cli->pipes[PI_NETLOGON], - mem_ctx, cli->srv_name_slash, - &clnt_creds, - ret_creds, username, - domain, workstation, chal, - lm_response, nt_response, - info3, cli->sess_key); -} - /*************************************************************************** LSA Server Password Set. ****************************************************************************/ -NTSTATUS cli_net_srv_pwset(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_net_srv_pwset(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *machine_name, uint8 hashed_mach_pwd[16]) { prs_struct rbuf; prs_struct qbuf; - DOM_CRED new_clnt_cred; - NET_Q_SRV_PWSET q_s; + DOM_CRED clnt_creds; + NET_Q_SRV_PWSET q; + NET_R_SRV_PWSET r; uint16 sec_chan_type = 2; - NTSTATUS nt_status; + NTSTATUS result; - gen_next_creds( cli, &new_clnt_cred); - - prs_init(&qbuf , 1024, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + creds_client_step(cli->dc, &clnt_creds); - DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s clnt %s %x\n", - cli->srv_name_slash, cli->mach_acct, sec_chan_type, machine_name, - credstr(new_clnt_cred.challenge.data), new_clnt_cred.timestamp.time)); + DEBUG(4,("cli_net_srv_pwset: srv:%s acct:%s sc: %d mc: %s\n", + cli->dc->remote_machine, cli->dc->mach_acct, sec_chan_type, machine_name)); /* store the parameters */ - init_q_srv_pwset(&q_s, cli->srv_name_slash, (const char *)cli->sess_key, - cli->mach_acct, sec_chan_type, machine_name, - &new_clnt_cred, hashed_mach_pwd); - - /* turn parameters into data stream */ - if(!net_io_q_srv_pwset("", &q_s, &qbuf, 0)) { - DEBUG(0,("cli_net_srv_pwset: Error : failed to marshall NET_Q_SRV_PWSET struct.\n")); - nt_status = NT_STATUS_UNSUCCESSFUL; - goto done; - } + init_q_srv_pwset(&q, cli->dc->remote_machine, (const char *)cli->dc->sess_key, + cli->dc->mach_acct, sec_chan_type, machine_name, + &clnt_creds, hashed_mach_pwd); - /* send the data on \PIPE\ */ - if (rpc_api_pipe_req(cli, PI_NETLOGON, NET_SRVPWSET, &qbuf, &rbuf)) - { - NET_R_SRV_PWSET r_s; - - if (!net_io_r_srv_pwset("", &r_s, &rbuf, 0)) { - nt_status = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - nt_status = r_s.status; + CLI_DO_RPC(cli, mem_ctx, PI_NETLOGON, NET_SRVPWSET, + q, r, + qbuf, rbuf, + net_io_q_srv_pwset, + net_io_r_srv_pwset, + NT_STATUS_UNSUCCESSFUL); - if (!NT_STATUS_IS_OK(r_s.status)) - { - /* report error code */ - DEBUG(0,("cli_net_srv_pwset: %s\n", nt_errstr(nt_status))); - } + result = r.status; - /* Update the credentials. */ - if (!clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &(r_s.srv_cred))) - { - /* - * Server replied with bad credential. Fail. - */ - DEBUG(0,("cli_net_srv_pwset: server %s replied with bad credential (bad machine \ -password ?).\n", cli->desthost )); - nt_status = NT_STATUS_UNSUCCESSFUL; - } + if (!NT_STATUS_IS_OK(result)) { + /* report error code */ + DEBUG(0,("cli_net_srv_pwset: %s\n", nt_errstr(result))); } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - - return nt_status; -} + /* Always check returned credentials. */ + if (!creds_client_check(cli->dc, &r.srv_cred.challenge)) { + DEBUG(0,("rpccli_net_srv_pwset: credentials chain check failed\n")); + return NT_STATUS_ACCESS_DENIED; + } + return result; +} diff --git a/source3/rpc_client/cli_pipe.c b/source3/rpc_client/cli_pipe.c index 230750817a9..df34b1c3d95 100644 --- a/source3/rpc_client/cli_pipe.c +++ b/source3/rpc_client/cli_pipe.c @@ -1,11 +1,7 @@ /* * Unix SMB/CIFS implementation. * RPC Pipe client / server routines - * Copyright (C) Andrew Tridgell 1992-1998, - * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, - * Copyright (C) Paul Ashton 1998. - * Copyright (C) Jeremy Allison 1999. - * Copyright (C) Andrew Bartlett 2003. + * Largely rewritten by Jeremy Allison 2005. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -29,23 +25,37 @@ extern struct pipe_id_info pipe_names[]; -/* convert pipe auth flags into the RPC auth type and level */ +/******************************************************************** + Map internal value to wire value. + ********************************************************************/ -void get_auth_type_level(int pipe_auth_flags, int *auth_type, int *auth_level) +static int map_pipe_auth_type_to_rpc_auth_type(enum pipe_auth_type auth_type) { - *auth_type = 0; - *auth_level = 0; - if (pipe_auth_flags & AUTH_PIPE_SEAL) { - *auth_level = RPC_PIPE_AUTH_SEAL_LEVEL; - } else if (pipe_auth_flags & AUTH_PIPE_SIGN) { - *auth_level = RPC_PIPE_AUTH_SIGN_LEVEL; - } - - if (pipe_auth_flags & AUTH_PIPE_NETSEC) { - *auth_type = NETSEC_AUTH_TYPE; - } else if (pipe_auth_flags & AUTH_PIPE_NTLMSSP) { - *auth_type = NTLMSSP_AUTH_TYPE; + switch (auth_type) { + + case PIPE_AUTH_TYPE_NONE: + return RPC_ANONYMOUS_AUTH_TYPE; + + case PIPE_AUTH_TYPE_NTLMSSP: + return RPC_NTLMSSP_AUTH_TYPE; + + case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: + case PIPE_AUTH_TYPE_SPNEGO_KRB5: + return RPC_SPNEGO_AUTH_TYPE; + + case PIPE_AUTH_TYPE_SCHANNEL: + return RPC_SCHANNEL_AUTH_TYPE; + + case PIPE_AUTH_TYPE_KRB5: + return RPC_KRB5_AUTH_TYPE; + + default: + DEBUG(0,("map_pipe_auth_type_to_rpc_type: unknown pipe " + "auth type %u\n", + (unsigned int)auth_type )); + break; } + return -1; } /******************************************************************** @@ -60,55 +70,81 @@ static uint32 get_rpc_call_id(void) /******************************************************************* Use SMBreadX to get rest of one fragment's worth of rpc data. + Will expand the current_pdu struct to the correct size. ********************************************************************/ -static BOOL rpc_read(struct rpc_pipe_client *cli, prs_struct *rdata, - uint32 data_to_read, uint32 *rdata_offset) +static NTSTATUS rpc_read(struct rpc_pipe_client *cli, + prs_struct *current_pdu, + uint32 data_to_read, + uint32 *current_pdu_offset) { size_t size = (size_t)cli->max_recv_frag; - int stream_offset = 0; - int num_read; + uint32 stream_offset = 0; + ssize_t num_read; char *pdata; - int extra_data_size = ((int)*rdata_offset) + ((int)data_to_read) - (int)prs_data_size(rdata); + ssize_t extra_data_size = ((ssize_t)*current_pdu_offset) + ((ssize_t)data_to_read) - (ssize_t)prs_data_size(current_pdu); - DEBUG(5,("rpc_read: data_to_read: %u rdata offset: %u extra_data_size: %d\n", - (int)data_to_read, (unsigned int)*rdata_offset, extra_data_size)); + DEBUG(5,("rpc_read: data_to_read: %u current_pdu offset: %u extra_data_size: %d\n", + (unsigned int)data_to_read, (unsigned int)*current_pdu_offset, (int)extra_data_size )); /* * Grow the buffer if needed to accommodate the data to be read. */ if (extra_data_size > 0) { - if(!prs_force_grow(rdata, (uint32)extra_data_size)) { - DEBUG(0,("rpc_read: Failed to grow parse struct by %d bytes.\n", extra_data_size )); - return False; + if(!prs_force_grow(current_pdu, (uint32)extra_data_size)) { + DEBUG(0,("rpc_read: Failed to grow parse struct by %d bytes.\n", (int)extra_data_size )); + return NT_STATUS_NO_MEMORY; } - DEBUG(5,("rpc_read: grew buffer by %d bytes to %u\n", extra_data_size, prs_data_size(rdata) )); + DEBUG(5,("rpc_read: grew buffer by %d bytes to %u\n", (int)extra_data_size, prs_data_size(current_pdu) )); } - pdata = prs_data_p(rdata) + *rdata_offset; + pdata = prs_data_p(current_pdu) + *current_pdu_offset; - do /* read data using SMBreadX */ - { - uint32 ecode; - uint8 eclass; - - if (size > (size_t)data_to_read) + do { + /* read data using SMBreadX */ + if (size > (size_t)data_to_read) { size = (size_t)data_to_read; + } - num_read = (int)cli_read(cli->cli, cli->fnum, pdata, + num_read = cli_read(cli->cli, cli->fnum, pdata, (off_t)stream_offset, size); - DEBUG(5,("rpc_read: num_read = %d, read offset: %d, to read: %d\n", - num_read, stream_offset, data_to_read)); + DEBUG(5,("rpc_read: num_read = %d, read offset: %u, to read: %u\n", + (int)num_read, (unsigned int)stream_offset, (unsigned int)data_to_read)); + /* + * A dos error of ERRDOS/ERRmoredata is not an error. + */ if (cli_is_dos_error(cli->cli)) { - cli_dos_error(cli->cli, &eclass, &ecode); - if (eclass != ERRDOS && ecode != ERRmoredata) { - DEBUG(0,("rpc_read: Error %d/%u in cli_read\n", - eclass, (unsigned int)ecode)); - return False; - } + uint32 ecode; + uint8 eclass; + cli_dos_error(cli->cli, &eclass, &ecode); + if (eclass != ERRDOS && ecode != ERRmoredata) { + DEBUG(0,("rpc_read: DOS Error %d/%u (%s) in cli_read on pipe %s\n", + eclass, (unsigned int)ecode, + cli_errstr(cli->cli), + cli->pipe_name )); + return dos_to_ntstatus(eclass, ecode); + } + } + + /* + * Likewise for NT_STATUS_BUFFER_TOO_SMALL + */ + if (cli_is_nt_error(cli->cli)) { + if (!NT_STATUS_EQUAL(cli_nt_error(cli->cli), NT_STATUS_BUFFER_TOO_SMALL)) { + DEBUG(0,("rpc_read: Error (%s) in cli_read on pipe %s\n", + nt_errstr(cli_nt_error(cli->cli)), + cli->pipe_name )); + return cli_nt_error(cli->cli); + } + } + + if (num_read == -1) { + DEBUG(0,("rpc_read: Error - cli_read on pipe %s returned -1\n", + cli->pipe_name )); + return cli_get_nt_error(cli->cli); } data_to_read -= num_read; @@ -119,262 +155,565 @@ static BOOL rpc_read(struct rpc_pipe_client *cli, prs_struct *rdata, /* && err == (0x80000000 | STATUS_BUFFER_OVERFLOW)); */ /* - * Update the current offset into rdata by the amount read. + * Update the current offset into current_pdu by the amount read. */ - *rdata_offset += stream_offset; - - return True; + *current_pdu_offset += stream_offset; + return NT_STATUS_OK; } /**************************************************************************** - Checks the header. This will set the endian bit in the rdata prs_struct. JRA. + Try and get a PDU's worth of data from current_pdu. If not, then read more + from the wire. ****************************************************************************/ -static BOOL rpc_check_hdr(prs_struct *rdata, RPC_HDR *rhdr, - BOOL *first, BOOL *last, uint32 *len) +static NTSTATUS cli_pipe_get_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu) { - DEBUG(5,("rpc_check_hdr: rdata->data_size = %u\n", (uint32)prs_data_size(rdata) )); - - /* Next call sets endian bit. */ + NTSTATUS ret = NT_STATUS_OK; + uint32 current_pdu_len = prs_data_size(current_pdu); + + /* Ensure we have at least RPC_HEADER_LEN worth of data to parse. */ + if (current_pdu_len < RPC_HEADER_LEN) { + /* rpc_read expands the current_pdu struct as neccessary. */ + ret = rpc_read(cli, current_pdu, RPC_HEADER_LEN - current_pdu_len, ¤t_pdu_len); + if (!NT_STATUS_IS_OK(ret)) { + return ret; + } + } - if(!smb_io_rpc_hdr("rpc_hdr ", rhdr, rdata, 0)) { - DEBUG(0,("rpc_check_hdr: Failed to unmarshall RPC_HDR.\n")); - return False; + /* This next call sets the endian bit correctly in current_pdu. */ + /* We will propagate this to rbuf later. */ + if(!smb_io_rpc_hdr("rpc_hdr ", prhdr, current_pdu, 0)) { + DEBUG(0,("cli_pipe_get_current_pdu: Failed to unmarshall RPC_HDR.\n")); + return NT_STATUS_BUFFER_TOO_SMALL; } - if (prs_offset(rdata) != RPC_HEADER_LEN) { - DEBUG(0,("rpc_check_hdr: offset was %x, should be %x.\n", prs_offset(rdata), RPC_HEADER_LEN)); - return False; + /* Ensure we have frag_len bytes of data. */ + if (current_pdu_len < prhdr->frag_len) { + /* rpc_read expands the current_pdu struct as neccessary. */ + ret = rpc_read(cli, current_pdu, (uint32)prhdr->frag_len - current_pdu_len, ¤t_pdu_len); + if (!NT_STATUS_IS_OK(ret)) { + return ret; + } } - (*first) = ((rhdr->flags & RPC_FLG_FIRST) != 0); - (*last) = ((rhdr->flags & RPC_FLG_LAST ) != 0); - (*len) = (uint32)rhdr->frag_len - prs_data_size(rdata); + if (current_pdu_len < prhdr->frag_len) { + return NT_STATUS_BUFFER_TOO_SMALL; + } - return (rhdr->pkt_type != RPC_FAULT); + return NT_STATUS_OK; } /**************************************************************************** - Verify data on an rpc pipe. - The VERIFY & SEAL code is only executed on packets that look like this : + NTLMSSP specific sign/seal. + Virtually identical to rpc_server/srv_pipe.c:api_pipe_ntlmssp_auth_process. + In fact I should probably abstract these into identical pieces of code... JRA. + ****************************************************************************/ - Request/Response PDU's look like the following... +static NTSTATUS cli_pipe_verify_ntlmssp(struct rpc_pipe_client *cli, RPC_HDR *prhdr, + prs_struct *current_pdu, + uint8 *p_ss_padding_len) +{ + RPC_HDR_AUTH auth_info; + uint32 save_offset = prs_offset(current_pdu); + uint32 auth_len = prhdr->auth_len; + NTLMSSP_STATE *ntlmssp_state = cli->auth.a_u.ntlmssp_state; + unsigned char *data = NULL; + size_t data_len; + unsigned char *full_packet_data = NULL; + size_t full_packet_data_len; + DATA_BLOB auth_blob; + NTSTATUS status; + + if (cli->auth.auth_level == PIPE_AUTH_LEVEL_NONE || cli->auth.auth_level == PIPE_AUTH_LEVEL_CONNECT) { + return NT_STATUS_OK; + } - |<------------------PDU len----------------------------------------------->| - |<-HDR_LEN-->|<--REQ LEN------>|.............|<-AUTH_HDRLEN->|<-AUTH_LEN-->| + if (!ntlmssp_state) { + return NT_STATUS_INVALID_PARAMETER; + } - +------------+-----------------+-------------+---------------+-------------+ - | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA | - +------------+-----------------+-------------+---------------+-------------+ + /* Ensure there's enough data for an authenticated response. */ + if ((auth_len > RPC_MAX_SIGN_SIZE) || + (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) { + DEBUG(0,("cli_pipe_verify_ntlmssp: auth_len %u is too large.\n", + (unsigned int)auth_len )); + return NT_STATUS_BUFFER_TOO_SMALL; + } - Never on bind requests/responses. - ****************************************************************************/ + /* + * We need the full packet data + length (minus auth stuff) as well as the packet data + length + * after the RPC header. + * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal + * functions as NTLMv2 checks the rpc headers also. + */ + + data = (unsigned char *)(prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN); + data_len = (size_t)(prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len); + + full_packet_data = prs_data_p(current_pdu); + full_packet_data_len = prhdr->frag_len - auth_len; + + /* Pull the auth header and the following data into a blob. */ + if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) { + DEBUG(0,("cli_pipe_verify_ntlmssp: cannot move offset to %u.\n", + (unsigned int)RPC_HEADER_LEN + (unsigned int)RPC_HDR_RESP_LEN + (unsigned int)data_len )); + return NT_STATUS_BUFFER_TOO_SMALL; + } + + if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) { + DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unmarshall RPC_HDR_AUTH.\n")); + return NT_STATUS_BUFFER_TOO_SMALL; + } + + auth_blob.data = prs_data_p(current_pdu) + prs_offset(current_pdu); + auth_blob.length = auth_len; + + switch (cli->auth.auth_level) { + case PIPE_AUTH_LEVEL_PRIVACY: + /* Data is encrypted. */ + status = ntlmssp_unseal_packet(ntlmssp_state, + data, data_len, + full_packet_data, + full_packet_data_len, + &auth_blob); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("cli_pipe_verify_ntlmssp: failed to unseal " + "packet from remote machine %s on pipe %s " + "fnum 0x%x. Error was %s.\n", + cli->cli->desthost, + cli->pipe_name, + (unsigned int)cli->fnum, + nt_errstr(status) )); + return status; + } + break; + case PIPE_AUTH_LEVEL_INTEGRITY: + /* Data is signed. */ + status = ntlmssp_check_packet(ntlmssp_state, + data, data_len, + full_packet_data, + full_packet_data_len, + &auth_blob); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("cli_pipe_verify_ntlmssp: check signing failed on " + "packet from remote machine %s on pipe %s " + "fnum 0x%x. Error was %s.\n", + cli->cli->desthost, + cli->pipe_name, + (unsigned int)cli->fnum, + nt_errstr(status) )); + return status; + } + break; + default: + DEBUG(0,("cli_pipe_verify_ntlmssp: unknown internal auth level %d\n", + cli->auth.auth_level )); + return NT_STATUS_INVALID_INFO_CLASS; + } -static BOOL rpc_auth_pipe(struct rpc_pipe_client *cli, prs_struct *rdata, - uint32 fragment_start, int len, int auth_len, uint8 pkt_type, - int *pauth_padding_len) -{ - /* - * The following is that length of the data we must sign or seal. - * This doesn't include the RPC headers or the auth_len or the RPC_HDR_AUTH_LEN - * preceeding the auth_data. + * Return the current pointer to the data offset. */ - int data_len = len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len; + if(!prs_set_offset(current_pdu, save_offset)) { + DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n", + (unsigned int)save_offset )); + return NT_STATUS_BUFFER_TOO_SMALL; + } /* - * The start of the data to sign/seal is just after the RPC headers. + * Remember the padding length. We must remove it from the real data + * stream once the sign/seal is done. */ - char *reply_data = prs_data_p(rdata) + fragment_start + RPC_HEADER_LEN + RPC_HDR_REQ_LEN; - RPC_HDR_AUTH rhdr_auth; + *p_ss_padding_len = auth_info.auth_pad_len; + + return NT_STATUS_OK; +} + +/**************************************************************************** + schannel specific sign/seal. + ****************************************************************************/ - char *dp = prs_data_p(rdata) + fragment_start + len - - RPC_HDR_AUTH_LEN - auth_len; - prs_struct auth_verf; +static NTSTATUS cli_pipe_verify_schannel(struct rpc_pipe_client *cli, RPC_HDR *prhdr, + prs_struct *current_pdu, + uint8 *p_ss_padding_len) +{ + RPC_HDR_AUTH auth_info; + RPC_AUTH_SCHANNEL_CHK schannel_chk; + uint32 auth_len = prhdr->auth_len; + uint32 save_offset = prs_offset(current_pdu); + struct schannel_auth_struct *schannel_auth = cli->auth.a_u.schannel_auth; + uint32 data_len; + + if (cli->auth.auth_level == PIPE_AUTH_LEVEL_NONE || cli->auth.auth_level == PIPE_AUTH_LEVEL_CONNECT) { + return NT_STATUS_OK; + } - *pauth_padding_len = 0; + if (auth_len != RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) { + DEBUG(0,("cli_pipe_verify_schannel: auth_len %u.\n", (unsigned int)auth_len )); + return NT_STATUS_INVALID_PARAMETER; + } - if (auth_len == 0) { - if (cli->pipe_auth_flags == 0) { - /* move along, nothing to see here */ - return True; - } + if (!schannel_auth) { + return NT_STATUS_INVALID_PARAMETER; + } - DEBUG(2, ("No authenticaton header recienved on reply, but this pipe is authenticated\n")); - return False; + /* Ensure there's enough data for an authenticated response. */ + if ((auth_len > RPC_MAX_SIGN_SIZE) || + (RPC_HEADER_LEN + RPC_HDR_RESP_LEN + RPC_HDR_AUTH_LEN + auth_len > prhdr->frag_len)) { + DEBUG(0,("cli_pipe_verify_schannel: auth_len %u is too large.\n", + (unsigned int)auth_len )); + return NT_STATUS_INVALID_PARAMETER; } - DEBUG(5,("rpc_auth_pipe: pkt_type: %d len: %d auth_len: %d NTLMSSP %s schannel %s sign %s seal %s \n", - pkt_type, len, auth_len, - BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP), - BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_NETSEC), - BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_SIGN), - BOOLSTR(cli->pipe_auth_flags & AUTH_PIPE_SEAL))); + data_len = prhdr->frag_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - RPC_HDR_AUTH_LEN - auth_len; - if (dp - prs_data_p(rdata) > prs_data_size(rdata)) { - DEBUG(0,("rpc_auth_pipe: schannel auth data > data size !\n")); - return False; + if(!prs_set_offset(current_pdu, RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len)) { + DEBUG(0,("cli_pipe_verify_schannel: cannot move offset to %u.\n", + (unsigned int)RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len )); + return NT_STATUS_BUFFER_TOO_SMALL; + } + + if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, current_pdu, 0)) { + DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshall RPC_HDR_AUTH.\n")); + return NT_STATUS_BUFFER_TOO_SMALL; } - DEBUG(10,("rpc_auth_pipe: packet:\n")); - dump_data(100, dp, auth_len); + if (auth_info.auth_type != RPC_SCHANNEL_AUTH_TYPE) { + DEBUG(0,("cli_pipe_verify_schannel: Invalid auth info %d on schannel\n", + auth_info.auth_type)); + return NT_STATUS_BUFFER_TOO_SMALL; + } - prs_init(&auth_verf, 0, cli->cli->mem_ctx, UNMARSHALL); - - /* The endinness must be preserved. JRA. */ - prs_set_endian_data( &auth_verf, rdata->bigendian_data); - - /* Point this new parse struct at the auth section of the main - parse struct - rather than copying it. Avoids needing to - free it on every error - */ - prs_give_memory(&auth_verf, dp, RPC_HDR_AUTH_LEN + auth_len, False /* not dynamic */); - prs_set_offset(&auth_verf, 0); + if(!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN, + &schannel_chk, current_pdu, 0)) { + DEBUG(0,("cli_pipe_verify_schannel: failed to unmarshal RPC_AUTH_SCHANNEL_CHK.\n")); + return NT_STATUS_BUFFER_TOO_SMALL; + } - { - int auth_type; - int auth_level; - if (!smb_io_rpc_hdr_auth("auth_hdr", &rhdr_auth, &auth_verf, 0)) { - DEBUG(0, ("rpc_auth_pipe: Could not parse auth header\n")); - return False; - } + if (!schannel_decode(schannel_auth, + cli->auth.auth_level, + SENDER_IS_ACCEPTOR, + &schannel_chk, + prs_data_p(current_pdu)+RPC_HEADER_LEN+RPC_HDR_RESP_LEN, + data_len)) { + DEBUG(3,("cli_pipe_verify_schannel: failed to decode PDU " + "Connection to remote machine %s " + "pipe %s fnum 0x%x.\n", + cli->cli->desthost, + cli->pipe_name, + (unsigned int)cli->fnum )); + return NT_STATUS_INVALID_PARAMETER; + } - /* Let the caller know how much padding at the end of the data */ - *pauth_padding_len = rhdr_auth.auth_pad_len; - - /* Check it's the type of reply we were expecting to decode */ + /* The sequence number gets incremented on both send and receive. */ + schannel_auth->seq_num++; - get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level); - if (rhdr_auth.auth_type != auth_type) { - DEBUG(0, ("BAD auth type %d (should be %d)\n", - rhdr_auth.auth_type, auth_type)); - return False; - } - - if (rhdr_auth.auth_level != auth_level) { - DEBUG(0, ("BAD auth level %d (should be %d)\n", - rhdr_auth.auth_level, auth_level)); - return False; - } + /* + * Return the current pointer to the data offset. + */ + + if(!prs_set_offset(current_pdu, save_offset)) { + DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n", + (unsigned int)save_offset )); + return NT_STATUS_BUFFER_TOO_SMALL; } - if (pkt_type == RPC_BINDACK) { - if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) { - /* copy the next auth_len bytes into a buffer for - later use */ + /* + * Remember the padding length. We must remove it from the real data + * stream once the sign/seal is done. + */ + + *p_ss_padding_len = auth_info.auth_pad_len; + + return NT_STATUS_OK; +} - DATA_BLOB ntlmssp_verf = data_blob(NULL, auth_len); - BOOL store_ok; +/**************************************************************************** + Do the authentication checks on an incoming pdu. Check sign and unseal etc. + ****************************************************************************/ - /* save the reply away, for use a little later */ - prs_copy_data_out((char *)ntlmssp_verf.data, &auth_verf, auth_len); +static NTSTATUS cli_pipe_validate_rpc_response(struct rpc_pipe_client *cli, RPC_HDR *prhdr, + prs_struct *current_pdu, + uint8 *p_ss_padding_len) +{ + NTSTATUS ret = NT_STATUS_OK; - store_ok = (NT_STATUS_IS_OK(ntlmssp_store_response(cli->ntlmssp_pipe_state, - ntlmssp_verf))); + /* Paranioa checks for auth_len. */ + if (prhdr->auth_len) { + if (prhdr->auth_len > prhdr->frag_len) { + return NT_STATUS_INVALID_PARAMETER; + } - data_blob_free(&ntlmssp_verf); - return store_ok; - } - else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) { - /* nothing to do here - we don't seem to be able to - validate the bindack based on VL's comments */ - return True; + if (prhdr->auth_len + RPC_HDR_AUTH_LEN < prhdr->auth_len || + prhdr->auth_len + RPC_HDR_AUTH_LEN < RPC_HDR_AUTH_LEN) { + /* Integer wrap attempt. */ + return NT_STATUS_INVALID_PARAMETER; } } - - if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) { - NTSTATUS nt_status; - DATA_BLOB sig; - if ((cli->pipe_auth_flags & AUTH_PIPE_SIGN) || - (cli->pipe_auth_flags & AUTH_PIPE_SEAL)) { - if (auth_len != RPC_AUTH_NTLMSSP_CHK_LEN) { - DEBUG(0,("rpc_auth_pipe: wrong ntlmssp auth len %d\n", auth_len)); - return False; + + /* + * Now we have a complete RPC request PDU fragment, try and verify any auth data. + */ + + switch(cli->auth.auth_type) { + case PIPE_AUTH_TYPE_NONE: + if (prhdr->auth_len) { + DEBUG(3, ("cli_pipe_validate_rpc_response: Connection to remote machine %s " + "pipe %s fnum 0x%x - got non-zero auth len %u.\n", + cli->cli->desthost, + cli->pipe_name, + (unsigned int)cli->fnum, + (unsigned int)prhdr->auth_len )); + return NT_STATUS_INVALID_PARAMETER; } - sig = data_blob(NULL, auth_len); - prs_copy_data_out((char *)sig.data, &auth_verf, auth_len); - } - - /* - * Unseal any sealed data in the PDU, not including the - * 8 byte auth_header or the auth_data. - */ + break; - /* - * Now unseal and check the auth verifier in the auth_data at - * the end of the packet. - */ + case PIPE_AUTH_TYPE_NTLMSSP: + case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: + ret = cli_pipe_verify_ntlmssp(cli, prhdr, current_pdu, p_ss_padding_len); + if (!NT_STATUS_IS_OK(ret)) { + return ret; + } + break; - if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) { - if (data_len < 0) { - DEBUG(1, ("Can't unseal - data_len < 0!!\n")); - return False; + case PIPE_AUTH_TYPE_SCHANNEL: + ret = cli_pipe_verify_schannel(cli, prhdr, current_pdu, p_ss_padding_len); + if (!NT_STATUS_IS_OK(ret)) { + return ret; } - nt_status = ntlmssp_unseal_packet(cli->ntlmssp_pipe_state, - (unsigned char *)reply_data, data_len, - &sig); - } - else if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) { - nt_status = ntlmssp_check_packet(cli->ntlmssp_pipe_state, - (const unsigned char *)reply_data, data_len, - &sig); - } + break; + + case PIPE_AUTH_TYPE_KRB5: + case PIPE_AUTH_TYPE_SPNEGO_KRB5: + default: + DEBUG(3, ("cli_pipe_validate_rpc_response: Connection to remote machine %s " + "pipe %s fnum %x - unknown internal auth type %u.\n", + cli->cli->desthost, + cli->pipe_name, + (unsigned int)cli->fnum, + cli->auth.auth_type )); + return NT_STATUS_INVALID_INFO_CLASS; + } - data_blob_free(&sig); + return NT_STATUS_OK; +} - if (!NT_STATUS_IS_OK(nt_status)) { - DEBUG(0, ("rpc_auth_pipe: could not validate " - "incoming NTLMSSP packet!\n")); - return False; - } +/**************************************************************************** + Do basic authentication checks on an incoming pdu. + ****************************************************************************/ + +static NTSTATUS cli_pipe_validate_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, + prs_struct *current_pdu, + uint8 expected_pkt_type, + char **ppdata, + uint32 *pdata_len, + prs_struct *return_data) +{ + + NTSTATUS ret = NT_STATUS_OK; + uint32 current_pdu_len = prs_data_size(current_pdu); + + if (current_pdu_len != prhdr->frag_len) { + DEBUG(5,("cli_pipe_validate_current_pdu: incorrect pdu length %u, expected %u\n", + (unsigned int)current_pdu_len, (unsigned int)prhdr->frag_len )); + return NT_STATUS_INVALID_PARAMETER; } - if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) { - RPC_AUTH_NETSEC_CHK chk; + /* + * Point the return values at the real data including the RPC + * header. Just in case the caller wants it. + */ + *ppdata = prs_data_p(current_pdu); + *pdata_len = current_pdu_len; - if ( (auth_len != RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN) - && (auth_len != RPC_AUTH_NETSEC_SIGN_ONLY_CHK_LEN) ) - { - DEBUG(0,("rpc_auth_pipe: wrong schannel auth len %d\n", auth_len)); - return False; - } + /* Ensure we have the correct type. */ + switch (prhdr->pkt_type) { + case RPC_ALTCONTRESP: + case RPC_BINDACK: + + /* Alter context and bind ack share the same packet definitions. */ + break; - /* can't seal with no nonce */ - if ( (cli->pipe_auth_flags & AUTH_PIPE_SEAL) - && (auth_len != RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN) ) + + case RPC_RESPONSE: { - DEBUG(0,("rpc_auth_pipe: sealing not supported with schannel auth len %d\n", auth_len)); - return False; + RPC_HDR_RESP rhdr_resp; + uint8 ss_padding_len = 0; + + if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) { + DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n")); + return NT_STATUS_BUFFER_TOO_SMALL; + } + + /* Here's where we deal with incoming sign/seal. */ + ret = cli_pipe_validate_rpc_response(cli, prhdr, + current_pdu, &ss_padding_len); + if (!NT_STATUS_IS_OK(ret)) { + return ret; + } + + /* Point the return values at the NDR data. Remember to remove any ss padding. */ + *ppdata = prs_data_p(current_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN; + + if (current_pdu_len < RPC_HEADER_LEN + RPC_HDR_RESP_LEN + ss_padding_len) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + + *pdata_len = current_pdu_len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - ss_padding_len; + + /* Remember to remove the auth footer. */ + if (prhdr->auth_len) { + /* We've already done integer wrap tests on auth_len in + cli_pipe_validate_rpc_response(). */ + if (*pdata_len < RPC_HDR_AUTH_LEN + prhdr->auth_len) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + *pdata_len -= (RPC_HDR_AUTH_LEN + prhdr->auth_len); + } + + DEBUG(10,("cli_pipe_validate_current_pdu: got pdu len %u, data_len %u, ss_len %u\n", + current_pdu_len, *pdata_len, ss_padding_len )); + + /* + * If this is the first reply, and the allocation hint is reasonably, try and + * set up the return_data parse_struct to the correct size. + */ + + if ((prs_data_size(return_data) == 0) && rhdr_resp.alloc_hint && (rhdr_resp.alloc_hint < 15*1024*1024)) { + if (!prs_set_buffer_size(return_data, rhdr_resp.alloc_hint)) { + DEBUG(0,("cli_pipe_validate_current_pdu: reply alloc hint %u " + "too large to allocate\n", + (unsigned int)rhdr_resp.alloc_hint )); + return NT_STATUS_NO_MEMORY; + } + } + + break; } - - if (!smb_io_rpc_auth_netsec_chk("schannel_auth_sign", auth_len, &chk, &auth_verf, 0)) + case RPC_BINDNACK: + DEBUG(1, ("cli_pipe_validate_current_pdu: Bind NACK received from remote machine %s " + "pipe %s fnum 0x%x!\n", + cli->cli->desthost, + cli->pipe_name, + (unsigned int)cli->fnum)); + /* Use this for now... */ + return NT_STATUS_NETWORK_ACCESS_DENIED; + + case RPC_FAULT: { - DEBUG(0, ("rpc_auth_pipe: schannel unmarshalling " - "RPC_AUTH_NETSECK_CHK failed\n")); - return False; - } + RPC_HDR_RESP rhdr_resp; + RPC_HDR_FAULT fault_resp; + + if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, current_pdu, 0)) { + DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_RESP.\n")); + return NT_STATUS_BUFFER_TOO_SMALL; + } + + if(!smb_io_rpc_hdr_fault("fault", &fault_resp, current_pdu, 0)) { + DEBUG(5,("cli_pipe_validate_current_pdu: failed to unmarshal RPC_HDR_FAULT.\n")); + return NT_STATUS_BUFFER_TOO_SMALL; + } - if (!netsec_decode(&cli->auth_info, - cli->pipe_auth_flags, - SENDER_IS_ACCEPTOR, - &chk, reply_data, data_len)) { - DEBUG(0, ("rpc_auth_pipe: Could not decode schannel\n")); - return False; + DEBUG(1, ("cli_pipe_validate_current_pdu: RPC fault code %s received from remote machine %s " + "pipe %s fnum 0x%x!\n", + nt_errstr(fault_resp.status), + cli->cli->desthost, + cli->pipe_name, + (unsigned int)cli->fnum)); + if (NT_STATUS_IS_OK(fault_resp.status)) { + return NT_STATUS_UNSUCCESSFUL; + } else { + return fault_resp.status; + } + } - cli->auth_info.seq_num++; + default: + DEBUG(0, ("cli_pipe_validate_current_pdu: unknown packet type %u received " + "from remote machine %s pipe %s fnum 0x%x!\n", + (unsigned int)prhdr->pkt_type, + cli->cli->desthost, + cli->pipe_name, + (unsigned int)cli->fnum)); + return NT_STATUS_INVALID_INFO_CLASS; + } + if (prhdr->pkt_type != expected_pkt_type) { + DEBUG(3, ("cli_pipe_validate_current_pdu: Connection to remote machine %s " + "pipe %s fnum %x got an unexpected RPC packet " + "type - %u, not %u\n", + cli->cli->desthost, + cli->pipe_name, + (unsigned int)cli->fnum, + prhdr->pkt_type, + expected_pkt_type)); + return NT_STATUS_INVALID_INFO_CLASS; } - return True; + + /* Do this just before return - we don't want to modify any rpc header + data before now as we may have needed to do cryptographic actions on + it before. */ + + if ((prhdr->pkt_type == RPC_BINDACK) && !(prhdr->flags & RPC_FLG_LAST)) { + DEBUG(5,("cli_pipe_validate_current_pdu: bug in server (AS/U?), " + "setting fragment first/last ON.\n")); + prhdr->flags |= RPC_FLG_FIRST|RPC_FLG_LAST; + } + + return NT_STATUS_OK; } +/**************************************************************************** + Ensure we eat the just processed pdu from the current_pdu prs_struct. + Normally the frag_len and buffer size will match, but on the first trans + reply there is a theoretical chance that buffer size > frag_len, so we must + deal with that. + ****************************************************************************/ + +static NTSTATUS cli_pipe_reset_current_pdu(struct rpc_pipe_client *cli, RPC_HDR *prhdr, prs_struct *current_pdu) +{ + uint32 current_pdu_len = prs_data_size(current_pdu); + + if (current_pdu_len < prhdr->frag_len) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + + /* Common case. */ + if (current_pdu_len == (uint32)prhdr->frag_len) { + prs_mem_free(current_pdu); + prs_init(current_pdu, 0, prs_get_mem_context(current_pdu), UNMARSHALL); + /* Make current_pdu dynamic with no memory. */ + prs_give_memory(current_pdu, 0, 0, True); + return NT_STATUS_OK; + } + + /* + * Oh no ! More data in buffer than we processed in current pdu. + * Cheat. Move the data down and shrink the buffer. + */ + + memcpy(prs_data_p(current_pdu), prs_data_p(current_pdu) + prhdr->frag_len, + current_pdu_len - prhdr->frag_len); + + /* Remember to set the read offset back to zero. */ + prs_set_offset(current_pdu, 0); + + /* Shrink the buffer. */ + if (!prs_set_buffer_size(current_pdu, current_pdu_len - prhdr->frag_len)) { + return NT_STATUS_BUFFER_TOO_SMALL; + } + + return NT_STATUS_OK; +} /**************************************************************************** - Send data on an rpc pipe via trans, which *must* be the last fragment. - receive response data from an rpc pipe, which may be large... + Send data on an rpc pipe via trans. The prs_struct data must be the last + pdu fragment of an NDR data stream. + + Receive response data from an rpc pipe, which may be large... Read the first fragment: unfortunately have to use SMBtrans for the first bit, then SMBreadX for subsequent bits. @@ -391,41 +730,50 @@ static BOOL rpc_auth_pipe(struct rpc_pipe_client *cli, prs_struct *rdata, | RPC HEADER | REQ/RESP HEADER | DATA ...... | AUTH_HDR | AUTH DATA | +------------+-----------------+-------------+---------------+-------------+ - Where the presence of the AUTH_HDR and AUTH are dependent on the + Where the presence of the AUTH_HDR and AUTH DATA are dependent on the signing & sealing being negotiated. ****************************************************************************/ -static BOOL rpc_api_pipe(struct rpc_pipe_client *cli, prs_struct *data, prs_struct *rdata, - uint8 expected_pkt_type) +static NTSTATUS rpc_api_pipe(struct rpc_pipe_client *cli, + prs_struct *data, /* Outgoing pdu fragment, already formatted for send. */ + prs_struct *rbuf, /* Incoming reply - return as an NDR stream. */ + uint8 expected_pkt_type) { - uint32 len; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; char *rparam = NULL; uint32 rparam_len = 0; uint16 setup[2]; - BOOL first = True; - BOOL last = True; - RPC_HDR rhdr; char *pdata = data ? prs_data_p(data) : NULL; uint32 data_len = data ? prs_offset(data) : 0; char *prdata = NULL; uint32 rdata_len = 0; - uint32 current_offset = 0; - uint32 fragment_start = 0; uint32 max_data = cli->max_xmit_frag ? cli->max_xmit_frag : 1024; - int auth_padding_len = 0; + uint32 current_rbuf_offset = 0; + prs_struct current_pdu; + +#ifdef DEVELOPER + /* Ensure we're not sending too much. */ + SMB_ASSERT(data_len <= max_data); +#endif - /* Create setup parameters - must be in native byte order. */ + /* Set up the current pdu parse struct. */ + prs_init(¤t_pdu, 0, prs_get_mem_context(rbuf), UNMARSHALL); + /* Create setup parameters - must be in native byte order. */ setup[0] = TRANSACT_DCERPCCMD; setup[1] = cli->fnum; /* Pipe file handle. */ - DEBUG(5,("rpc_api_pipe: fnum:%x\n", (int)cli->fnum)); + DEBUG(5,("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x\n", + cli->cli->desthost, + cli->pipe_name, + (unsigned int)cli->fnum )); - /* Send the RPC request and receive a response. For short RPC - calls (about 1024 bytes or so) the RPC request and response - appears in a SMBtrans request and response. Larger RPC - responses are received further on. */ + /* + * Send the last (or only) fragment of an RPC request. For small + * amounts of data (about 1024 bytes or so) the RPC request and response + * appears in a SMBtrans request and response. + */ if (!cli_api_pipe(cli->cli, "\\PIPE\\", setup, 2, 0, /* Setup, length, max */ @@ -434,9 +782,14 @@ static BOOL rpc_api_pipe(struct rpc_pipe_client *cli, prs_struct *data, prs_stru &rparam, &rparam_len, /* return params, len */ &prdata, &rdata_len)) /* return data, len */ { - DEBUG(0, ("cli_pipe: return critical error. Error was %s\n", - cli_errstr(cli->cli))); - return False; + DEBUG(0, ("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x" + "returned critical error. Error was %s\n", + cli->cli->desthost, + cli->pipe_name, + (unsigned int)cli->fnum, + cli_errstr(cli->cli))); + ret = cli_get_nt_error(cli->cli); + goto err; } /* Throw away returned params - we know we won't use them. */ @@ -444,327 +797,343 @@ static BOOL rpc_api_pipe(struct rpc_pipe_client *cli, prs_struct *data, prs_stru SAFE_FREE(rparam); if (prdata == NULL) { - DEBUG(0,("rpc_api_pipe: pipe %x failed to return data.\n", - (int)cli->fnum)); - return False; + DEBUG(3,("rpc_api_pipe: Remote machine %s pipe %s " + "fnum 0x%x failed to return data.\n", + cli->cli->desthost, + cli->pipe_name, + (unsigned int)cli->fnum)); + /* Yes - some calls can truely return no data... */ + prs_mem_free(¤t_pdu); + return NT_STATUS_OK; } /* - * Give this memory as dynamically allocated to the return parse - * struct. + * Give this memory as dynamic to the current pdu. */ - prs_give_memory(rdata, prdata, rdata_len, True); - current_offset = rdata_len; - - /* This next call sets the endian bit correctly in rdata. */ + prs_give_memory(¤t_pdu, prdata, rdata_len, True); - if (!rpc_check_hdr(rdata, &rhdr, &first, &last, &len)) { - prs_mem_free(rdata); - return False; - } + /* Ensure we can mess with the return prs_struct. */ + SMB_ASSERT(UNMARSHALLING(rbuf)); + SMB_ASSERT(prs_data_size(rbuf) == 0); - if (rhdr.pkt_type == RPC_BINDACK) { - if (!last && !first) { - DEBUG(5,("rpc_api_pipe: bug in server (AS/U?), setting fragment first/last ON.\n")); - first = True; - last = True; - } - } + /* Make rbuf dynamic with no memory. */ + prs_give_memory(rbuf, 0, 0, True); - if (rhdr.pkt_type == RPC_BINDNACK) { - DEBUG(3, ("Bind NACK received on pipe %x!\n", (int)cli->fnum)); - prs_mem_free(rdata); - return False; - } + while(1) { + RPC_HDR rhdr; + char *ret_data; + uint32 ret_data_len; - if (rhdr.pkt_type == RPC_RESPONSE) { - RPC_HDR_RESP rhdr_resp; - if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, rdata, 0)) { - DEBUG(5,("rpc_api_pipe: failed to unmarshal RPC_HDR_RESP.\n")); - prs_mem_free(rdata); - return False; + /* Ensure we have enough data for a pdu. */ + ret = cli_pipe_get_current_pdu(cli, &rhdr, ¤t_pdu); + if (!NT_STATUS_IS_OK(ret)) { + goto err; } - } - if (rhdr.pkt_type != expected_pkt_type) { - DEBUG(3, ("Connection to pipe %x got an unexpected RPC packet " - "type - %d, not %d\n", (int)cli->fnum, - rhdr.pkt_type, expected_pkt_type)); - prs_mem_free(rdata); - return False; - } + /* We pass in rbuf here so if the alloc hint is set correctly + we can set the output size and avoid reallocs. */ + + ret = cli_pipe_validate_current_pdu(cli, &rhdr, ¤t_pdu, expected_pkt_type, + &ret_data, &ret_data_len, rbuf); - DEBUG(5,("rpc_api_pipe: len left: %u smbtrans read: %u\n", - (unsigned int)len, (unsigned int)rdata_len )); + DEBUG(10,("rpc_api_pipe: got PDU len of %u at offset %u\n", + prs_data_size(¤t_pdu), current_rbuf_offset )); - /* check if data to be sent back was too large for one SMBtrans */ - /* err status is only informational: the _real_ check is on the - length */ + if (!NT_STATUS_IS_OK(ret)) { + goto err; + } - if (len > 0) { - /* || err == (0x80000000 | STATUS_BUFFER_OVERFLOW)) */ + if ((rhdr.flags & RPC_FLG_FIRST)) { + if (rhdr.pack_type[0] == 0) { + /* Set the data type correctly for big-endian data on the first packet. */ + DEBUG(10,("rpc_api_pipe: On machine %s pipe %s fnum 0x%x " + "PDU data format is big-endian.\n", + cli->cli->desthost, + cli->pipe_name, + (unsigned int)cli->fnum)); + + prs_set_endian_data(rbuf, RPC_BIG_ENDIAN); + } else { + /* Check endianness on subsequent packets. */ + if (current_pdu.bigendian_data != rbuf->bigendian_data) { + DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to %s\n", + rbuf->bigendian_data ? "big" : "little", + current_pdu.bigendian_data ? "big" : "little" )); + ret = NT_STATUS_INVALID_PARAMETER; + goto err; + } + } + } - /* Read the remaining part of the first response fragment */ + /* Now copy the data portion out of the pdu into rbuf. */ + if (!prs_force_grow(rbuf, ret_data_len)) { + ret = NT_STATUS_NO_MEMORY; + goto err; + } + memcpy(prs_data_p(rbuf)+current_rbuf_offset, ret_data, (size_t)ret_data_len); + current_rbuf_offset += ret_data_len; + + /* See if we've finished with all the data in current_pdu yet ? */ + ret = cli_pipe_reset_current_pdu(cli, &rhdr, ¤t_pdu); + if (!NT_STATUS_IS_OK(ret)) { + goto err; + } - if (!rpc_read(cli, rdata, len, ¤t_offset)) { - prs_mem_free(rdata); - return False; + if (rhdr.flags & RPC_FLG_LAST) { + break; /* We're done. */ } } - /* - * Now we have a complete PDU, check the auth struct if any was sent. - */ + DEBUG(10,("rpc_api_pipe: Remote machine %s pipe %s fnum 0x%x returned %u bytes.\n", + cli->cli->desthost, + cli->pipe_name, + (unsigned int)cli->fnum, + (unsigned int)prs_data_size(rbuf) )); - if(!rpc_auth_pipe(cli, rdata, fragment_start, rhdr.frag_len, - rhdr.auth_len, rhdr.pkt_type, &auth_padding_len)) { - prs_mem_free(rdata); - return False; - } + prs_mem_free(¤t_pdu); + return NT_STATUS_OK; - if (rhdr.auth_len != 0) { - /* - * Drop the auth footers from the current offset. - * We need this if there are more fragments. - * The auth footers consist of the auth_data and the - * preceeding 8 byte auth_header. - */ - current_offset -= (auth_padding_len + RPC_HDR_AUTH_LEN + rhdr.auth_len); - } - - /* - * Only one rpc fragment, and it has been read. - */ + err: - if (first && last) { - DEBUG(6,("rpc_api_pipe: fragment first and last both set\n")); - return True; - } + prs_mem_free(¤t_pdu); + prs_mem_free(rbuf); + return ret; +} - /* - * Read more fragments using SMBreadX until we get one with the - * last bit set. - */ +/******************************************************************* + Creates krb5 auth bind. + ********************************************************************/ - while (!last) { - RPC_HDR_RESP rhdr_resp; - int num_read; - char hdr_data[RPC_HEADER_LEN+RPC_HDR_RESP_LEN]; - prs_struct hps; - uint8 eclass; - uint32 ecode; - - /* - * First read the header of the next PDU. - */ +static NTSTATUS create_krb5_auth_bind_req( struct rpc_pipe_client *cli, + enum pipe_auth_level auth_level, + RPC_HDR_AUTH *pauth_out, + prs_struct *auth_data) +{ +#ifdef HAVE_KRB5 + int ret; + struct kerberos_auth_struct *a = cli->auth.a_u.kerberos_auth; + DATA_BLOB tkt = data_blob(NULL, 0); + DATA_BLOB tkt_wrapped = data_blob(NULL, 0); - prs_init(&hps, 0, cli->cli->mem_ctx, UNMARSHALL); - prs_give_memory(&hps, hdr_data, sizeof(hdr_data), False); + /* We may change the pad length before marshalling. */ + init_rpc_hdr_auth(pauth_out, RPC_KRB5_AUTH_TYPE, (int)auth_level, 0, 1); - num_read = cli_read(cli->cli, cli->fnum, hdr_data, 0, - RPC_HEADER_LEN+RPC_HDR_RESP_LEN); - if (cli_is_dos_error(cli->cli)) { - cli_dos_error(cli->cli, &eclass, &ecode); - if (eclass != ERRDOS && ecode != ERRmoredata) { - DEBUG(0,("rpc_api_pipe: cli_read error : %d/%d\n", eclass, ecode)); - return False; - } - } + DEBUG(5, ("create_krb5_auth_bind_req: creating a service ticket for principal %s\n", + a->service_principal )); - DEBUG(5,("rpc_api_pipe: read header (size:%d)\n", num_read)); + /* Create the ticket for the service principal and return it in a gss-api wrapped blob. */ - if (num_read != RPC_HEADER_LEN+RPC_HDR_RESP_LEN) { - DEBUG(0,("rpc_api_pipe: Error : requested %d bytes, got %d.\n", - RPC_HEADER_LEN+RPC_HDR_RESP_LEN, num_read )); - return False; - } + ret = cli_krb5_get_ticket(a->service_principal, 0, &tkt, + &a->session_key, (uint32)AP_OPTS_MUTUAL_REQUIRED); - /* This call sets the endianness in hps. */ + if (ret) { + DEBUG(1,("create_krb5_auth_bind_req: cli_krb5_get_ticket for principal %s " + "failed with %s\n", + a->service_principal, + error_message(ret) )); - if (!rpc_check_hdr(&hps, &rhdr, &first, &last, &len)) - return False; + data_blob_free(&tkt); + prs_mem_free(auth_data); + return NT_STATUS_INVALID_PARAMETER; + } - /* Ensure the endianness in rdata is set correctly - must be same as hps. */ + /* wrap that up in a nice GSS-API wrapping */ + tkt_wrapped = spnego_gen_krb5_wrap(tkt, TOK_ID_KRB_AP_REQ); - if (hps.bigendian_data != rdata->bigendian_data) { - DEBUG(0,("rpc_api_pipe: Error : Endianness changed from %s to %s\n", - rdata->bigendian_data ? "big" : "little", - hps.bigendian_data ? "big" : "little" )); - return False; - } + data_blob_free(&tkt); - if(!smb_io_rpc_hdr_resp("rpc_hdr_resp", &rhdr_resp, &hps, 0)) { - DEBUG(0,("rpc_api_pipe: Error in unmarshalling RPC_HDR_RESP.\n")); - return False; - } + /* Auth len in the rpc header doesn't include auth_header. */ + if (!prs_copy_data_in(auth_data, (char *)tkt_wrapped.data, tkt_wrapped.length)) { + data_blob_free(&tkt_wrapped); + prs_mem_free(auth_data); + return NT_STATUS_NO_MEMORY; + } - if (first) { - DEBUG(0,("rpc_api_pipe: secondary PDU rpc header has 'first' set !\n")); - return False; - } + DEBUG(5, ("create_krb5_auth_bind_req: Created krb5 GSS blob :\n")); + dump_data(5, (const char *)tkt_wrapped.data, tkt_wrapped.length); - /* - * Now read the rest of the PDU. - */ + data_blob_free(&tkt_wrapped); + return NT_STATUS_OK; +#else + return NT_STATUS_INVALID_PARAMETER; +#endif +} - if (!rpc_read(cli, rdata, len, ¤t_offset)) { - prs_mem_free(rdata); - return False; - } +/******************************************************************* + Creates SPNEGO NTLMSSP auth bind. + ********************************************************************/ + +static NTSTATUS create_spnego_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli, + enum pipe_auth_level auth_level, + RPC_HDR_AUTH *pauth_out, + prs_struct *auth_data) +{ + NTSTATUS nt_status; + DATA_BLOB null_blob = data_blob(NULL, 0); + DATA_BLOB request = data_blob(NULL, 0); + DATA_BLOB spnego_msg = data_blob(NULL, 0); - fragment_start = current_offset - len - RPC_HEADER_LEN - RPC_HDR_RESP_LEN; + /* We may change the pad length before marshalling. */ + init_rpc_hdr_auth(pauth_out, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1); - /* - * Verify any authentication footer. - */ + DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n")); + nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state, + null_blob, + &request); - - if(!rpc_auth_pipe(cli, rdata, fragment_start, rhdr.frag_len, - rhdr.auth_len, rhdr.pkt_type, &auth_padding_len)) { - prs_mem_free(rdata); - return False; - } - - if (rhdr.auth_len != 0 ) { - - /* - * Drop the auth footers from the current offset. - * The auth footers consist of the auth_data and the - * preceeding 8 byte auth_header. - * We need this if there are more fragments. - */ - current_offset -= (auth_padding_len + RPC_HDR_AUTH_LEN + rhdr.auth_len); - } + if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + data_blob_free(&request); + prs_mem_free(auth_data); + return nt_status; } - return True; -} + /* Wrap this in SPNEGO. */ + spnego_msg = gen_negTokenInit(OID_NTLMSSP, request); -/******************************************************************* - creates a DCE/RPC bind request + data_blob_free(&request); - - initialises the parse structure. - - dynamically allocates the header data structure - - caller is expected to free the header data structure once used. + /* Auth len in the rpc header doesn't include auth_header. */ + if (!prs_copy_data_in(auth_data, (char *)spnego_msg.data, spnego_msg.length)) { + data_blob_free(&spnego_msg); + prs_mem_free(auth_data); + return NT_STATUS_NO_MEMORY; + } - ********************************************************************/ + DEBUG(5, ("create_spnego_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n")); + dump_data(5, (const char *)spnego_msg.data, spnego_msg.length); -static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli, - prs_struct *rpc_out, - uint32 rpc_call_id, - RPC_IFACE *abstract, RPC_IFACE *transfer, - const char *my_name, const char *domain) + data_blob_free(&spnego_msg); + return NT_STATUS_OK; +} + +/******************************************************************* + Creates NTLMSSP auth bind. + ********************************************************************/ + +static NTSTATUS create_ntlmssp_auth_rpc_bind_req( struct rpc_pipe_client *cli, + enum pipe_auth_level auth_level, + RPC_HDR_AUTH *pauth_out, + prs_struct *auth_data) { - RPC_HDR hdr; - RPC_HDR_RB hdr_rb; - RPC_HDR_AUTH hdr_auth; - RPC_CONTEXT rpc_ctx; - int auth_len = 0; - int auth_type, auth_level; - size_t saved_hdr_offset = 0; + NTSTATUS nt_status; + DATA_BLOB null_blob = data_blob(NULL, 0); + DATA_BLOB request = data_blob(NULL, 0); - prs_struct auth_info; - prs_init(&auth_info, RPC_HDR_AUTH_LEN, /* we will need at least this much */ - prs_get_mem_context(rpc_out), MARSHALL); - - if (cli->pipe_auth_flags) { - get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level); - - /* - * Create the auth structs we will marshall. - */ - - init_rpc_hdr_auth(&hdr_auth, auth_type, auth_level, 0x00, 1); - - /* - * Now marshall the data into the temporary parse_struct. - */ - - if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, &auth_info, 0)) { - DEBUG(0,("create_rpc_bind_req: failed to marshall RPC_HDR_AUTH.\n")); - prs_mem_free(&auth_info); - return NT_STATUS_NO_MEMORY; - } - saved_hdr_offset = prs_offset(&auth_info); - } - - if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) { + /* We may change the pad length before marshalling. */ + init_rpc_hdr_auth(pauth_out, RPC_NTLMSSP_AUTH_TYPE, (int)auth_level, 0, 1); - NTSTATUS nt_status; - DATA_BLOB null_blob = data_blob(NULL, 0); - DATA_BLOB request; + DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: Processing NTLMSSP Negotiate\n")); + nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state, + null_blob, + &request); - DEBUG(5, ("Processing NTLMSSP Negotiate\n")); - nt_status = ntlmssp_update(cli->ntlmssp_pipe_state, - null_blob, - &request); + if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + data_blob_free(&request); + prs_mem_free(auth_data); + return nt_status; + } - if (!NT_STATUS_EQUAL(nt_status, - NT_STATUS_MORE_PROCESSING_REQUIRED)) { - prs_mem_free(&auth_info); - return nt_status; - } + /* Auth len in the rpc header doesn't include auth_header. */ + if (!prs_copy_data_in(auth_data, (char *)request.data, request.length)) { + data_blob_free(&request); + prs_mem_free(auth_data); + return NT_STATUS_NO_MEMORY; + } - /* Auth len in the rpc header doesn't include auth_header. */ - auth_len = request.length; - prs_copy_data_in(&auth_info, (char *)request.data, request.length); + DEBUG(5, ("create_ntlmssp_auth_rpc_bind_req: NTLMSSP Negotiate:\n")); + dump_data(5, (const char *)request.data, request.length); - DEBUG(5, ("NTLMSSP Negotiate:\n")); - dump_data(5, (const char *)request.data, request.length); + data_blob_free(&request); + return NT_STATUS_OK; +} - data_blob_free(&request); +/******************************************************************* + Creates schannel auth bind. + ********************************************************************/ - } else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) { - RPC_AUTH_NETSEC_NEG netsec_neg; +static NTSTATUS create_schannel_auth_rpc_bind_req( struct rpc_pipe_client *cli, + enum pipe_auth_level auth_level, + RPC_HDR_AUTH *pauth_out, + prs_struct *auth_data) +{ + RPC_AUTH_SCHANNEL_NEG schannel_neg; - /* Use lp_workgroup() if domain not specified */ + /* We may change the pad length before marshalling. */ + init_rpc_hdr_auth(pauth_out, RPC_SCHANNEL_AUTH_TYPE, (int)auth_level, 0, 1); - if (!domain || !domain[0]) { - DEBUG(10,("create_rpc_bind_req: no domain; assuming my own\n")); - domain = lp_workgroup(); - } + /* Use lp_workgroup() if domain not specified */ - init_rpc_auth_netsec_neg(&netsec_neg, domain, my_name); + if (!cli->domain || !cli->domain[0]) { + cli->domain = lp_workgroup(); + } - /* - * Now marshall the data into the temporary parse_struct. - */ + init_rpc_auth_schannel_neg(&schannel_neg, cli->domain, global_myname()); - if(!smb_io_rpc_auth_netsec_neg("netsec_neg", - &netsec_neg, &auth_info, 0)) { - DEBUG(0,("Failed to marshall RPC_AUTH_NETSEC_NEG.\n")); - prs_mem_free(&auth_info); - return NT_STATUS_NO_MEMORY; - } + /* + * Now marshall the data into the auth parse_struct. + */ - /* Auth len in the rpc header doesn't include auth_header. */ - auth_len = prs_offset(&auth_info) - saved_hdr_offset; + if(!smb_io_rpc_auth_schannel_neg("schannel_neg", + &schannel_neg, auth_data, 0)) { + DEBUG(0,("Failed to marshall RPC_AUTH_SCHANNEL_NEG.\n")); + prs_mem_free(auth_data); + return NT_STATUS_NO_MEMORY; } + return NT_STATUS_OK; +} + +/******************************************************************* + Creates the internals of a DCE/RPC bind request or alter context PDU. + ********************************************************************/ + +static NTSTATUS create_bind_or_alt_ctx_internal(uint8 pkt_type, + prs_struct *rpc_out, + uint32 rpc_call_id, + RPC_IFACE *abstract, + RPC_IFACE *transfer, + RPC_HDR_AUTH *phdr_auth, + prs_struct *pauth_info) +{ + RPC_HDR hdr; + RPC_HDR_RB hdr_rb; + RPC_CONTEXT rpc_ctx; + uint16 auth_len = prs_offset(pauth_info); + uint8 ss_padding_len = 0; + uint16 frag_len = 0; + /* create the RPC context. */ - init_rpc_context(&rpc_ctx, 0 /* context id */, - abstract, transfer); + init_rpc_context(&rpc_ctx, 0 /* context id */, abstract, transfer); /* create the bind request RPC_HDR_RB */ - init_rpc_hdr_rb(&hdr_rb, MAX_PDU_FRAG_LEN, MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx); + init_rpc_hdr_rb(&hdr_rb, RPC_MAX_PDU_FRAG_LEN, RPC_MAX_PDU_FRAG_LEN, 0x0, &rpc_ctx); + + /* Start building the frag length. */ + frag_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb); + + /* Do we need to pad ? */ + if (auth_len) { + uint16 data_len = RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb); + if (data_len % 8) { + ss_padding_len = 8 - (data_len % 8); + phdr_auth->auth_pad_len = ss_padding_len; + } + frag_len += RPC_HDR_AUTH_LEN + auth_len + ss_padding_len; + } /* Create the request RPC_HDR */ - init_rpc_hdr(&hdr, RPC_BIND, 0x3, rpc_call_id, - RPC_HEADER_LEN + RPC_HDR_RB_LEN(&hdr_rb) + prs_offset(&auth_info), - auth_len); + init_rpc_hdr(&hdr, pkt_type, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id, frag_len, auth_len); /* Marshall the RPC header */ if(!smb_io_rpc_hdr("hdr" , &hdr, rpc_out, 0)) { - DEBUG(0,("create_rpc_bind_req: failed to marshall RPC_HDR.\n")); - prs_mem_free(&auth_info); + DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR.\n")); return NT_STATUS_NO_MEMORY; } /* Marshall the bind request data */ if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_out, 0)) { - DEBUG(0,("create_rpc_bind_req: failed to marshall RPC_HDR_RB.\n")); - prs_mem_free(&auth_info); + DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_RB.\n")); return NT_STATUS_NO_MEMORY; } @@ -773,363 +1142,453 @@ static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli, */ if(auth_len != 0) { - if(!prs_append_prs_data( rpc_out, &auth_info)) { - DEBUG(0,("create_rpc_bind_req: failed to grow parse struct to add auth.\n")); - prs_mem_free(&auth_info); + if (ss_padding_len) { + unsigned char pad[8]; + memset(pad, '\0', 8); + if (!prs_copy_data_in(rpc_out, pad, ss_padding_len)) { + DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall padding.\n")); + return NT_STATUS_NO_MEMORY; + } + } + + if(!smb_io_rpc_hdr_auth("hdr_auth", phdr_auth, rpc_out, 0)) { + DEBUG(0,("create_bind_or_alt_ctx_internal: failed to marshall RPC_HDR_AUTH.\n")); + return NT_STATUS_NO_MEMORY; + } + + + if(!prs_append_prs_data( rpc_out, pauth_info)) { + DEBUG(0,("create_bind_or_alt_ctx_internal: failed to grow parse struct to add auth.\n")); return NT_STATUS_NO_MEMORY; } } - prs_mem_free(&auth_info); + return NT_STATUS_OK; } /******************************************************************* - Creates a DCE/RPC bind authentication response. - This is the packet that is sent back to the server once we - have received a BIND-ACK, to finish the third leg of - the authentication handshake. + Creates a DCE/RPC bind request. ********************************************************************/ -static NTSTATUS create_rpc_bind_resp(struct rpc_pipe_client *cli, - uint32 rpc_call_id, - prs_struct *rpc_out) +static NTSTATUS create_rpc_bind_req(struct rpc_pipe_client *cli, + prs_struct *rpc_out, + uint32 rpc_call_id, + RPC_IFACE *abstract, RPC_IFACE *transfer, + enum pipe_auth_type auth_type, + enum pipe_auth_level auth_level) { - NTSTATUS nt_status; - RPC_HDR hdr; RPC_HDR_AUTH hdr_auth; - RPC_HDR_AUTHA hdr_autha; - DATA_BLOB ntlmssp_null_response = data_blob(NULL, 0); - DATA_BLOB ntlmssp_reply; - int auth_type, auth_level; - - /* The response is picked up from the internal cache, - where it was placed by the rpc_auth_pipe() code */ - nt_status = ntlmssp_update(cli->ntlmssp_pipe_state, - ntlmssp_null_response, - &ntlmssp_reply); - - if (!NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - return nt_status; - } + prs_struct auth_info; + NTSTATUS ret = NT_STATUS_OK; - /* Create the request RPC_HDR */ - init_rpc_hdr(&hdr, RPC_BINDRESP, 0x0, rpc_call_id, - RPC_HEADER_LEN + RPC_HDR_AUTHA_LEN + ntlmssp_reply.length, - ntlmssp_reply.length ); - - /* Marshall it. */ - if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) { - DEBUG(0,("create_rpc_bind_resp: failed to marshall RPC_HDR.\n")); - data_blob_free(&ntlmssp_reply); - return NT_STATUS_NO_MEMORY; - } + ZERO_STRUCT(hdr_auth); + prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL); - get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level); - - /* Create the request RPC_HDR_AUTHA */ - init_rpc_hdr_auth(&hdr_auth, auth_type, auth_level, 0, 0x0014a0c0); - init_rpc_hdr_autha(&hdr_autha, MAX_PDU_FRAG_LEN, MAX_PDU_FRAG_LEN, &hdr_auth); + switch (auth_type) { + case PIPE_AUTH_TYPE_SCHANNEL: + ret = create_schannel_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info); + if (!NT_STATUS_IS_OK(ret)) { + prs_mem_free(&auth_info); + return ret; + } + break; - if(!smb_io_rpc_hdr_autha("hdr_autha", &hdr_autha, rpc_out, 0)) { - DEBUG(0,("create_rpc_bind_resp: failed to marshall RPC_HDR_AUTHA.\n")); - data_blob_free(&ntlmssp_reply); - return NT_STATUS_NO_MEMORY; - } + case PIPE_AUTH_TYPE_NTLMSSP: + ret = create_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info); + if (!NT_STATUS_IS_OK(ret)) { + prs_mem_free(&auth_info); + return ret; + } + break; - /* - * Append the auth data to the outgoing buffer. - */ + case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: + ret = create_spnego_ntlmssp_auth_rpc_bind_req(cli, auth_level, &hdr_auth, &auth_info); + if (!NT_STATUS_IS_OK(ret)) { + prs_mem_free(&auth_info); + return ret; + } + break; - if(!prs_copy_data_in(rpc_out, (char *)ntlmssp_reply.data, ntlmssp_reply.length)) { - DEBUG(0,("create_rpc_bind_req: failed to grow parse struct to add auth.\n")); - data_blob_free(&ntlmssp_reply); - return NT_STATUS_NO_MEMORY; + case PIPE_AUTH_TYPE_KRB5: + ret = create_krb5_auth_bind_req(cli, auth_level, &hdr_auth, &auth_info); + if (!NT_STATUS_IS_OK(ret)) { + prs_mem_free(&auth_info); + return ret; + } + break; + + case PIPE_AUTH_TYPE_NONE: + break; + + default: + /* "Can't" happen. */ + return NT_STATUS_INVALID_INFO_CLASS; } - data_blob_free(&ntlmssp_reply); - return NT_STATUS_OK; -} + ret = create_bind_or_alt_ctx_internal(RPC_BIND, + rpc_out, + rpc_call_id, + abstract, + transfer, + &hdr_auth, + &auth_info); + prs_mem_free(&auth_info); + return ret; +} /******************************************************************* - Creates a DCE/RPC request. + Create and add the NTLMSSP sign/seal auth header and data. ********************************************************************/ -static uint32 create_rpc_request(prs_struct *rpc_out, uint8 op_num, int data_len, int auth_len, uint8 flags, uint32 oldid, uint32 data_left) +static NTSTATUS add_ntlmssp_auth_footer(struct rpc_pipe_client *cli, + RPC_HDR *phdr, + uint32 ss_padding_len, + prs_struct *outgoing_pdu) { - uint32 alloc_hint; - RPC_HDR hdr; - RPC_HDR_REQ hdr_req; - uint32 callid = oldid ? oldid : get_rpc_call_id(); + RPC_HDR_AUTH auth_info; + NTSTATUS status; + DATA_BLOB auth_blob = data_blob(NULL, 0); + uint16 data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN; - DEBUG(5,("create_rpc_request: opnum: 0x%x data_len: 0x%x\n", op_num, data_len)); + if (!cli->auth.a_u.ntlmssp_state) { + return NT_STATUS_INVALID_PARAMETER; + } - /* create the rpc header RPC_HDR */ - init_rpc_hdr(&hdr, RPC_REQUEST, flags, - callid, data_len, auth_len); + /* Init and marshall the auth header. */ + init_rpc_hdr_auth(&auth_info, + map_pipe_auth_type_to_rpc_auth_type(cli->auth.auth_type), + cli->auth.auth_level, + ss_padding_len, + 1 /* context id. */); - /* - * The alloc hint should be the amount of data, not including - * RPC headers & footers. - */ + if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) { + DEBUG(0,("add_ntlmssp_auth_footer: failed to marshall RPC_HDR_AUTH.\n")); + data_blob_free(&auth_blob); + return NT_STATUS_NO_MEMORY; + } + + switch (cli->auth.auth_level) { + case PIPE_AUTH_LEVEL_PRIVACY: + /* Data portion is encrypted. */ + status = ntlmssp_seal_packet(cli->auth.a_u.ntlmssp_state, + prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN, + data_and_pad_len, + prs_data_p(outgoing_pdu), + (size_t)prs_offset(outgoing_pdu), + &auth_blob); + if (!NT_STATUS_IS_OK(status)) { + data_blob_free(&auth_blob); + return status; + } + break; + + case PIPE_AUTH_LEVEL_INTEGRITY: + /* Data is signed. */ + status = ntlmssp_sign_packet(cli->auth.a_u.ntlmssp_state, + prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN, + data_and_pad_len, + prs_data_p(outgoing_pdu), + (size_t)prs_offset(outgoing_pdu), + &auth_blob); + if (!NT_STATUS_IS_OK(status)) { + data_blob_free(&auth_blob); + return status; + } + break; + + default: + /* Can't happen. */ + smb_panic("bad auth level"); + /* Notreached. */ + return NT_STATUS_INVALID_PARAMETER; + } - if (auth_len != 0) - alloc_hint = data_len - RPC_HEADER_LEN - RPC_HDR_AUTH_LEN - auth_len; - else - alloc_hint = data_len - RPC_HEADER_LEN; + /* Finally marshall the blob. */ + + if (!prs_copy_data_in(outgoing_pdu, auth_blob.data, NTLMSSP_SIG_SIZE)) { + DEBUG(0,("add_ntlmssp_auth_footer: failed to add %u bytes auth blob.\n", + (unsigned int)NTLMSSP_SIG_SIZE)); + data_blob_free(&auth_blob); + return NT_STATUS_NO_MEMORY; + } + + data_blob_free(&auth_blob); + return NT_STATUS_OK; +} - DEBUG(10,("create_rpc_request: data_len: %x auth_len: %x alloc_hint: %x\n", - data_len, auth_len, alloc_hint)); +/******************************************************************* + Create and add the schannel sign/seal auth header and data. + ********************************************************************/ - /* Create the rpc request RPC_HDR_REQ */ - init_rpc_hdr_req(&hdr_req, alloc_hint, op_num); +static NTSTATUS add_schannel_auth_footer(struct rpc_pipe_client *cli, + RPC_HDR *phdr, + uint32 ss_padding_len, + prs_struct *outgoing_pdu) +{ + RPC_HDR_AUTH auth_info; + RPC_AUTH_SCHANNEL_CHK verf; + struct schannel_auth_struct *sas = cli->auth.a_u.schannel_auth; + char *data_p = prs_data_p(outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN; + size_t data_and_pad_len = prs_offset(outgoing_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN; + + if (!sas) { + return NT_STATUS_INVALID_PARAMETER; + } - /* stream-time... */ - if(!smb_io_rpc_hdr("hdr ", &hdr, rpc_out, 0)) - return 0; + /* Init and marshall the auth header. */ + init_rpc_hdr_auth(&auth_info, + map_pipe_auth_type_to_rpc_auth_type(cli->auth.auth_type), + cli->auth.auth_level, + ss_padding_len, + 1 /* context id. */); - if(!smb_io_rpc_hdr_req("hdr_req", &hdr_req, rpc_out, 0)) - return 0; + if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, outgoing_pdu, 0)) { + DEBUG(0,("add_schannel_auth_footer: failed to marshall RPC_HDR_AUTH.\n")); + return NT_STATUS_NO_MEMORY; + } - if (prs_offset(rpc_out) != RPC_HEADER_LEN + RPC_HDR_REQ_LEN) - return 0; + switch (cli->auth.auth_level) { + case PIPE_AUTH_LEVEL_PRIVACY: + case PIPE_AUTH_LEVEL_INTEGRITY: + DEBUG(10,("add_schannel_auth_footer: SCHANNEL seq_num=%d\n", + sas->seq_num)); + + schannel_encode(sas, + cli->auth.auth_level, + SENDER_IS_INITIATOR, + &verf, + data_p, + data_and_pad_len); + + sas->seq_num++; + break; + + default: + /* Can't happen. */ + smb_panic("bad auth level"); + /* Notreached. */ + return NT_STATUS_INVALID_PARAMETER; + } - return callid; + /* Finally marshall the blob. */ + smb_io_rpc_auth_schannel_chk("", + RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN, + &verf, + outgoing_pdu, + 0); + + return NT_STATUS_OK; } /******************************************************************* - Puts an auth header into an rpc request. + Calculate how much data we're going to send in this packet, also + work out any sign/seal padding length. ********************************************************************/ -static BOOL create_auth_hdr(prs_struct *outgoing_packet, - int auth_type, - int auth_level, int padding) +static uint32 calculate_data_len_tosend(struct rpc_pipe_client *cli, + uint32 data_left, + uint16 *p_frag_len, + uint16 *p_auth_len, + uint32 *p_ss_padding) { - RPC_HDR_AUTH hdr_auth; + uint32 data_space, data_len; + + switch (cli->auth.auth_level) { + case PIPE_AUTH_LEVEL_NONE: + case PIPE_AUTH_LEVEL_CONNECT: + data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN; + data_len = MIN(data_space, data_left); + *p_ss_padding = 0; + *p_auth_len = 0; + *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + data_len; + return data_len; + + case PIPE_AUTH_LEVEL_INTEGRITY: + case PIPE_AUTH_LEVEL_PRIVACY: + /* Treat the same for all authenticated rpc requests. */ + switch(cli->auth.auth_type) { + case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: + case PIPE_AUTH_TYPE_NTLMSSP: + *p_auth_len = NTLMSSP_SIG_SIZE; + break; + case PIPE_AUTH_TYPE_SCHANNEL: + *p_auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN; + break; + default: + smb_panic("bad auth type"); + break; + } - init_rpc_hdr_auth(&hdr_auth, auth_type, auth_level, - padding, 1); - if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, - outgoing_packet, 0)) { - DEBUG(0,("create_auth_hdr:Failed to marshal RPC_HDR_AUTH.\n")); - return False; + data_space = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN - + RPC_HDR_AUTH_LEN - *p_auth_len; + + data_len = MIN(data_space, data_left); + if (data_len % 8) { + *p_ss_padding = 8 - (data_len % 8); + } + *p_frag_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + /* Normal headers. */ + data_len + *p_ss_padding + /* data plus padding. */ + RPC_HDR_AUTH_LEN + *p_auth_len; /* Auth header and auth data. */ + return data_len; + + default: + smb_panic("bad auth level"); + /* Notreached. */ + return 0; } - return True; } -/** - * Send a request on an RPC pipe and get a response. - * - * @param data NDR contents of the request to be sent. - * @param rdata Unparsed NDR response data. -**/ +/******************************************************************* + External interface. + Does an rpc request on a pipe. Incoming data is NDR encoded in in_data. + Reply is NDR encoded in out_data. Splits the data stream into RPC PDU's + and deals with signing/sealing details. + ********************************************************************/ -BOOL rpc_api_pipe_req_int(struct rpc_pipe_client *cli, uint8 op_num, - prs_struct *data, prs_struct *rdata) +NTSTATUS rpc_api_pipe_req(struct rpc_pipe_client *cli, + uint8 op_num, + prs_struct *in_data, + prs_struct *out_data) { - uint32 auth_len, real_auth_len, auth_hdr_len, max_data, data_left, data_sent; - NTSTATUS nt_status; - BOOL ret = False; - uint32 callid = 0; - fstring dump_name; - - auth_len = 0; - real_auth_len = 0; - auth_hdr_len = 0; + NTSTATUS ret; + uint32 data_left = prs_offset(in_data); + uint32 alloc_hint = prs_offset(in_data); + uint32 data_sent_thistime = 0; + uint32 current_data_offset = 0; + uint32 call_id = get_rpc_call_id(); + char pad[8]; + prs_struct outgoing_pdu; + + memset(pad, '\0', 8); + + if (cli->max_xmit_frag < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_MAX_SIGN_SIZE) { + /* Server is screwed up ! */ + return NT_STATUS_INVALID_PARAMETER; + } - if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) { - if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) { - auth_len = RPC_AUTH_NTLMSSP_CHK_LEN; - } - if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) { - auth_len = RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN; - } - auth_hdr_len = RPC_HDR_AUTH_LEN; + if (data_left == 0) { + /* Caller is screwed up ! */ + return NT_STATUS_INVALID_PARAMETER; } - /* - * calc how much actual data we can send in a PDU fragment - */ - max_data = cli->max_xmit_frag - RPC_HEADER_LEN - RPC_HDR_REQ_LEN - - auth_hdr_len - auth_len - 8; - - for (data_left = prs_offset(data), data_sent = 0; data_left > 0;) { - prs_struct outgoing_packet; - prs_struct sec_blob; - uint32 data_len, send_size; + prs_init(&outgoing_pdu, cli->max_xmit_frag, prs_get_mem_context(in_data), MARSHALL); + + while (1) { + RPC_HDR hdr; + RPC_HDR_REQ hdr_req; + uint16 auth_len = 0; + uint16 frag_len = 0; uint8 flags = 0; - uint32 auth_padding = 0; - DATA_BLOB sign_blob; + uint32 ss_padding = 0; - /* - * how much will we send this time - */ - send_size = MIN(data_left, max_data); + data_sent_thistime = calculate_data_len_tosend(cli, data_left, + &frag_len, &auth_len, &ss_padding); - if (!prs_init(&sec_blob, send_size, /* will need at least this much */ - cli->cli->mem_ctx, MARSHALL)) { - DEBUG(0,("Could not malloc %u bytes", - send_size+auth_padding)); - return False; + if (current_data_offset == 0) { + flags = RPC_FLG_FIRST; } - if(!prs_append_some_prs_data(&sec_blob, data, - data_sent, send_size)) { - DEBUG(0,("Failed to append data to netsec blob\n")); - prs_mem_free(&sec_blob); - return False; + if (data_sent_thistime == data_left) { + flags |= RPC_FLG_LAST; } - /* - * NT expects the data that is sealed to be 8-byte - * aligned. The padding must be encrypted as well and - * taken into account when generating the - * authentication verifier. The amount of padding must - * be stored in the auth header. - */ + /* Create and marshall the header and request header. */ + init_rpc_hdr(&hdr, RPC_REQUEST, flags, call_id, frag_len, auth_len); - if (cli->pipe_auth_flags) { - size_t data_and_padding_size; - int auth_type; - int auth_level; - prs_align_uint64(&sec_blob); + if(!smb_io_rpc_hdr("hdr ", &hdr, &outgoing_pdu, 0)) { + prs_mem_free(&outgoing_pdu); + return NT_STATUS_NO_MEMORY; + } - get_auth_type_level(cli->pipe_auth_flags, &auth_type, &auth_level); + /* Create the rpc request RPC_HDR_REQ */ + init_rpc_hdr_req(&hdr_req, alloc_hint, op_num); + + if(!smb_io_rpc_hdr_req("hdr_req", &hdr_req, &outgoing_pdu, 0)) { + prs_mem_free(&outgoing_pdu); + return NT_STATUS_NO_MEMORY; + } - data_and_padding_size = prs_offset(&sec_blob); - auth_padding = data_and_padding_size - send_size; + /* Copy in the data, plus any ss padding. */ + if (!prs_append_some_prs_data(&outgoing_pdu, in_data, current_data_offset, data_sent_thistime)) { + prs_mem_free(&outgoing_pdu); + return NT_STATUS_NO_MEMORY; + } - /* insert the auth header */ - - if(!create_auth_hdr(&sec_blob, auth_type, auth_level, auth_padding)) { - prs_mem_free(&sec_blob); - return False; + /* Copy the sign/seal padding data. */ + if (ss_padding) { + if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding)) { + prs_mem_free(&outgoing_pdu); + return NT_STATUS_NO_MEMORY; } - - /* create an NTLMSSP signature */ - if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) { - /* - * Seal the outgoing data if requested. - */ - if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) { - - nt_status = ntlmssp_seal_packet(cli->ntlmssp_pipe_state, - (unsigned char*)prs_data_p(&sec_blob), - data_and_padding_size, - &sign_blob); - if (!NT_STATUS_IS_OK(nt_status)) { - prs_mem_free(&sec_blob); - return False; + } + + /* Generate any auth sign/seal and add the auth footer. */ + if (auth_len) { + switch (cli->auth.auth_type) { + case PIPE_AUTH_TYPE_NONE: + break; + case PIPE_AUTH_TYPE_NTLMSSP: + case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: + ret = add_ntlmssp_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu); + if (!NT_STATUS_IS_OK(ret)) { + prs_mem_free(&outgoing_pdu); + return ret; } - } - else if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) { - - nt_status = ntlmssp_sign_packet(cli->ntlmssp_pipe_state, - (unsigned char*)prs_data_p(&sec_blob), - data_and_padding_size, &sign_blob); - if (!NT_STATUS_IS_OK(nt_status)) { - prs_mem_free(&sec_blob); - return False; + break; + case PIPE_AUTH_TYPE_SCHANNEL: + ret = add_schannel_auth_footer(cli, &hdr, ss_padding, &outgoing_pdu); + if (!NT_STATUS_IS_OK(ret)) { + prs_mem_free(&outgoing_pdu); + return ret; } - } - - - /* write auth footer onto the packet */ - real_auth_len = sign_blob.length; - - prs_copy_data_in(&sec_blob, (char *)sign_blob.data, sign_blob.length); - data_blob_free(&sign_blob); - - } - else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) { - size_t parse_offset_marker; - RPC_AUTH_NETSEC_CHK verf; - DEBUG(10,("SCHANNEL seq_num=%d\n", cli->auth_info.seq_num)); - - netsec_encode(&cli->auth_info, - cli->pipe_auth_flags, - SENDER_IS_INITIATOR, - &verf, - prs_data_p(&sec_blob), - data_and_padding_size); - - cli->auth_info.seq_num++; - - /* write auth footer onto the packet */ - - parse_offset_marker = prs_offset(&sec_blob); - if (!smb_io_rpc_auth_netsec_chk("", RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN, - &verf, &sec_blob, 0)) - { - prs_mem_free(&sec_blob); - return False; - } - real_auth_len = prs_offset(&sec_blob) - parse_offset_marker; + break; + default: + smb_panic("bad auth type"); + break; /* notreached */ } } - data_len = RPC_HEADER_LEN + RPC_HDR_REQ_LEN + prs_offset(&sec_blob); + /* Actually send the packet. */ + if (flags & RPC_FLG_LAST) { + /* Last packet - send the data, get the reply and return. */ + ret = rpc_api_pipe(cli, &outgoing_pdu, out_data, RPC_RESPONSE); + prs_mem_free(&outgoing_pdu); - /* - * Malloc parse struct to hold it (and enough for alignments). - */ - if(!prs_init(&outgoing_packet, data_len + 8, - cli->cli->mem_ctx, MARSHALL)) { - DEBUG(0,("rpc_api_pipe_req: Failed to malloc %u bytes.\n", (unsigned int)data_len )); - return False; - } - - if (data_left == prs_offset(data)) - flags |= RPC_FLG_FIRST; + + if (DEBUGLEVEL >= 50) { + pstring dump_name; + /* Also capture received data */ + slprintf(dump_name, sizeof(dump_name) - 1, "%s/reply_%s_%d", + dyn_LOGFILEBASE, cli->pipe_name, op_num); + prs_dump(dump_name, op_num, out_data); + } - if (data_left <= max_data) - flags |= RPC_FLG_LAST; - /* - * Write out the RPC header and the request header. - */ - if(!(callid = create_rpc_request(&outgoing_packet, op_num, - data_len, real_auth_len, flags, - callid, data_left))) { - DEBUG(0,("rpc_api_pipe_req: Failed to create RPC request.\n")); - prs_mem_free(&outgoing_packet); - prs_mem_free(&sec_blob); - return False; + return ret; + } else { + /* More packets to come - write and continue. */ + ssize_t num_written = cli_write(cli->cli, cli->fnum, 8, /* 8 means message mode. */ + prs_data_p(&outgoing_pdu), + (off_t)0, + (size_t)hdr.frag_len); + + if (num_written != hdr.frag_len) { + prs_mem_free(&outgoing_pdu); + return cli_get_nt_error(cli->cli); + } } - prs_append_prs_data(&outgoing_packet, &sec_blob); - prs_mem_free(&sec_blob); - - DEBUG(100,("data_len: %x data_calc_len: %x\n", data_len, - prs_offset(&outgoing_packet))); - - if (flags & RPC_FLG_LAST) - ret = rpc_api_pipe(cli, &outgoing_packet, - rdata, RPC_RESPONSE); - else { - cli_write(cli->cli, cli->fnum, 0x0008, - prs_data_p(&outgoing_packet), - data_sent, data_len); + current_data_offset += data_sent_thistime; + data_left -= data_sent_thistime; + + /* Reset the marshalling position back to zero. */ + if (!prs_set_offset(&outgoing_pdu, 0)) { + prs_mem_free(&outgoing_pdu); + return NT_STATUS_NO_MEMORY; } - prs_mem_free(&outgoing_packet); - data_sent += send_size; - data_left -= send_size; } - /* Also capture received data */ - slprintf(dump_name, sizeof(dump_name) - 1, "reply_%s", - cli_pipe_get_name(cli->cli)); - prs_dump(dump_name, op_num, rdata); - - return ret; -} - -BOOL rpc_api_pipe_req(struct cli_state *cli, int pipe_idx, uint8 op_num, - prs_struct *data, prs_struct *rdata) -{ - return rpc_api_pipe_req_int(&cli->pipes[pipe_idx], op_num, - data, rdata); } - - +#if 0 /**************************************************************************** Set the handle state. ****************************************************************************/ @@ -1174,56 +1633,10 @@ static BOOL rpc_pipe_set_hnd_state(struct rpc_pipe_client *cli, return state_set; } +#endif /**************************************************************************** - check the rpc bind acknowledge response -****************************************************************************/ - -int get_pipe_index( const char *pipe_name ) -{ - int pipe_idx = 0; - - while (pipe_names[pipe_idx].client_pipe != NULL) { - if (strequal(pipe_name, pipe_names[pipe_idx].client_pipe )) - return pipe_idx; - pipe_idx++; - }; - - return -1; -} - - -/**************************************************************************** - check the rpc bind acknowledge response -****************************************************************************/ - -const char* get_pipe_name_from_index( const int pipe_index ) -{ - - if ( (pipe_index < 0) || (pipe_index >= PI_MAX_PIPES) ) - return NULL; - - return pipe_names[pipe_index].client_pipe; -} - -/**************************************************************************** - Check to see if this pipe index points to one of - the pipes only supported by Win2k - ****************************************************************************/ - -BOOL is_win2k_pipe( const int pipe_idx ) -{ - switch ( pipe_idx ) - { - case PI_LSARPC_DS: - return True; - } - - return False; -} - -/**************************************************************************** - check the rpc bind acknowledge response + Check the rpc bind acknowledge response. ****************************************************************************/ static BOOL valid_pipe_name(const int pipe_idx, RPC_IFACE *abstract, RPC_IFACE *transfer) @@ -1235,10 +1648,10 @@ static BOOL valid_pipe_name(const int pipe_idx, RPC_IFACE *abstract, RPC_IFACE * } DEBUG(5,("Bind Abstract Syntax: ")); - dump_data(5, (char*)&(pipe_names[pipe_idx].abstr_syntax), + dump_data(5, (char*)&pipe_names[pipe_idx].abstr_syntax, sizeof(pipe_names[pipe_idx].abstr_syntax)); DEBUG(5,("Bind Transfer Syntax: ")); - dump_data(5, (char*)&(pipe_names[pipe_idx].trans_syntax), + dump_data(5, (char*)&pipe_names[pipe_idx].trans_syntax, sizeof(pipe_names[pipe_idx].trans_syntax)); /* copy the required syntaxes out so we can do the right bind */ @@ -1250,7 +1663,7 @@ static BOOL valid_pipe_name(const int pipe_idx, RPC_IFACE *abstract, RPC_IFACE * } /**************************************************************************** - check the rpc bind acknowledge response + Check the rpc bind acknowledge response. ****************************************************************************/ static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, const int pipe_idx, RPC_IFACE *transfer) @@ -1259,7 +1672,6 @@ static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, const int pipe_idx, RPC_IFAC DEBUG(4,("Ignoring length check -- ASU bug (server didn't fill in the pipe name correctly)")); } - # if 0 /* JERRY -- apparently ASU forgets to fill in the server pipe name sometimes */ if ( !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].client_pipe) && !strequal(hdr_ba->addr.str, pipe_names[pipe_idx].server_pipe) ) @@ -1284,396 +1696,500 @@ static BOOL check_bind_response(RPC_HDR_BA *hdr_ba, const int pipe_idx, RPC_IFAC return False; } - /* lkclXXXX only accept one result: check the result(s) */ if (hdr_ba->res.num_results != 0x1 || hdr_ba->res.result != 0) { DEBUG(2,("bind_rpc_pipe: bind denied results: %d reason: %x\n", hdr_ba->res.num_results, hdr_ba->res.reason)); } - DEBUG(5,("bind_rpc_pipe: accepted!\n")); + DEBUG(5,("check_bind_response: accepted!\n")); return True; } -/**************************************************************************** - Create and send the third packet in an RPC auth. -****************************************************************************/ +/******************************************************************* + Creates a DCE/RPC bind authentication response. + This is the packet that is sent back to the server once we + have received a BIND-ACK, to finish the third leg of + the authentication handshake. + ********************************************************************/ -static BOOL rpc_send_auth_reply(struct rpc_pipe_client *cli, - prs_struct *rdata, uint32 rpc_call_id) +static NTSTATUS create_rpc_bind_auth3(struct rpc_pipe_client *cli, + uint32 rpc_call_id, + enum pipe_auth_type auth_type, + enum pipe_auth_level auth_level, + DATA_BLOB *pauth_blob, + prs_struct *rpc_out) { - prs_struct rpc_out; - ssize_t ret; + RPC_HDR hdr; + RPC_HDR_AUTH hdr_auth; + uint32 pad = 0; + + /* Create the request RPC_HDR */ + init_rpc_hdr(&hdr, RPC_AUTH3, RPC_FLG_FIRST|RPC_FLG_LAST, rpc_call_id, + RPC_HEADER_LEN + 4 /* pad */ + RPC_HDR_AUTH_LEN + pauth_blob->length, + pauth_blob->length ); + + /* Marshall it. */ + if(!smb_io_rpc_hdr("hdr", &hdr, rpc_out, 0)) { + DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR.\n")); + return NT_STATUS_NO_MEMORY; + } - prs_init(&rpc_out, RPC_HEADER_LEN + RPC_HDR_AUTHA_LEN, /* need at least this much */ - cli->cli->mem_ctx, MARSHALL); + /* + I'm puzzled about this - seems to violate the DCE RPC auth rules, + about padding - shouldn't this pad to length 8 ? JRA. + */ - if (!NT_STATUS_IS_OK(create_rpc_bind_resp(cli, rpc_call_id, - &rpc_out))) { - return False; + /* 4 bytes padding. */ + if (!prs_uint32("pad", rpc_out, 0, &pad)) { + DEBUG(0,("create_rpc_bind_auth3: failed to marshall 4 byte pad.\n")); + return NT_STATUS_NO_MEMORY; } - if ((ret = cli_write(cli->cli, cli->fnum, 0x8, prs_data_p(&rpc_out), - 0, (size_t)prs_offset(&rpc_out))) != (ssize_t)prs_offset(&rpc_out)) { - DEBUG(0,("rpc_send_auth_reply: cli_write failed. Return was %d\n", (int)ret)); - prs_mem_free(&rpc_out); - return False; + /* Create the request RPC_HDR_AUTHA */ + init_rpc_hdr_auth(&hdr_auth, + map_pipe_auth_type_to_rpc_auth_type(auth_type), + auth_level, 0, 1); + + if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rpc_out, 0)) { + DEBUG(0,("create_rpc_bind_auth3: failed to marshall RPC_HDR_AUTHA.\n")); + return NT_STATUS_NO_MEMORY; } - prs_mem_free(&rpc_out); - return True; + /* + * Append the auth data to the outgoing buffer. + */ + + if(!prs_copy_data_in(rpc_out, (char *)pauth_blob->data, pauth_blob->length)) { + DEBUG(0,("create_rpc_bind_auth3: failed to marshall auth blob.\n")); + return NT_STATUS_NO_MEMORY; + } + + return NT_STATUS_OK; } /**************************************************************************** - Do an rpc bind. + Create and send the third packet in an RPC auth. ****************************************************************************/ -static BOOL rpc_pipe_bind(struct rpc_pipe_client *cli) +static NTSTATUS rpc_finish_auth3_bind(struct rpc_pipe_client *cli, + RPC_HDR *phdr, + prs_struct *rbuf, + uint32 rpc_call_id, + enum pipe_auth_type auth_type, + enum pipe_auth_level auth_level) { - RPC_IFACE abstract; - RPC_IFACE transfer; + DATA_BLOB server_response = data_blob(NULL,0); + DATA_BLOB client_reply = data_blob(NULL,0); + RPC_HDR_AUTH hdr_auth; + NTSTATUS nt_status; prs_struct rpc_out; - prs_struct rdata; - uint32 rpc_call_id; - char buffer[MAX_PDU_FRAG_LEN]; + ssize_t ret; - if ( (cli->pipe_idx < 0) || (cli->pipe_idx >= PI_MAX_PIPES) ) - return False; + if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) { + return NT_STATUS_INVALID_PARAMETER; + } - DEBUG(5,("Bind RPC Pipe[%x]: %s\n", cli->fnum, - pipe_names[cli->pipe_idx].client_pipe)); + /* Process the returned NTLMSSP blob first. */ + if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) { + return NT_STATUS_INVALID_PARAMETER; + } - if (!valid_pipe_name(cli->pipe_idx, &abstract, &transfer)) - return False; + if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) { + return NT_STATUS_INVALID_PARAMETER; + } - prs_init(&rpc_out, 0, cli->cli->mem_ctx, MARSHALL); + /* TODO - check auth_type/auth_level match. */ - /* - * Use the MAX_PDU_FRAG_LEN buffer to store the bind request. - */ + server_response = data_blob(NULL, phdr->auth_len); + prs_copy_data_out((char *)server_response.data, rbuf, phdr->auth_len); + + nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state, + server_response, + &client_reply); + + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0,("rpc_finish_auth3_bind: NTLMSSP update using server blob failed.\n")); + return nt_status; + } - prs_give_memory( &rpc_out, buffer, sizeof(buffer), False); + prs_init(&rpc_out, 0, prs_get_mem_context(rbuf), MARSHALL); - rpc_call_id = get_rpc_call_id(); + nt_status = create_rpc_bind_auth3(cli, rpc_call_id, + auth_type, auth_level, + &client_reply, &rpc_out); - if (cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) { - NTSTATUS nt_status; - fstring password; + if (!NT_STATUS_IS_OK(nt_status)) { + prs_mem_free(&rpc_out); + data_blob_free(&client_reply); + data_blob_free(&server_response); + return nt_status; + } - DEBUG(5, ("NTLMSSP authenticated pipe selected\n")); + /* 8 here is named pipe message mode. */ + ret = cli_write(cli->cli, cli->fnum, 0x8, prs_data_p(&rpc_out), 0, + (size_t)prs_offset(&rpc_out)); - nt_status = ntlmssp_client_start(&cli->ntlmssp_pipe_state); - - if (!NT_STATUS_IS_OK(nt_status)) - return False; + if (ret != (ssize_t)prs_offset(&rpc_out)) { + DEBUG(0,("rpc_send_auth_auth3: cli_write failed. Return was %d\n", (int)ret)); + prs_mem_free(&rpc_out); + data_blob_free(&client_reply); + data_blob_free(&server_response); + return cli_get_nt_error(cli->cli); + } - /* Currently the NTLMSSP code does not implement NTLM2 correctly for signing or sealing */ + DEBUG(5,("rpc_send_auth_auth3: Remote machine %s pipe %s " + "fnum 0x%x sent auth3 response ok.\n", + cli->cli->desthost, + cli->pipe_name, + (unsigned int)cli->fnum)); - cli->ntlmssp_pipe_state->neg_flags &= ~NTLMSSP_NEGOTIATE_NTLM2; + prs_mem_free(&rpc_out); + data_blob_free(&client_reply); + data_blob_free(&server_response); + return NT_STATUS_OK; +} - nt_status = ntlmssp_set_username(cli->ntlmssp_pipe_state, - cli->user_name); - if (!NT_STATUS_IS_OK(nt_status)) - return False; +/******************************************************************* + Creates a DCE/RPC bind alter context authentication request which + may contain a spnego auth blobl + ********************************************************************/ - nt_status = ntlmssp_set_domain(cli->ntlmssp_pipe_state, - cli->domain); - if (!NT_STATUS_IS_OK(nt_status)) - return False; +static NTSTATUS create_rpc_alter_context(uint32 rpc_call_id, + RPC_IFACE *abstract, + RPC_IFACE *transfer, + enum pipe_auth_level auth_level, + const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */ + prs_struct *rpc_out) +{ + RPC_HDR_AUTH hdr_auth; + prs_struct auth_info; + NTSTATUS ret = NT_STATUS_OK; - if (cli->pwd.null_pwd) { - nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state, - NULL); - if (!NT_STATUS_IS_OK(nt_status)) - return False; - } else { - pwd_get_cleartext(&cli->pwd, password); - nt_status = ntlmssp_set_password(cli->ntlmssp_pipe_state, - password); - if (!NT_STATUS_IS_OK(nt_status)) - return False; - } + ZERO_STRUCT(hdr_auth); + prs_init(&auth_info, RPC_HDR_AUTH_LEN, prs_get_mem_context(rpc_out), MARSHALL); - if (cli->pipe_auth_flags & AUTH_PIPE_SIGN) { - cli->ntlmssp_pipe_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; - } + /* We may change the pad length before marshalling. */ + init_rpc_hdr_auth(&hdr_auth, RPC_SPNEGO_AUTH_TYPE, (int)auth_level, 0, 1); - if (cli->pipe_auth_flags & AUTH_PIPE_SEAL) { - cli->ntlmssp_pipe_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL; + if (pauth_blob->length) { + if (!prs_copy_data_in(&auth_info, (const char *)pauth_blob->data, pauth_blob->length)) { + prs_mem_free(&auth_info); + return NT_STATUS_NO_MEMORY; } - } else if (cli->pipe_auth_flags & AUTH_PIPE_NETSEC) { - cli->auth_info.seq_num = 0; } - /* Marshall the outgoing data. */ - create_rpc_bind_req(cli, &rpc_out, rpc_call_id, - &abstract, &transfer, - global_myname(), cli->domain); - - /* Initialize the incoming data struct. */ - prs_init(&rdata, 0, cli->cli->mem_ctx, UNMARSHALL); - - /* send data on \PIPE\. receive a response */ - if (rpc_api_pipe(cli, &rpc_out, &rdata, RPC_BINDACK)) { - RPC_HDR_BA hdr_ba; - - DEBUG(5, ("rpc_pipe_bind: rpc_api_pipe returned OK.\n")); - - if(!smb_io_rpc_hdr_ba("", &hdr_ba, &rdata, 0)) { - DEBUG(0,("rpc_pipe_bind: Failed to unmarshall RPC_HDR_BA.\n")); - prs_mem_free(&rdata); - return False; - } + ret = create_bind_or_alt_ctx_internal(RPC_ALTCONT, + rpc_out, + rpc_call_id, + abstract, + transfer, + &hdr_auth, + &auth_info); + prs_mem_free(&auth_info); + return ret; +} - if(!check_bind_response(&hdr_ba, cli->pipe_idx, &transfer)) { - DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n")); - prs_mem_free(&rdata); - return False; - } +/******************************************************************* + Third leg of the SPNEGO bind mechanism - sends alter context PDU + and gets a response. + ********************************************************************/ - cli->max_xmit_frag = hdr_ba.bba.max_tsize; - cli->max_recv_frag = hdr_ba.bba.max_rsize; +static NTSTATUS rpc_finish_spnego_ntlmssp_bind(struct rpc_pipe_client *cli, + RPC_HDR *phdr, + prs_struct *rbuf, + uint32 rpc_call_id, + RPC_IFACE *abstract, + RPC_IFACE *transfer, + enum pipe_auth_type auth_type, + enum pipe_auth_level auth_level) +{ + DATA_BLOB server_spnego_response = data_blob(NULL,0); + DATA_BLOB server_ntlm_response = data_blob(NULL,0); + DATA_BLOB client_reply = data_blob(NULL,0); + DATA_BLOB tmp_blob = data_blob(NULL, 0); + RPC_HDR_AUTH hdr_auth; + NTSTATUS nt_status; + prs_struct rpc_out; - /* - * If we're doing NTLMSSP auth we need to send a reply to - * the bind-ack to complete the 3-way challenge response - * handshake. - */ + if (!phdr->auth_len || (phdr->frag_len < phdr->auth_len + RPC_HDR_AUTH_LEN)) { + return NT_STATUS_INVALID_PARAMETER; + } - if ((cli->pipe_auth_flags & AUTH_PIPE_NTLMSSP) - && !rpc_send_auth_reply(cli, &rdata, rpc_call_id)) { - DEBUG(0,("rpc_pipe_bind: rpc_send_auth_reply failed.\n")); - prs_mem_free(&rdata); - return False; - } - prs_mem_free(&rdata); - return True; + /* Process the returned NTLMSSP blob first. */ + if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) { + return NT_STATUS_INVALID_PARAMETER; } - return False; -} + if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) { + return NT_STATUS_INVALID_PARAMETER; + } -/**************************************************************************** - Open a session. - ****************************************************************************/ + server_spnego_response = data_blob(NULL, phdr->auth_len); + prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len); + + /* The server might give us back two challenges - tmp_blob is for the second. */ + if (!spnego_parse_challenge(server_spnego_response, &server_ntlm_response, &tmp_blob)) { + data_blob_free(&server_spnego_response); + data_blob_free(&server_ntlm_response); + data_blob_free(&tmp_blob); + return NT_STATUS_INVALID_PARAMETER; + } -BOOL cli_nt_session_open(struct cli_state *cli, const int pipe_idx) -{ - int fnum; - struct rpc_pipe_client *cli_pipe; + /* We're finished with the server spnego response and the tmp_blob. */ + data_blob_free(&server_spnego_response); + data_blob_free(&tmp_blob); - SMB_ASSERT(cli->pipes[pipe_idx].fnum == 0); + nt_status = ntlmssp_update(cli->auth.a_u.ntlmssp_state, + server_ntlm_response, + &client_reply); - /* The pipe index must fall within our array */ + /* Finished with the server_ntlm response */ + data_blob_free(&server_ntlm_response); - SMB_ASSERT((pipe_idx >= 0) && (pipe_idx < PI_MAX_PIPES)); + if (!NT_STATUS_IS_OK(nt_status)) { + DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: NTLMSSP update using server blob failed.\n")); + data_blob_free(&client_reply); + return nt_status; + } - if (cli->capabilities & CAP_NT_SMBS) { - if ((fnum = cli_nt_create(cli, &pipe_names[pipe_idx].client_pipe[5], DESIRED_ACCESS_PIPE)) == -1) { - DEBUG(0,("cli_nt_session_open: cli_nt_create failed on pipe %s to machine %s. Error was %s\n", - &pipe_names[pipe_idx].client_pipe[5], cli->desthost, cli_errstr(cli))); - return False; - } + /* SPNEGO wrap the client reply. */ + tmp_blob = spnego_gen_auth(client_reply); + data_blob_free(&client_reply); + client_reply = tmp_blob; + tmp_blob = data_blob(NULL,0); /* Ensure it's safe to free this just in case. */ - cli->pipes[pipe_idx].fnum = (uint16)fnum; - } else { - if ((fnum = cli_open(cli, pipe_names[pipe_idx].client_pipe, O_CREAT|O_RDWR, DENY_NONE)) == -1) { - DEBUG(1,("cli_nt_session_open: cli_open failed on pipe %s to machine %s. Error was %s\n", - pipe_names[pipe_idx].client_pipe, cli->desthost, cli_errstr(cli))); - return False; - } + /* Now prepare the alter context pdu. */ + prs_init(&rpc_out, 0, prs_get_mem_context(rbuf), MARSHALL); - cli->pipes[pipe_idx].fnum = (uint16)fnum; + nt_status = create_rpc_alter_context(rpc_call_id, + abstract, + transfer, + auth_level, + &client_reply, + &rpc_out); - /**************** Set Named Pipe State ***************/ - if (!rpc_pipe_set_hnd_state(&cli->pipes[pipe_idx], pipe_names[pipe_idx].client_pipe, 0x4300)) { - DEBUG(0,("cli_nt_session_open: pipe hnd state failed. Error was %s\n", - cli_errstr(cli))); - cli_close(cli, cli->pipes[pipe_idx].fnum); - cli->pipes[pipe_idx].fnum = 0; - return False; - } + data_blob_free(&client_reply); + + if (!NT_STATUS_IS_OK(nt_status)) { + prs_mem_free(&rpc_out); + return nt_status; } - cli_pipe = &cli->pipes[pipe_idx]; - cli_pipe->pipe_idx = pipe_idx; - cli_pipe->cli = cli; - cli_pipe->pipe_auth_flags = cli->pipe_auth_flags; - memcpy(&cli_pipe->auth_info.sess_key, - cli->sess_key, sizeof(cli->sess_key)); + /* Initialize the returning data struct. */ + prs_mem_free(rbuf); + prs_init(rbuf, 0, cli->cli->mem_ctx, UNMARSHALL); - /******************* bind request on pipe *****************/ + nt_status = rpc_api_pipe(cli, &rpc_out, rbuf, RPC_ALTCONTRESP); + if (!NT_STATUS_IS_OK(nt_status)) { + prs_mem_free(&rpc_out); + return nt_status; + } - if (!rpc_pipe_bind(&cli->pipes[pipe_idx])) { - DEBUG(2,("cli_nt_session_open: rpc bind to %s failed\n", - get_pipe_name_from_index(pipe_idx))); - cli_close(cli, cli->pipes[pipe_idx].fnum); - cli->pipes[pipe_idx].fnum = 0; - return False; + prs_mem_free(&rpc_out); + + /* Get the auth blob from the reply. */ + if(!smb_io_rpc_hdr("rpc_hdr ", phdr, rbuf, 0)) { + DEBUG(0,("rpc_finish_spnego_ntlmssp_bind: Failed to unmarshall RPC_HDR.\n")); + return NT_STATUS_BUFFER_TOO_SMALL; } - cli->pipe_idx = pipe_idx; + if (!prs_set_offset(rbuf, phdr->frag_len - phdr->auth_len - RPC_HDR_AUTH_LEN)) { + return NT_STATUS_INVALID_PARAMETER; + } - /* - * Setup the remote server name prefixed by \ and the machine account name. - */ + if(!smb_io_rpc_hdr_auth("hdr_auth", &hdr_auth, rbuf, 0)) { + return NT_STATUS_INVALID_PARAMETER; + } - fstrcpy(cli->srv_name_slash, "\\\\"); - fstrcat(cli->srv_name_slash, cli->desthost); - strupper_m(cli->srv_name_slash); + server_spnego_response = data_blob(NULL, phdr->auth_len); + prs_copy_data_out((char *)server_spnego_response.data, rbuf, phdr->auth_len); - fstrcpy(cli->clnt_name_slash, "\\\\"); - fstrcat(cli->clnt_name_slash, global_myname()); - strupper_m(cli->clnt_name_slash); + /* Check we got a valid auth response. */ + if (!spnego_parse_auth_response(server_spnego_response, NT_STATUS_OK, &tmp_blob)) { + data_blob_free(&server_spnego_response); + data_blob_free(&tmp_blob); + return NT_STATUS_INVALID_PARAMETER; + } - fstrcpy(cli->mach_acct, global_myname()); - fstrcat(cli->mach_acct, "$"); - strupper_m(cli->mach_acct); + data_blob_free(&server_spnego_response); + data_blob_free(&tmp_blob); - /* Remember which pipe we're talking to */ - fstrcpy(cli->pipe_name, pipe_names[pipe_idx].client_pipe); + DEBUG(5,("rpc_finish_spnego_ntlmssp_bind: alter context request to " + "remote machine %s pipe %s fnum 0x%x.\n", + cli->cli->desthost, + cli->pipe_name, + (unsigned int)cli->fnum)); - return True; + return NT_STATUS_OK; } - /**************************************************************************** - Open a session to the NETLOGON pipe using schannel. - - (Assumes that the netlogon pipe is already open) - ****************************************************************************/ + Do an rpc bind. +****************************************************************************/ -NTSTATUS cli_nt_establish_netlogon(struct cli_state *cli, int sec_chan, - const uchar trust_password[16]) +static NTSTATUS rpc_pipe_bind(struct rpc_pipe_client *cli, + enum pipe_auth_type auth_type, + enum pipe_auth_level auth_level) { - NTSTATUS result; - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; - - cli_nt_netlogon_netsec_session_close(cli); - - if (lp_client_schannel() != False) - neg_flags |= NETLOGON_NEG_SCHANNEL; + RPC_HDR hdr; + RPC_HDR_BA hdr_ba; + RPC_IFACE abstract; + RPC_IFACE transfer; + prs_struct rpc_out; + prs_struct rbuf; + uint32 rpc_call_id; + NTSTATUS status; - result = cli_nt_setup_creds(cli, sec_chan, trust_password, - &neg_flags, 2); + DEBUG(5,("Bind RPC Pipe[%x]: %s auth_type %u, auth_level %u\n", + (unsigned int)cli->fnum, + cli->pipe_name, + (unsigned int)auth_type, + (unsigned int)auth_level )); - if (!NT_STATUS_IS_OK(result)) { - cli_nt_session_close(cli); - return result; + if (!valid_pipe_name(cli->pipe_idx, &abstract, &transfer)) { + return NT_STATUS_INVALID_PARAMETER; } - if ((lp_client_schannel() == True) && - ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { + prs_init(&rpc_out, 0, cli->cli->mem_ctx, MARSHALL); - DEBUG(3, ("Server did not offer schannel\n")); - cli_nt_session_close(cli); - return NT_STATUS_UNSUCCESSFUL; - } + rpc_call_id = get_rpc_call_id(); - if ((lp_client_schannel() == False) || - ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0)) { - return NT_STATUS_OK; - - /* keep the existing connection to NETLOGON open */ + /* Marshall the outgoing data. */ + status = create_rpc_bind_req(cli, &rpc_out, rpc_call_id, + &abstract, &transfer, + auth_type, + auth_level); + if (!NT_STATUS_IS_OK(status)) { + prs_mem_free(&rpc_out); + return status; } - cli->netlogon_pipe = cli->pipes[PI_NETLOGON]; - ZERO_STRUCT(cli->pipes[PI_NETLOGON]); + /* Initialize the incoming data struct. */ + prs_init(&rbuf, 0, cli->cli->mem_ctx, UNMARSHALL); - /* Server offered schannel, so try it. */ + /* send data on \PIPE\. receive a response */ + status = rpc_api_pipe(cli, &rpc_out, &rbuf, RPC_BINDACK); + if (!NT_STATUS_IS_OK(status)) { + prs_mem_free(&rpc_out); + return status; + } - memcpy(cli->pipes[PI_NETLOGON].auth_info.sess_key, cli->sess_key, - sizeof(cli->pipes[PI_NETLOGON].auth_info.sess_key)); + prs_mem_free(&rpc_out); - cli->pipe_auth_flags = AUTH_PIPE_NETSEC; - cli->pipe_auth_flags |= AUTH_PIPE_SIGN; - cli->pipe_auth_flags |= AUTH_PIPE_SEAL; + DEBUG(3,("rpc_pipe_bind: Remote machine %s pipe %s " + "fnum 0x%x bind request returned ok.\n", + cli->cli->desthost, + cli->pipe_name, + (unsigned int)cli->fnum)); + + /* Unmarshall the RPC header */ + if(!smb_io_rpc_hdr("hdr" , &hdr, &rbuf, 0)) { + DEBUG(0,("rpc_pipe_bind: failed to unmarshall RPC_HDR.\n")); + prs_mem_free(&rbuf); + return NT_STATUS_BUFFER_TOO_SMALL; + } - return cli_nt_session_open(cli, PI_NETLOGON) ? - NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; -} + if(!smb_io_rpc_hdr_ba("", &hdr_ba, &rbuf, 0)) { + DEBUG(0,("rpc_pipe_bind: Failed to unmarshall RPC_HDR_BA.\n")); + prs_mem_free(&rbuf); + return NT_STATUS_BUFFER_TOO_SMALL; + } + if(!check_bind_response(&hdr_ba, cli->pipe_idx, &transfer)) { + DEBUG(2,("rpc_pipe_bind: check_bind_response failed.\n")); + prs_mem_free(&rbuf); + return NT_STATUS_BUFFER_TOO_SMALL; + } -NTSTATUS cli_nt_setup_netsec(struct cli_state *cli, int sec_chan, int auth_flags, - const uchar trust_password[16]) -{ - NTSTATUS result; - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; - cli->pipe_auth_flags = 0; + cli->max_xmit_frag = hdr_ba.bba.max_tsize; + cli->max_recv_frag = hdr_ba.bba.max_rsize; - if (lp_client_schannel() == False) { - return NT_STATUS_OK; - } + /* For authenticated binds we may need to do 3 or 4 leg binds. */ + switch(auth_type) { - if (!cli_nt_session_open(cli, PI_NETLOGON)) { - DEBUG(0, ("Could not initialise %s\n", - get_pipe_name_from_index(PI_NETLOGON))); - return NT_STATUS_UNSUCCESSFUL; - } + case PIPE_AUTH_TYPE_NONE: + case PIPE_AUTH_TYPE_SCHANNEL: + /* Bind complete. */ + break; - neg_flags |= NETLOGON_NEG_SCHANNEL; + case PIPE_AUTH_TYPE_NTLMSSP: + /* Need to send AUTH3 packet - no reply. */ + status = rpc_finish_auth3_bind(cli, &hdr, &rbuf, rpc_call_id, + auth_type, auth_level); + if (!NT_STATUS_IS_OK(status)) { + prs_mem_free(&rbuf); + return status; + } + break; + + case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: + /* Need to send alter context request and reply. */ + status = rpc_finish_spnego_ntlmssp_bind(cli, &hdr, &rbuf, rpc_call_id, + &abstract, &transfer, + auth_type, auth_level); + if (!NT_STATUS_IS_OK(status)) { + prs_mem_free(&rbuf); + return status; + } + break; - result = cli_nt_setup_creds(cli, sec_chan, trust_password, - &neg_flags, 2); + case PIPE_AUTH_TYPE_KRB5: + /* */ - if (!(neg_flags & NETLOGON_NEG_SCHANNEL) - && lp_client_schannel() == True) { - DEBUG(1, ("Could not negotiate SCHANNEL with the DC!\n")); - result = NT_STATUS_UNSUCCESSFUL; + default: + DEBUG(0,("cli_finish_bind_auth: unknown auth type %u\n", + (unsigned int)auth_type )); + prs_mem_free(&rbuf); + return NT_STATUS_INVALID_INFO_CLASS; } - if (!NT_STATUS_IS_OK(result)) { - ZERO_STRUCT(cli->pipes[cli->pipe_idx].auth_info.sess_key); - ZERO_STRUCT(cli->sess_key); - cli->pipe_auth_flags = 0; - cli_nt_session_close(cli); - return result; - } + /* Pipe is bound - set up auth_type and auth_level data. */ - memcpy(cli->pipes[PI_NETLOGON].auth_info.sess_key, cli->sess_key, - sizeof(cli->pipes[PI_NETLOGON].auth_info.sess_key)); - - cli_close(cli, cli->pipes[PI_NETLOGON].fnum); - cli->pipes[PI_NETLOGON].fnum = 0; - cli->pipe_idx = -1; - - /* doing schannel, not per-user auth */ - cli->pipe_auth_flags = auth_flags; + cli->auth.auth_type = auth_type; + cli->auth.auth_level = auth_level; + prs_mem_free(&rbuf); return NT_STATUS_OK; } -const char *cli_pipe_get_name(struct cli_state *cli) -{ - return cli->pipe_name; -} +/**************************************************************************** + Open a named pipe over SMB to a remote server. + ****************************************************************************/ -static struct rpc_pipe_client *cli_rpc_open(struct cli_state *cli, - int pipe_idx) +static struct rpc_pipe_client *cli_rpc_pipe_open(struct cli_state *cli, int pipe_idx, NTSTATUS *perr) { TALLOC_CTX *mem_ctx; struct rpc_pipe_client *result; int fnum; - /* The pipe index must fall within our array */ + *perr = NT_STATUS_NO_MEMORY; + + /* The pipe name index must fall within our array */ SMB_ASSERT((pipe_idx >= 0) && (pipe_idx < PI_MAX_PIPES)); mem_ctx = talloc_init("struct rpc_pipe_client"); - if (mem_ctx == NULL) return NULL; + if (mem_ctx == NULL) { + return NULL; + } - result = TALLOC_P(mem_ctx, struct rpc_pipe_client); - if (result == NULL) return NULL; + result = TALLOC_ZERO_P(mem_ctx, struct rpc_pipe_client); + if (result == NULL) { + return NULL; + } result->mem_ctx = mem_ctx; - fnum = cli_nt_create(cli, &pipe_names[pipe_idx].client_pipe[5], - DESIRED_ACCESS_PIPE); + result->pipe_name = cli_get_pipe_name(pipe_idx); + + fnum = cli_nt_create(cli, result->pipe_name, DESIRED_ACCESS_PIPE); if (fnum == -1) { - DEBUG(0,("cli_rpc_open failed on pipe %s " + DEBUG(0,("cli_rpc_pipe_open: cli_nt_create failed on pipe %s " "to machine %s. Error was %s\n", - &pipe_names[pipe_idx].client_pipe[5], cli->desthost, + result->pipe_name, cli->desthost, cli_errstr(cli))); + *perr = cli_get_nt_error(cli); talloc_destroy(result->mem_ctx); return NULL; } @@ -1681,91 +2197,440 @@ static struct rpc_pipe_client *cli_rpc_open(struct cli_state *cli, result->fnum = fnum; result->cli = cli; result->pipe_idx = pipe_idx; + result->auth.auth_type = PIPE_AUTH_TYPE_NONE; + result->auth.auth_level = PIPE_AUTH_LEVEL_NONE; + + if (pipe_idx == PI_NETLOGON) { + /* Set up a netlogon credential chain for a netlogon pipe. */ + result->dc = TALLOC_ZERO_P(mem_ctx, struct dcinfo); + if (result->dc == NULL) { + talloc_destroy(result->mem_ctx); + return NULL; + } + } + + DLIST_ADD(cli->pipe_list, result); + *perr = NT_STATUS_OK; return result; } -struct rpc_pipe_client *cli_rpc_open_noauth(struct cli_state *cli, - int pipe_idx) +/**************************************************************************** + Open a named pipe to an SMB server and bind anonymously. + ****************************************************************************/ + +struct rpc_pipe_client *cli_rpc_pipe_open_noauth(struct cli_state *cli, int pipe_idx, NTSTATUS *perr) { struct rpc_pipe_client *result; - result = cli_rpc_open(cli, pipe_idx); - if (result == NULL) return NULL; - - result->max_xmit_frag = 0; - result->pipe_auth_flags = 0; + result = cli_rpc_pipe_open(cli, pipe_idx, perr); + if (result == NULL) { + return NULL; + } - if (!rpc_pipe_bind(result)) { - DEBUG(0, ("rpc_pipe_bind failed\n")); - talloc_destroy(result->mem_ctx); + *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_NONE, PIPE_AUTH_LEVEL_NONE); + if (!NT_STATUS_IS_OK(*perr)) { + DEBUG(0, ("cli_rpc_pipe_open_noauth: rpc_pipe_bind for pipe %s failed with error %s\n", + cli_get_pipe_name(pipe_idx), nt_errstr(*perr) )); + cli_rpc_pipe_close(result); return NULL; } + DEBUG(10,("cli_rpc_pipe_open_noauth: opened pipe %s to machine %s and bound anonymously.\n", + result->pipe_name, cli->desthost )); + return result; } -struct rpc_pipe_client *cli_rpc_open_ntlmssp(struct cli_state *cli, - int pipe_idx, - const char *domain, - const char *username, - const char *password) +/**************************************************************************** + Free function for NTLMSSP auth. + ****************************************************************************/ + +static void cli_ntlmssp_auth_free(struct cli_pipe_auth_data *auth) +{ + if (auth->a_u.ntlmssp_state) { + ntlmssp_end(&auth->a_u.ntlmssp_state); + auth->a_u.ntlmssp_state = NULL; + } +} + +/**************************************************************************** + Open a named pipe to an SMB server and bind using NTLMSSP or SPNEGO NTLMSSP + ****************************************************************************/ + +static struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp_internal(struct cli_state *cli, + int pipe_idx, + enum pipe_auth_type auth_type, + enum pipe_auth_level auth_level, + const char *domain, + const char *username, + const char *password, + NTSTATUS *perr) { struct rpc_pipe_client *result; + NTLMSSP_STATE *ntlmssp_state = NULL; - result = cli_rpc_open(cli, pipe_idx); - if (result == NULL) return NULL; + result = cli_rpc_pipe_open(cli, pipe_idx, perr); + if (result == NULL) { + return NULL; + } - result->max_xmit_frag = 0; - result->pipe_auth_flags = - AUTH_PIPE_NTLMSSP|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL; + result->auth.cli_auth_data_free_func = cli_ntlmssp_auth_free; + result->domain = domain; result->user_name = username; pwd_set_cleartext(&result->pwd, password); - if (!rpc_pipe_bind(result)) { - DEBUG(0, ("cli_rpc_pipe_bind failed\n")); - talloc_destroy(result->mem_ctx); - return NULL; + *perr = ntlmssp_client_start(&ntlmssp_state); + if (!NT_STATUS_IS_OK(*perr)) { + goto err; + } + + result->auth.a_u.ntlmssp_state = ntlmssp_state; + + *perr = ntlmssp_set_username(ntlmssp_state, cli->user_name); + if (!NT_STATUS_IS_OK(*perr)) { + goto err; + } + + *perr = ntlmssp_set_domain(ntlmssp_state, cli->domain); + if (!NT_STATUS_IS_OK(*perr)) { + goto err; } + if (cli->pwd.null_pwd) { + *perr = ntlmssp_set_password(ntlmssp_state, NULL); + if (!NT_STATUS_IS_OK(*perr)) { + goto err; + } + } else { + *perr = ntlmssp_set_password(ntlmssp_state, password); + if (!NT_STATUS_IS_OK(*perr)) { + goto err; + } + } + + /* Turn off sign+seal to allow selected auth level to turn it back on. */ + ntlmssp_state->neg_flags &= ~(NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL); + + if (auth_level == PIPE_AUTH_LEVEL_INTEGRITY) { + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SIGN; + } else if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) { + ntlmssp_state->neg_flags |= NTLMSSP_NEGOTIATE_SEAL | NTLMSSP_NEGOTIATE_SIGN; + } + + *perr = rpc_pipe_bind(result, auth_type, auth_level); + if (!NT_STATUS_IS_OK(*perr)) { + DEBUG(0, ("cli_rpc_pipe_open_ntlmssp_internal: cli_rpc_pipe_bind failed with error %s\n", + nt_errstr(*perr) )); + goto err; + } + + DEBUG(10,("cli_rpc_pipe_open_ntlmssp_internal: opened pipe %s to machine %s and" + "bound NTLMSSP as user %s\\%s.\n", + result->pipe_name, cli->desthost, + domain, username )); + return result; + + err: + + cli_rpc_pipe_close(result); + return NULL; } -struct rpc_pipe_client *cli_rpc_open_schannel(struct cli_state *cli, - int pipe_idx, - const uchar session_key[16], - const char *domain) +/**************************************************************************** + External interface. + Open a named pipe to an SMB server and bind using NTLMSSP (bind type 10) + ****************************************************************************/ + +struct rpc_pipe_client *cli_rpc_pipe_open_ntlmssp(struct cli_state *cli, + int pipe_idx, + enum pipe_auth_level auth_level, + const char *domain, + const char *username, + const char *password, + NTSTATUS *perr) +{ + return cli_rpc_pipe_open_ntlmssp_internal(cli, + pipe_idx, + PIPE_AUTH_TYPE_NTLMSSP, + auth_level, + domain, + username, + password, + perr); +} + +/**************************************************************************** + External interface. + Open a named pipe to an SMB server and bind using spnego NTLMSSP (bind type 9) + ****************************************************************************/ + +struct rpc_pipe_client *cli_rpc_pipe_open_spnego_ntlmssp(struct cli_state *cli, + int pipe_idx, + enum pipe_auth_level auth_level, + const char *domain, + const char *username, + const char *password, + NTSTATUS *perr) +{ + return cli_rpc_pipe_open_ntlmssp_internal(cli, + pipe_idx, + PIPE_AUTH_TYPE_SPNEGO_NTLMSSP, + auth_level, + domain, + username, + password, + perr); +} + +/**************************************************************************** + Open a netlogon pipe and get the schannel session key. + ****************************************************************************/ + +static struct rpc_pipe_client *get_schannel_session_key(struct cli_state *cli, + const char *domain, + NTSTATUS *perr) +{ + uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL; + struct rpc_pipe_client *netlogon_pipe = NULL; + uint32 sec_chan_type = 0; + char machine_pwd[16]; + fstring machine_account; + + netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, perr); + if (!netlogon_pipe) { + return NULL; + } + + /* Get the machine account credentials from secrets.tdb. */ + if (!get_trust_pw(domain, machine_pwd, &sec_chan_type)) { + DEBUG(0, ("get_schannel_session_key: could not fetch " + "trust account password for domain '%s'\n", + domain)); + cli_rpc_pipe_close(netlogon_pipe); + *perr = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; + return NULL; + } + + if ( IS_DC ) { + fstrcpy( machine_account, lp_workgroup() ); + } else { + /* Hmmm. Is this correct for trusted domains when we're a member server ? JRA. */ + if (strequal(domain, lp_workgroup())) { + fstrcpy(machine_account, global_myname()); + } else { + fstrcpy(machine_account, domain); + } + } + + *perr = rpccli_netlogon_setup_creds(netlogon_pipe, + cli->desthost, + domain, + machine_account, + machine_pwd, + sec_chan_type, + &neg_flags); + + if (!NT_STATUS_IS_OK(*perr)) { + DEBUG(3,("get_schannel_session_key: rpccli_netlogon_setup_creds " + "failed with result %s\n", + nt_errstr(*perr) )); + cli_rpc_pipe_close(netlogon_pipe); + return NULL; + } + + if ((neg_flags & NETLOGON_NEG_SCHANNEL) == 0) { + DEBUG(3, ("get_schannel_session_key: Server %s did not offer schannel\n", + cli->desthost)); + cli_rpc_pipe_close(netlogon_pipe); + *perr = NT_STATUS_INVALID_NETWORK_RESPONSE; + return NULL; + } + + return netlogon_pipe; +} + +/**************************************************************************** + External interface. + Open a named pipe to an SMB server and bind using schannel (bind type 68) + using session_key. sign and seal. + ****************************************************************************/ + +struct rpc_pipe_client *cli_rpc_pipe_open_schannel_with_key(struct cli_state *cli, + int pipe_idx, + enum pipe_auth_level auth_level, + const char *domain, + const struct dcinfo *pdc, + NTSTATUS *perr) { struct rpc_pipe_client *result; - result = cli_rpc_open(cli, pipe_idx); - if (result == NULL) return NULL; - - result->max_xmit_frag = 0; - result->pipe_auth_flags = - AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN | AUTH_PIPE_SEAL; + result = cli_rpc_pipe_open(cli, pipe_idx, perr); + if (result == NULL) { + return NULL; + } + + result->auth.a_u.schannel_auth = TALLOC_ZERO_P(result->mem_ctx, struct schannel_auth_struct); + if (!result->auth.a_u.schannel_auth) { + cli_rpc_pipe_close(result); + *perr = NT_STATUS_NO_MEMORY; + return NULL; + } + result->domain = domain; - memcpy(result->auth_info.sess_key, session_key, 16); + memcpy(result->auth.a_u.schannel_auth->sess_key, pdc->sess_key, 16); - if (!rpc_pipe_bind(result)) { - DEBUG(0, ("cli_rpc_pipe_bind failed\n")); - talloc_destroy(result->mem_ctx); + *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_SCHANNEL, auth_level); + if (!NT_STATUS_IS_OK(*perr)) { + DEBUG(0, ("cli_rpc_pipe_open_schannel_with_key: cli_rpc_pipe_bind failed with error %s\n", + nt_errstr(*perr) )); + cli_rpc_pipe_close(result); return NULL; } + /* The credentials on a new netlogon pipe are the ones we are passed in - copy them over. */ + if (result->dc) { + *result->dc = *pdc; + } + + DEBUG(10,("cli_rpc_pipe_open_schannel_with_key: opened pipe %s to machine %s " + "for domain %s " + "and bound using schannel.\n", + result->pipe_name, cli->desthost, domain )); + return result; } -void cli_rpc_close(struct rpc_pipe_client *cli_pipe) +/**************************************************************************** + Open a named pipe to an SMB server and bind using schannel (bind type 68). + Fetch the session key ourselves using a temporary netlogon pipe. + ****************************************************************************/ + +struct rpc_pipe_client *cli_rpc_pipe_open_schannel(struct cli_state *cli, + int pipe_idx, + enum pipe_auth_level auth_level, + const char *domain, + NTSTATUS *perr) { - if (!cli_close(cli_pipe->cli, cli_pipe->fnum)) - DEBUG(0,("cli_rpc_open failed on pipe %s " - "to machine %s. Error was %s\n", - &pipe_names[cli_pipe->pipe_idx].client_pipe[5], - cli_pipe->cli->desthost, - cli_errstr(cli_pipe->cli))); + struct rpc_pipe_client *netlogon_pipe = NULL; + struct rpc_pipe_client *result = NULL; + + netlogon_pipe = get_schannel_session_key(cli, domain, perr); + if (!netlogon_pipe) { + DEBUG(0,("cli_rpc_pipe_open_schannel: failed to get schannel session " + "key from server %s for domain %s.\n", + cli->desthost, domain )); + return NULL; + } + + result = cli_rpc_pipe_open_schannel_with_key(cli, pipe_idx, + auth_level, + domain, netlogon_pipe->dc, perr); + + /* Now we've bound using the session key we can close the netlog pipe. */ + cli_rpc_pipe_close(netlogon_pipe); + + return result; +} + +/**************************************************************************** + Free function for the kerberos spcific data. + ****************************************************************************/ + +static void kerberos_auth_struct_free(struct cli_pipe_auth_data *a) +{ + data_blob_free(&a->a_u.kerberos_auth->session_key); +} - talloc_destroy(cli_pipe->mem_ctx); +/**************************************************************************** + Open a named pipe to an SMB server and bind using krb5 (bind type 16). + ****************************************************************************/ + +struct rpc_pipe_client *cli_rpc_pipe_open_krb5(struct cli_state *cli, + int pipe_idx, + enum pipe_auth_level auth_level, + const char *service_princ, + const char *username, + const char *password, + NTSTATUS *perr) +{ +#ifdef HAVE_KRB5 + struct rpc_pipe_client *result; + + result = cli_rpc_pipe_open(cli, pipe_idx, perr); + if (result == NULL) { + return NULL; + } + + /* Default service principal is "host/server@realm" */ + if (!service_princ) { + service_princ = talloc_asprintf(result->mem_ctx, "host/%s@%s", + cli->desthost, lp_realm() ); + if (!service_princ) { + cli_rpc_pipe_close(result); + return NULL; + } + } + + /* Only get a new TGT if username/password are given. */ + if (username && password) { + int ret = kerberos_kinit_password(username, password, 0, NULL, NULL); + if (ret) { + cli_rpc_pipe_close(result); + return NULL; + } + } + + result->auth.a_u.kerberos_auth = TALLOC_ZERO_P(cli->mem_ctx, struct kerberos_auth_struct); + if (!result->auth.a_u.kerberos_auth) { + cli_rpc_pipe_close(result); + *perr = NT_STATUS_NO_MEMORY; + return NULL; + } + + result->auth.a_u.kerberos_auth->service_principal = service_princ; + result->auth.cli_auth_data_free_func = kerberos_auth_struct_free; + + *perr = rpc_pipe_bind(result, PIPE_AUTH_TYPE_KRB5, auth_level); + if (!NT_STATUS_IS_OK(*perr)) { + DEBUG(0, ("cli_rpc_pipe_open_krb5: cli_rpc_pipe_bind failed with error %s\n", + nt_errstr(*perr) )); + cli_rpc_pipe_close(result); + return NULL; + } + + return result; +#else + DEBUG(0,("cli_rpc_pipe_open_krb5: kerberos not found at compile time.\n")); + return NULL; +#endif } +#if 0 /* Moved to libsmb/clientgen.c */ +/**************************************************************************** + External interface. + Close an open named pipe over SMB. Free any authentication data. + ****************************************************************************/ + +void cli_rpc_pipe_close(struct rpc_pipe_client *cli) +{ + if (!cli_close(cli->cli, cli->fnum)) { + DEBUG(0,("cli_rpc_pipe_close: cli_close failed on pipe %s " + "to machine %s. Error was %s\n", + cli->pipe_name), + cli->cli->desthost, + cli_errstr(cli->cli))); + } + + if (cli->auth.cli_auth_data_free_func) { + (*cli->auth.cli_auth_data_free_func)(&cli->auth); + } + DEBUG(10,("cli_rpc_pipe_close: closed pipe %s to machine %s\n", + cli->pipe_name, cli->cli->desthost )); + + DLIST_REMOVE(cli->cli->pipe_list, cli); + talloc_destroy(cli->mem_ctx); +} +#endif diff --git a/source3/rpc_client/cli_reg.c b/source3/rpc_client/cli_reg.c index 97ae8b29e7d..87ab5dc9dad 100644 --- a/source3/rpc_client/cli_reg.c +++ b/source3/rpc_client/cli_reg.c @@ -3,9 +3,7 @@ RPC Pipe client Copyright (C) Andrew Tridgell 1992-2000, - Copyright (C) Luke Kenneth Casson Leighton 1996-2000, - Copyright (C) Paul Ashton 1997-2000. - Copyright (C) Jeremy Allison 1999. + Copyright (C) Jeremy Allison 1999 - 2005 Copyright (C) Simo Sorce 2001 Copyright (C) Jeremy Cooper 2004 Copyright (C) Gerald (Jerry) Carter 2005 @@ -34,7 +32,7 @@ internal connect to a registry hive root (open a registry policy) *******************************************************************/ -static WERROR cli_reg_open_hive_int(struct cli_state *cli, +static WERROR rpccli_reg_open_hive_int(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint16 op_code, const char *op_name, uint32 access_mask, POLICY_HND *hnd) @@ -48,7 +46,7 @@ static WERROR cli_reg_open_hive_int(struct cli_state *cli, init_reg_q_open_hive(&in, access_mask); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, op_code, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, op_code, in, out, qbuf, rbuf, reg_io_q_open_hive, @@ -67,7 +65,7 @@ static WERROR cli_reg_open_hive_int(struct cli_state *cli, connect to a registry hive root (open a registry policy) *******************************************************************/ -WERROR cli_reg_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_reg_connect(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 reg_type, uint32 access_mask, POLICY_HND *reg_hnd) { uint16 op_code; @@ -97,7 +95,7 @@ WERROR cli_reg_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx, return WERR_INVALID_PARAM; } - return cli_reg_open_hive_int(cli, mem_ctx, op_code, op_name, + return rpccli_reg_open_hive_int(cli, mem_ctx, op_code, op_name, access_mask, reg_hnd); } @@ -105,7 +103,7 @@ WERROR cli_reg_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx, /******************************************************************* *******************************************************************/ -WERROR cli_reg_shutdown(struct cli_state * cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_reg_shutdown(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *msg, uint32 timeout, BOOL do_reboot, BOOL force) { @@ -123,7 +121,7 @@ WERROR cli_reg_shutdown(struct cli_state * cli, TALLOC_CTX *mem_ctx, init_reg_q_shutdown(&in, msg, timeout, do_reboot, force); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_SHUTDOWN, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_SHUTDOWN, in, out, qbuf, rbuf, reg_io_q_shutdown, @@ -136,7 +134,7 @@ WERROR cli_reg_shutdown(struct cli_state * cli, TALLOC_CTX *mem_ctx, /******************************************************************* *******************************************************************/ -WERROR cli_reg_abort_shutdown(struct cli_state * cli, TALLOC_CTX *mem_ctx) +WERROR rpccli_reg_abort_shutdown(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx) { REG_Q_ABORT_SHUTDOWN in; REG_R_ABORT_SHUTDOWN out; @@ -145,7 +143,7 @@ WERROR cli_reg_abort_shutdown(struct cli_state * cli, TALLOC_CTX *mem_ctx) ZERO_STRUCT (in); ZERO_STRUCT (out); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_ABORT_SHUTDOWN, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_ABORT_SHUTDOWN, in, out, qbuf, rbuf, reg_io_q_abort_shutdown, @@ -161,7 +159,8 @@ do a REG Unknown 0xB command. sent after a create key or create value. this might be some sort of "sync" or "refresh" command, sent after modification of the registry... ****************************************************************************/ -WERROR cli_reg_flush_key(struct cli_state *cli, TALLOC_CTX *mem_ctx, + +WERROR rpccli_reg_flush_key(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd) { REG_Q_FLUSH_KEY in; @@ -173,7 +172,7 @@ WERROR cli_reg_flush_key(struct cli_state *cli, TALLOC_CTX *mem_ctx, init_reg_q_flush_key(&in, hnd); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_FLUSH_KEY, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_FLUSH_KEY, in, out, qbuf, rbuf, reg_io_q_flush_key, @@ -186,7 +185,8 @@ WERROR cli_reg_flush_key(struct cli_state *cli, TALLOC_CTX *mem_ctx, /**************************************************************************** do a REG Query Key ****************************************************************************/ -WERROR cli_reg_query_key(struct cli_state *cli, TALLOC_CTX *mem_ctx, + +WERROR rpccli_reg_query_key(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, char *key_class, uint32 *class_len, uint32 *num_subkeys, uint32 *max_subkeylen, @@ -204,7 +204,7 @@ WERROR cli_reg_query_key(struct cli_state *cli, TALLOC_CTX *mem_ctx, init_reg_q_query_key( &in, hnd, key_class ); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_QUERY_KEY, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_QUERY_KEY, in, out, qbuf, rbuf, reg_io_q_query_key, @@ -227,7 +227,7 @@ WERROR cli_reg_query_key(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT (out); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_QUERY_KEY, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_QUERY_KEY, in, out, qbuf, rbuf, reg_io_q_query_key, @@ -255,7 +255,7 @@ WERROR cli_reg_query_key(struct cli_state *cli, TALLOC_CTX *mem_ctx, /**************************************************************************** ****************************************************************************/ -WERROR cli_reg_getversion(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_reg_getversion(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, uint32 *version) { REG_Q_GETVERSION in; @@ -267,7 +267,7 @@ WERROR cli_reg_getversion(struct cli_state *cli, TALLOC_CTX *mem_ctx, init_reg_q_getversion(&in, hnd); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_GETVERSION, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_GETVERSION, in, out, qbuf, rbuf, reg_io_q_getversion, @@ -286,7 +286,8 @@ WERROR cli_reg_getversion(struct cli_state *cli, TALLOC_CTX *mem_ctx, /**************************************************************************** do a REG Query Info ****************************************************************************/ -WERROR cli_reg_query_value(struct cli_state *cli, TALLOC_CTX *mem_ctx, + +WERROR rpccli_reg_query_value(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, const char *val_name, uint32 *type, REGVAL_BUFFER *buffer) { @@ -299,7 +300,7 @@ WERROR cli_reg_query_value(struct cli_state *cli, TALLOC_CTX *mem_ctx, init_reg_q_query_value(&in, hnd, val_name, buffer); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_QUERY_VALUE, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_QUERY_VALUE, in, out, qbuf, rbuf, reg_io_q_query_value, @@ -319,7 +320,8 @@ WERROR cli_reg_query_value(struct cli_state *cli, TALLOC_CTX *mem_ctx, /**************************************************************************** do a REG Set Key Security ****************************************************************************/ -WERROR cli_reg_set_key_sec(struct cli_state *cli, TALLOC_CTX *mem_ctx, + +WERROR rpccli_reg_set_key_sec(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, uint32 sec_info, size_t secdesc_size, SEC_DESC *sec_desc) { @@ -338,7 +340,7 @@ WERROR cli_reg_set_key_sec(struct cli_state *cli, TALLOC_CTX *mem_ctx, init_reg_q_set_key_sec(&in, hnd, sec_info, sec_desc_buf); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_SET_KEY_SEC, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_SET_KEY_SEC, in, out, qbuf, rbuf, reg_io_q_set_key_sec, @@ -353,7 +355,8 @@ WERROR cli_reg_set_key_sec(struct cli_state *cli, TALLOC_CTX *mem_ctx, /**************************************************************************** do a REG Query Key Security ****************************************************************************/ -WERROR cli_reg_get_key_sec(struct cli_state *cli, TALLOC_CTX *mem_ctx, + +WERROR rpccli_reg_get_key_sec(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, uint32 sec_info, uint32 *sec_buf_size, SEC_DESC_BUF *sec_buf) { @@ -366,7 +369,7 @@ WERROR cli_reg_get_key_sec(struct cli_state *cli, TALLOC_CTX *mem_ctx, init_reg_q_get_key_sec(&in, hnd, sec_info, *sec_buf_size, sec_buf); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_GET_KEY_SEC, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_GET_KEY_SEC, in, out, qbuf, rbuf, reg_io_q_get_key_sec, @@ -388,7 +391,8 @@ WERROR cli_reg_get_key_sec(struct cli_state *cli, TALLOC_CTX *mem_ctx, /**************************************************************************** do a REG Delete Value ****************************************************************************/ -WERROR cli_reg_delete_val(struct cli_state *cli, TALLOC_CTX *mem_ctx, + +WERROR rpccli_reg_delete_val(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, char *val_name) { REG_Q_DELETE_VALUE in; @@ -400,7 +404,7 @@ WERROR cli_reg_delete_val(struct cli_state *cli, TALLOC_CTX *mem_ctx, init_reg_q_delete_val(&in, hnd, val_name); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_DELETE_VALUE, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_DELETE_VALUE, in, out, qbuf, rbuf, reg_io_q_delete_value, @@ -413,7 +417,8 @@ WERROR cli_reg_delete_val(struct cli_state *cli, TALLOC_CTX *mem_ctx, /**************************************************************************** do a REG Delete Key ****************************************************************************/ -WERROR cli_reg_delete_key(struct cli_state *cli, TALLOC_CTX *mem_ctx, + +WERROR rpccli_reg_delete_key(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, char *key_name) { REG_Q_DELETE_KEY in; @@ -425,7 +430,7 @@ WERROR cli_reg_delete_key(struct cli_state *cli, TALLOC_CTX *mem_ctx, init_reg_q_delete_key(&in, hnd, key_name); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_DELETE_KEY, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_DELETE_KEY, in, out, qbuf, rbuf, reg_io_q_delete_key, @@ -438,7 +443,8 @@ WERROR cli_reg_delete_key(struct cli_state *cli, TALLOC_CTX *mem_ctx, /**************************************************************************** do a REG Create Key ****************************************************************************/ -WERROR cli_reg_create_key_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx, + +WERROR rpccli_reg_create_key_ex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, char *key_name, char *key_class, uint32 access_desired, POLICY_HND *key) { @@ -453,8 +459,7 @@ WERROR cli_reg_create_key_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT (out); if ( !(sec = make_sec_desc(mem_ctx, 1, SEC_DESC_SELF_RELATIVE, - NULL, NULL, NULL, NULL, &sec_len)) ) - { + NULL, NULL, NULL, NULL, &sec_len)) ) { return WERR_GENERAL_FAILURE; } @@ -463,7 +468,7 @@ WERROR cli_reg_create_key_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx, init_reg_q_create_key_ex(&in, hnd, key_name, key_class, access_desired, sec_buf); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_CREATE_KEY_EX, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_CREATE_KEY_EX, in, out, qbuf, rbuf, reg_io_q_create_key_ex, @@ -482,7 +487,8 @@ WERROR cli_reg_create_key_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx, /**************************************************************************** do a REG Enum Key ****************************************************************************/ -WERROR cli_reg_enum_key(struct cli_state *cli, TALLOC_CTX *mem_ctx, + +WERROR rpccli_reg_enum_key(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, int key_index, fstring key_name, fstring class_name, time_t *mod_time) { @@ -495,7 +501,7 @@ WERROR cli_reg_enum_key(struct cli_state *cli, TALLOC_CTX *mem_ctx, init_reg_q_enum_key(&in, hnd, key_index); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_ENUM_KEY, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_ENUM_KEY, in, out, qbuf, rbuf, reg_io_q_enum_key, @@ -523,7 +529,8 @@ WERROR cli_reg_enum_key(struct cli_state *cli, TALLOC_CTX *mem_ctx, /**************************************************************************** do a REG Create Value ****************************************************************************/ -WERROR cli_reg_set_val(struct cli_state *cli, TALLOC_CTX *mem_ctx, + +WERROR rpccli_reg_set_val(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, char *val_name, uint32 type, RPC_DATA_BLOB *data) { @@ -536,7 +543,7 @@ WERROR cli_reg_set_val(struct cli_state *cli, TALLOC_CTX *mem_ctx, init_reg_q_set_val(&in, hnd, val_name, type, data); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_SET_VALUE, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_SET_VALUE, in, out, qbuf, rbuf, reg_io_q_set_value, @@ -549,7 +556,8 @@ WERROR cli_reg_set_val(struct cli_state *cli, TALLOC_CTX *mem_ctx, /**************************************************************************** do a REG Enum Value ****************************************************************************/ -WERROR cli_reg_enum_val(struct cli_state *cli, TALLOC_CTX *mem_ctx, + +WERROR rpccli_reg_enum_val(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, int idx, fstring val_name, uint32 *type, REGVAL_BUFFER *value) { @@ -562,7 +570,7 @@ WERROR cli_reg_enum_val(struct cli_state *cli, TALLOC_CTX *mem_ctx, init_reg_q_enum_val(&in, hnd, idx, 0x0100, 0x1000); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_ENUM_VALUE, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_ENUM_VALUE, in, out, qbuf, rbuf, reg_io_q_enum_val, @@ -577,7 +585,7 @@ WERROR cli_reg_enum_val(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT (out); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_ENUM_VALUE, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_ENUM_VALUE, in, out, qbuf, rbuf, reg_io_q_enum_val, @@ -598,7 +606,7 @@ WERROR cli_reg_enum_val(struct cli_state *cli, TALLOC_CTX *mem_ctx, /**************************************************************************** ****************************************************************************/ -WERROR cli_reg_open_entry(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_reg_open_entry(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, char *key_name, uint32 access_desired, POLICY_HND *key_hnd) { @@ -611,7 +619,7 @@ WERROR cli_reg_open_entry(struct cli_state *cli, TALLOC_CTX *mem_ctx, init_reg_q_open_entry(&in, hnd, key_name, access_desired); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_OPEN_ENTRY, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_OPEN_ENTRY, in, out, qbuf, rbuf, reg_io_q_open_entry, @@ -629,7 +637,7 @@ WERROR cli_reg_open_entry(struct cli_state *cli, TALLOC_CTX *mem_ctx, /**************************************************************************** ****************************************************************************/ -WERROR cli_reg_close(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_reg_close(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd) { REG_Q_CLOSE in; @@ -641,7 +649,7 @@ WERROR cli_reg_close(struct cli_state *cli, TALLOC_CTX *mem_ctx, init_reg_q_close(&in, hnd); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_CLOSE, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_CLOSE, in, out, qbuf, rbuf, reg_io_q_close, @@ -654,7 +662,8 @@ WERROR cli_reg_close(struct cli_state *cli, TALLOC_CTX *mem_ctx, /**************************************************************************** do a REG Query Info ****************************************************************************/ -WERROR cli_reg_save_key( struct cli_state *cli, TALLOC_CTX *mem_ctx, + +WERROR rpccli_reg_save_key(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, const char *filename ) { REG_Q_SAVE_KEY in; @@ -666,7 +675,7 @@ WERROR cli_reg_save_key( struct cli_state *cli, TALLOC_CTX *mem_ctx, init_q_reg_save_key( &in, hnd, filename ); - CLI_DO_RPC( cli, mem_ctx, PI_WINREG, REG_SAVE_KEY, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_WINREG, REG_SAVE_KEY, in, out, qbuf, rbuf, reg_io_q_save_key, @@ -720,5 +729,3 @@ BOOL reg_split_hive(const char *full_keyname, uint32 *reg_type, pstring key_name return True; } - - diff --git a/source3/rpc_client/cli_samr.c b/source3/rpc_client/cli_samr.c index 01ec0bd51eb..d68c72e20c8 100644 --- a/source3/rpc_client/cli_samr.c +++ b/source3/rpc_client/cli_samr.c @@ -3,10 +3,8 @@ RPC pipe client Copyright (C) Tim Potter 2000-2001, Copyright (C) Andrew Tridgell 1992-1997,2000, - Copyright (C) Luke Kenneth Casson Leighton 1996-1997,2000, - Copyright (C) Paul Ashton 1997,2000, - Copyright (C) Elrond 2000, Copyright (C) Rafal Szczesniak 2002. + Copyright (C) Jeremy Allison 2005. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -40,24 +38,16 @@ NTSTATUS rpccli_samr_connect(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_connect(&q, cli->cli->desthost, access_mask); - if (!samr_io_q_connect("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, SAMR_CONNECT, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!samr_io_r_connect("", &r, &rbuf, 0)) - goto done; - + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CONNECT, + q, r, + qbuf, rbuf, + samr_io_q_connect, + samr_io_r_connect, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ if (NT_STATUS_IS_OK(result = r.status)) { @@ -67,22 +57,12 @@ NTSTATUS rpccli_samr_connect(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, #endif } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_samr_connect(struct cli_state *cli, TALLOC_CTX *mem_ctx, - uint32 access_mask, POLICY_HND *connect_pol) -{ - return rpccli_samr_connect(&cli->pipes[PI_SAMR], mem_ctx, - access_mask, connect_pol); -} /* Connect to SAMR database */ -NTSTATUS cli_samr_connect4(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_connect4(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 access_mask, POLICY_HND *connect_pol) { prs_struct qbuf, rbuf; @@ -90,28 +70,19 @@ NTSTATUS cli_samr_connect4(struct cli_state *cli, TALLOC_CTX *mem_ctx, SAMR_R_CONNECT4 r; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - DEBUG(10,("cli_samr_connect4 to %s\n", cli->desthost)); - ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ - init_samr_q_connect4(&q, cli->desthost, access_mask); - - if (!samr_io_q_connect4("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_CONNECT4, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ + init_samr_q_connect4(&q, cli->cli->desthost, access_mask); - if (!samr_io_r_connect4("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CONNECT4, + q, r, + qbuf, rbuf, + samr_io_q_connect4, + samr_io_r_connect4, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -122,10 +93,6 @@ NTSTATUS cli_samr_connect4(struct cli_state *cli, TALLOC_CTX *mem_ctx, #endif } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } @@ -144,23 +111,16 @@ NTSTATUS rpccli_samr_close(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_close_hnd(&q, connect_pol); - if (!samr_io_q_close_hnd("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, SAMR_CLOSE_HND, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!samr_io_r_close_hnd("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CLOSE_HND, + q, r, + qbuf, rbuf, + samr_io_q_close_hnd, + samr_io_r_close_hnd, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -171,19 +131,9 @@ NTSTATUS rpccli_samr_close(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, *connect_pol = r.pol; } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_samr_close(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *connect_pol) -{ - return rpccli_samr_close(&cli->pipes[PI_SAMR], mem_ctx, connect_pol); -} - /* Open handle on a domain */ NTSTATUS rpccli_samr_open_domain(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, @@ -201,23 +151,16 @@ NTSTATUS rpccli_samr_open_domain(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ct ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_open_domain(&q, connect_pol, access_mask, domain_sid); - if (!samr_io_q_open_domain("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, SAMR_OPEN_DOMAIN, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!samr_io_r_open_domain("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_OPEN_DOMAIN, + q, r, + qbuf, rbuf, + samr_io_q_open_domain, + samr_io_r_open_domain, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -228,26 +171,9 @@ NTSTATUS rpccli_samr_open_domain(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ct #endif } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -/* Open handle on a user */ - -NTSTATUS cli_samr_open_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *connect_pol, uint32 access_mask, - const DOM_SID *domain_sid, - POLICY_HND *domain_pol) -{ - return rpccli_samr_open_domain(&cli->pipes[PI_SAMR], mem_ctx, - connect_pol, access_mask, domain_sid, - domain_pol); -} - - NTSTATUS rpccli_samr_open_user(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *domain_pol, uint32 access_mask, @@ -263,23 +189,16 @@ NTSTATUS rpccli_samr_open_user(struct rpc_pipe_client *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_open_user(&q, domain_pol, access_mask, user_rid); - if (!samr_io_q_open_user("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, SAMR_OPEN_USER, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!samr_io_r_open_user("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_OPEN_USER, + q, r, + qbuf, rbuf, + samr_io_q_open_user, + samr_io_r_open_user, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -290,22 +209,9 @@ NTSTATUS rpccli_samr_open_user(struct rpc_pipe_client *cli, #endif } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_samr_open_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *domain_pol, uint32 access_mask, - uint32 user_rid, POLICY_HND *user_pol) -{ - return rpccli_samr_open_user(&cli->pipes[PI_SAMR], mem_ctx, domain_pol, - access_mask, user_rid, user_pol); -} - - /* Open handle on a group */ NTSTATUS rpccli_samr_open_group(struct rpc_pipe_client *cli, @@ -323,23 +229,16 @@ NTSTATUS rpccli_samr_open_group(struct rpc_pipe_client *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_open_group(&q, domain_pol, access_mask, group_rid); - if (!samr_io_q_open_group("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, SAMR_OPEN_GROUP, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!samr_io_r_open_group("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_OPEN_GROUP, + q, r, + qbuf, rbuf, + samr_io_q_open_group, + samr_io_r_open_group, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -350,25 +249,12 @@ NTSTATUS rpccli_samr_open_group(struct rpc_pipe_client *cli, #endif } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_samr_open_group(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *domain_pol, uint32 access_mask, - uint32 group_rid, POLICY_HND *group_pol) -{ - return rpccli_samr_open_group(&cli->pipes[PI_SAMR], mem_ctx, - domain_pol, access_mask, group_rid, - group_pol); -} - /* Create domain group */ -NTSTATUS cli_samr_create_dom_group(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_create_dom_group(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *domain_pol, const char *group_name, uint32 access_mask, POLICY_HND *group_pol) @@ -383,23 +269,16 @@ NTSTATUS cli_samr_create_dom_group(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_create_dom_group(&q, domain_pol, group_name, access_mask); - if (!samr_io_q_create_dom_group("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_CREATE_DOM_GROUP, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!samr_io_r_create_dom_group("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CREATE_DOM_GROUP, + q, r, + qbuf, rbuf, + samr_io_q_create_dom_group, + samr_io_r_create_dom_group, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -408,16 +287,12 @@ NTSTATUS cli_samr_create_dom_group(struct cli_state *cli, TALLOC_CTX *mem_ctx, if (NT_STATUS_IS_OK(result)) *group_pol = r.pol; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } /* Add a domain group member */ -NTSTATUS cli_samr_add_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_add_groupmem(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *group_pol, uint32 rid) { prs_struct qbuf, rbuf; @@ -430,38 +305,27 @@ NTSTATUS cli_samr_add_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_add_groupmem(&q, group_pol, rid); - if (!samr_io_q_add_groupmem("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_ADD_GROUPMEM, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!samr_io_r_add_groupmem("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_ADD_GROUPMEM, + q, r, + qbuf, rbuf, + samr_io_q_add_groupmem, + samr_io_r_add_groupmem, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ result = r.status; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } /* Delete a domain group member */ -NTSTATUS cli_samr_del_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_del_groupmem(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *group_pol, uint32 rid) { prs_struct qbuf, rbuf; @@ -474,32 +338,21 @@ NTSTATUS cli_samr_del_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_del_groupmem(&q, group_pol, rid); - if (!samr_io_q_del_groupmem("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_DEL_GROUPMEM, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!samr_io_r_del_groupmem("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_DEL_GROUPMEM, + q, r, + qbuf, rbuf, + samr_io_q_del_groupmem, + samr_io_r_del_groupmem, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ result = r.status; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } @@ -520,47 +373,28 @@ NTSTATUS rpccli_samr_query_userinfo(struct rpc_pipe_client *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_query_userinfo(&q, user_pol, switch_value); - if (!samr_io_q_query_userinfo("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, SAMR_QUERY_USERINFO, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!samr_io_r_query_userinfo("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_USERINFO, + q, r, + qbuf, rbuf, + samr_io_q_query_userinfo, + samr_io_r_query_userinfo, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ result = r.status; *ctr = r.ctr; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_samr_query_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *user_pol, uint16 switch_value, - SAM_USERINFO_CTR **ctr) -{ - return rpccli_samr_query_userinfo(&cli->pipes[PI_SAMR], mem_ctx, - user_pol, switch_value, ctr); -} - /* Set group info */ -NTSTATUS cli_samr_set_groupinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_set_groupinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *group_pol, GROUP_INFO_CTR *ctr) { prs_struct qbuf, rbuf; @@ -573,38 +407,27 @@ NTSTATUS cli_samr_set_groupinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_set_groupinfo(&q, group_pol, ctr); - if (!samr_io_q_set_groupinfo("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_SET_GROUPINFO, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!samr_io_r_set_groupinfo("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_SET_GROUPINFO, + q, r, + qbuf, rbuf, + samr_io_q_set_groupinfo, + samr_io_r_set_groupinfo, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ result = r.status; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } /* Query group info */ -NTSTATUS cli_samr_query_groupinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_query_groupinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *group_pol, uint32 info_level, GROUP_INFO_CTR **ctr) { @@ -618,23 +441,16 @@ NTSTATUS cli_samr_query_groupinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_query_groupinfo(&q, group_pol, info_level); - if (!samr_io_q_query_groupinfo("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_QUERY_GROUPINFO, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!samr_io_r_query_groupinfo("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_GROUPINFO, + q, r, + qbuf, rbuf, + samr_io_q_query_groupinfo, + samr_io_r_query_groupinfo, + NT_STATUS_UNSUCCESSFUL); *ctr = r.ctr; @@ -642,10 +458,6 @@ NTSTATUS cli_samr_query_groupinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, result = r.status; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } @@ -667,23 +479,16 @@ NTSTATUS rpccli_samr_query_usergroups(struct rpc_pipe_client *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_query_usergroups(&q, user_pol); - if (!samr_io_q_query_usergroups("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, SAMR_QUERY_USERGROUPS, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!samr_io_r_query_usergroups("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_USERGROUPS, + q, r, + qbuf, rbuf, + samr_io_q_query_usergroups, + samr_io_r_query_usergroups, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -692,24 +497,12 @@ NTSTATUS rpccli_samr_query_usergroups(struct rpc_pipe_client *cli, *gid = r.gid; } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_samr_query_usergroups(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *user_pol, uint32 *num_groups, - DOM_GID **gid) -{ - return rpccli_samr_query_usergroups(&cli->pipes[PI_SAMR], mem_ctx, - user_pol, num_groups, gid); -} - /* Set alias info */ -NTSTATUS cli_samr_set_aliasinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_set_aliasinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *alias_pol, ALIAS_INFO_CTR *ctr) { prs_struct qbuf, rbuf; @@ -722,32 +515,21 @@ NTSTATUS cli_samr_set_aliasinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_set_aliasinfo(&q, alias_pol, ctr); - if (!samr_io_q_set_aliasinfo("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_SET_ALIASINFO, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!samr_io_r_set_aliasinfo("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_SET_ALIASINFO, + q, r, + qbuf, rbuf, + samr_io_q_set_aliasinfo, + samr_io_r_set_aliasinfo, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ result = r.status; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } @@ -771,11 +553,6 @@ NTSTATUS rpccli_samr_query_useraliases(struct rpc_pipe_client *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - sid_ptrs = TALLOC_ARRAY(mem_ctx, uint32, num_sids); if (sid_ptrs == NULL) return NT_STATUS_NO_MEMORY; @@ -787,14 +564,12 @@ NTSTATUS rpccli_samr_query_useraliases(struct rpc_pipe_client *cli, init_samr_q_query_useraliases(&q, dom_pol, num_sids, sid_ptrs, sid); - if (!samr_io_q_query_useraliases("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, SAMR_QUERY_USERALIASES, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!samr_io_r_query_useraliases("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_USERALIASES, + q, r, + qbuf, rbuf, + samr_io_q_query_useraliases, + samr_io_r_query_useraliases, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -803,25 +578,9 @@ NTSTATUS rpccli_samr_query_useraliases(struct rpc_pipe_client *cli, *als_rids = r.rid; } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_samr_query_useraliases(struct cli_state *cli, - TALLOC_CTX *mem_ctx, - POLICY_HND *dom_pol, uint32 num_sids, - DOM_SID2 *sid, - uint32 *num_aliases, uint32 **als_rids) -{ - return rpccli_samr_query_useraliases(&cli->pipes[PI_SAMR], mem_ctx, - dom_pol, num_sids, sid, - num_aliases, als_rids); -} - - /* Query user groups */ NTSTATUS rpccli_samr_query_groupmem(struct rpc_pipe_client *cli, @@ -839,23 +598,16 @@ NTSTATUS rpccli_samr_query_groupmem(struct rpc_pipe_client *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_query_groupmem(&q, group_pol); - if (!samr_io_q_query_groupmem("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, SAMR_QUERY_GROUPMEM, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!samr_io_r_query_groupmem("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_GROUPMEM, + q, r, + qbuf, rbuf, + samr_io_q_query_groupmem, + samr_io_r_query_groupmem, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -865,22 +617,9 @@ NTSTATUS rpccli_samr_query_groupmem(struct rpc_pipe_client *cli, *attr = r.attr; } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_samr_query_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *group_pol, uint32 *num_mem, - uint32 **rid, uint32 **attr) -{ - return rpccli_samr_query_groupmem(&cli->pipes[PI_SAMR], mem_ctx, - group_pol, num_mem, rid, attr); -} - - /** * Enumerate domain users * @@ -898,7 +637,8 @@ NTSTATUS cli_samr_query_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, * * @return NTSTATUS returned in rpc response **/ -NTSTATUS cli_samr_enum_dom_users(struct cli_state *cli, TALLOC_CTX *mem_ctx, + +NTSTATUS rpccli_samr_enum_dom_users(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint32 *start_idx, uint16 acb_mask, uint32 size, char ***dom_users, uint32 **rids, uint32 *num_dom_users) @@ -918,25 +658,17 @@ NTSTATUS cli_samr_enum_dom_users(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* always init this */ *num_dom_users = 0; - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Fill query structure with parameters */ init_samr_q_enum_dom_users(&q, pol, *start_idx, acb_mask, 0, size); - if (!samr_io_q_enum_dom_users("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_ENUM_DOM_USERS, &qbuf, &rbuf)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_ENUM_DOM_USERS, + q, r, + qbuf, rbuf, + samr_io_q_enum_dom_users, + samr_io_r_enum_dom_users, + NT_STATUS_UNSUCCESSFUL); - /* unpack received stream */ - - if(!samr_io_r_enum_dom_users("", &r, &rbuf, 0)) - goto done; - result = r.status; if (!NT_STATUS_IS_OK(result) && @@ -971,9 +703,6 @@ NTSTATUS cli_samr_enum_dom_users(struct cli_state *cli, TALLOC_CTX *mem_ctx, } done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } @@ -996,23 +725,16 @@ NTSTATUS rpccli_samr_enum_dom_groups(struct rpc_pipe_client *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_enum_dom_groups(&q, pol, *start_idx, size); - if (!samr_io_q_enum_dom_groups("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, SAMR_ENUM_DOM_GROUPS, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!samr_io_r_enum_dom_groups("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_ENUM_DOM_GROUPS, + q, r, + qbuf, rbuf, + samr_io_q_enum_dom_groups, + samr_io_r_enum_dom_groups, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -1051,22 +773,9 @@ NTSTATUS rpccli_samr_enum_dom_groups(struct rpc_pipe_client *cli, } done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_samr_enum_dom_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *pol, uint32 *start_idx, - uint32 size, struct acct_info **dom_groups, - uint32 *num_dom_groups) -{ - return rpccli_samr_enum_dom_groups(&cli->pipes[PI_SAMR], mem_ctx, - pol, start_idx, size, dom_groups, - num_dom_groups); -} - /* Enumerate domain groups */ NTSTATUS rpccli_samr_enum_als_groups(struct rpc_pipe_client *cli, @@ -1086,25 +795,16 @@ NTSTATUS rpccli_samr_enum_als_groups(struct rpc_pipe_client *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_enum_dom_aliases(&q, pol, *start_idx, size); - if (!samr_io_q_enum_dom_aliases("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, SAMR_ENUM_DOM_ALIASES, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!samr_io_r_enum_dom_aliases("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_ENUM_DOM_ALIASES, + q, r, + qbuf, rbuf, + samr_io_q_enum_dom_aliases, + samr_io_r_enum_dom_aliases, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -1144,27 +844,15 @@ NTSTATUS rpccli_samr_enum_als_groups(struct rpc_pipe_client *cli, } done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_samr_enum_als_groups(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *pol, uint32 *start_idx, - uint32 size, struct acct_info **dom_aliases, - uint32 *num_dom_aliases) -{ - return rpccli_samr_enum_als_groups(&cli->pipes[PI_SAMR], mem_ctx, - pol, start_idx, size, dom_aliases, - num_dom_aliases); -} - /* Query alias members */ -NTSTATUS cli_samr_query_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *alias_pol, uint32 *num_mem, - DOM_SID **sids) +NTSTATUS rpccli_samr_query_aliasmem(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + POLICY_HND *alias_pol, uint32 *num_mem, + DOM_SID **sids) { prs_struct qbuf, rbuf; SAMR_Q_QUERY_ALIASMEM q; @@ -1177,25 +865,16 @@ NTSTATUS cli_samr_query_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_query_aliasmem(&q, alias_pol); - if (!samr_io_q_query_aliasmem("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_QUERY_ALIASMEM, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!samr_io_r_query_aliasmem("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_ALIASMEM, + q, r, + qbuf, rbuf, + samr_io_q_query_aliasmem, + samr_io_r_query_aliasmem, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -1221,17 +900,15 @@ NTSTATUS cli_samr_query_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, } done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } /* Open handle on an alias */ -NTSTATUS cli_samr_open_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *domain_pol, uint32 access_mask, - uint32 alias_rid, POLICY_HND *alias_pol) +NTSTATUS rpccli_samr_open_alias(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, + POLICY_HND *domain_pol, uint32 access_mask, + uint32 alias_rid, POLICY_HND *alias_pol) { prs_struct qbuf, rbuf; SAMR_Q_OPEN_ALIAS q; @@ -1243,27 +920,16 @@ NTSTATUS cli_samr_open_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_open_alias(&q, domain_pol, access_mask, alias_rid); - if (!samr_io_q_open_alias("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_OPEN_ALIAS, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!samr_io_r_open_alias("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_OPEN_ALIAS, + q, r, + qbuf, rbuf, + samr_io_q_open_alias, + samr_io_r_open_alias, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -1274,16 +940,12 @@ NTSTATUS cli_samr_open_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, #endif } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } /* Create an alias */ -NTSTATUS cli_samr_create_dom_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_create_dom_alias(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *domain_pol, const char *name, POLICY_HND *alias_pol) { @@ -1297,27 +959,16 @@ NTSTATUS cli_samr_create_dom_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_create_dom_alias(&q, domain_pol, name); - if (!samr_io_q_create_dom_alias("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_CREATE_DOM_ALIAS, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!samr_io_r_create_dom_alias("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CREATE_DOM_ALIAS, + q, r, + qbuf, rbuf, + samr_io_q_create_dom_alias, + samr_io_r_create_dom_alias, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -1325,16 +976,12 @@ NTSTATUS cli_samr_create_dom_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, *alias_pol = r.alias_pol; } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } /* Add an alias member */ -NTSTATUS cli_samr_add_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_add_aliasmem(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *alias_pol, DOM_SID *member) { prs_struct qbuf, rbuf; @@ -1347,40 +994,25 @@ NTSTATUS cli_samr_add_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_add_aliasmem(&q, alias_pol, member); - if (!samr_io_q_add_aliasmem("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_ADD_ALIASMEM, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!samr_io_r_add_aliasmem("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_ADD_ALIASMEM, + q, r, + qbuf, rbuf, + samr_io_q_add_aliasmem, + samr_io_r_add_aliasmem, + NT_STATUS_UNSUCCESSFUL); result = r.status; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } /* Delete an alias member */ -NTSTATUS cli_samr_del_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_del_aliasmem(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *alias_pol, DOM_SID *member) { prs_struct qbuf, rbuf; @@ -1393,40 +1025,25 @@ NTSTATUS cli_samr_del_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_del_aliasmem(&q, alias_pol, member); - if (!samr_io_q_del_aliasmem("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_DEL_ALIASMEM, &qbuf, &rbuf)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } - - /* Unmarshall response */ - - if (!samr_io_r_del_aliasmem("", &r, &rbuf, 0)) { - result = NT_STATUS_UNSUCCESSFUL; - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_DEL_ALIASMEM, + q, r, + qbuf, rbuf, + samr_io_q_del_aliasmem, + samr_io_r_del_aliasmem, + NT_STATUS_UNSUCCESSFUL); result = r.status; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } /* Query alias info */ -NTSTATUS cli_samr_query_alias_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_query_alias_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *alias_pol, uint16 switch_value, ALIAS_INFO_CTR *ctr) { @@ -1440,25 +1057,16 @@ NTSTATUS cli_samr_query_alias_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_query_aliasinfo(&q, alias_pol, switch_value); - if (!samr_io_q_query_aliasinfo("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_QUERY_ALIASINFO, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!samr_io_r_query_aliasinfo("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_ALIASINFO, + q, r, + qbuf, rbuf, + samr_io_q_query_aliasinfo, + samr_io_r_query_aliasinfo, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -1468,9 +1076,7 @@ NTSTATUS cli_samr_query_alias_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, *ctr = *r.ctr; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); + done: return result; } @@ -1493,27 +1099,18 @@ NTSTATUS rpccli_samr_query_dom_info(struct rpc_pipe_client *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_query_dom_info(&q, domain_pol, switch_value); - if (!samr_io_q_query_dom_info("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, SAMR_QUERY_DOMAIN_INFO, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - r.ctr = ctr; - if (!samr_io_r_query_dom_info("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_DOMAIN_INFO, + q, r, + qbuf, rbuf, + samr_io_q_query_dom_info, + samr_io_r_query_dom_info, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -1522,20 +1119,10 @@ NTSTATUS rpccli_samr_query_dom_info(struct rpc_pipe_client *cli, } done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } -NTSTATUS cli_samr_query_dom_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *domain_pol, uint16 switch_value, - SAM_UNK_CTR *ctr) -{ - return rpccli_samr_query_dom_info(&cli->pipes[PI_SAMR], mem_ctx, - domain_pol, switch_value, ctr); -} - /* User change password */ NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli, @@ -1559,7 +1146,9 @@ NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli, uchar new_nt_hash[16]; uchar new_lanman_hash[16]; - DEBUG(10,("cli_samr_query_dom_info\n")); + char *srv_name_slash = talloc_asprintf(mem_ctx, "\\\\%s", cli->cli->desthost); + + DEBUG(10,("rpccli_samr_chgpasswd_user\n")); ZERO_STRUCT(q); ZERO_STRUCT(r); @@ -1590,29 +1179,20 @@ NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli, SamOEMhash( new_nt_password, old_nt_hash, 516); E_old_pw_hash( new_nt_hash, old_nt_hash, old_nt_hash_enc); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ - init_samr_q_chgpasswd_user(&q, cli->cli->srv_name_slash, username, + init_samr_q_chgpasswd_user(&q, srv_name_slash, username, new_nt_password, old_nt_hash_enc, new_lm_password, old_lanman_hash_enc); - if (!samr_io_q_chgpasswd_user("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, SAMR_CHGPASSWD_USER, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!samr_io_r_chgpasswd_user("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CHGPASSWD_USER, + q, r, + qbuf, rbuf, + samr_io_q_chgpasswd_user, + samr_io_r_chgpasswd_user, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -1621,21 +1201,10 @@ NTSTATUS rpccli_samr_chgpasswd_user(struct rpc_pipe_client *cli, } done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } -NTSTATUS cli_samr_chgpasswd_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, - const char *username, - const char *newpassword, - const char *oldpassword ) -{ - return rpccli_samr_chgpasswd_user(&cli->pipes[PI_SAMR], mem_ctx, - username, newpassword, oldpassword); -} - /* This function returns the bizzare set of (max_entries, max_size) required for the QueryDisplayInfo RPC to actually work against a domain controller with large (10k and higher) numbers of users. These values were @@ -1689,28 +1258,19 @@ NTSTATUS rpccli_samr_query_dispinfo(struct rpc_pipe_client *cli, *num_entries = 0; - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_query_dispinfo(&q, domain_pol, switch_value, *start_idx, max_entries, max_size); - if (!samr_io_q_query_dispinfo("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, SAMR_QUERY_DISPINFO, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - r.ctr = ctr; - if (!samr_io_r_query_dispinfo("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_DISPINFO, + q, r, + qbuf, rbuf, + samr_io_q_query_dispinfo, + samr_io_r_query_dispinfo, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -1725,23 +1285,9 @@ NTSTATUS rpccli_samr_query_dispinfo(struct rpc_pipe_client *cli, *start_idx += r.num_entries; /* No next_idx in this structure! */ done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -NTSTATUS cli_samr_query_dispinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *domain_pol, uint32 *start_idx, - uint16 switch_value, uint32 *num_entries, - uint32 max_entries, uint32 max_size, - SAM_DISPINFO_CTR *ctr) -{ - return rpccli_samr_query_dispinfo(&cli->pipes[PI_SAMR], mem_ctx, - domain_pol, start_idx, switch_value, - num_entries, max_entries, max_size, ctr); -} - /* Lookup rids. Note that NT4 seems to crash if more than ~1000 rids are looked up in one packet. */ @@ -1768,25 +1314,16 @@ NTSTATUS rpccli_samr_lookup_rids(struct rpc_pipe_client *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_lookup_rids(mem_ctx, &q, domain_pol, 1000, num_rids, rids); - if (!samr_io_q_lookup_rids("", &q, &qbuf, 0) || - !rpc_api_pipe_req_int(cli, SAMR_LOOKUP_RIDS, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!samr_io_r_lookup_rids("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_LOOKUP_RIDS, + q, r, + qbuf, rbuf, + samr_io_q_lookup_rids, + samr_io_r_lookup_rids, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -1815,26 +1352,13 @@ NTSTATUS rpccli_samr_lookup_rids(struct rpc_pipe_client *cli, } done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } -NTSTATUS cli_samr_lookup_rids(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *domain_pol, - uint32 num_rids, uint32 *rids, - uint32 *num_names, char ***names, - uint32 **name_types) -{ - return rpccli_samr_lookup_rids(&cli->pipes[PI_SAMR], mem_ctx, - domain_pol, num_rids, rids, - num_names, names, name_types); -} - /* Lookup names */ -NTSTATUS cli_samr_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_lookup_names(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *domain_pol, uint32 flags, uint32 num_names, const char **names, uint32 *num_rids, uint32 **rids, @@ -1851,26 +1375,17 @@ NTSTATUS cli_samr_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_lookup_names(mem_ctx, &q, domain_pol, flags, num_names, names); - if (!samr_io_q_lookup_names("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_LOOKUP_NAMES, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!samr_io_r_lookup_names("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_LOOKUP_NAMES, + q, r, + qbuf, rbuf, + samr_io_q_lookup_names, + samr_io_r_lookup_names, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -1893,15 +1408,13 @@ NTSTATUS cli_samr_lookup_names(struct cli_state *cli, TALLOC_CTX *mem_ctx, } done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } /* Create a domain user */ -NTSTATUS cli_samr_create_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_create_dom_user(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *domain_pol, const char *acct_name, uint32 acb_info, uint32 unknown, POLICY_HND *user_pol, uint32 *rid) @@ -1916,25 +1429,16 @@ NTSTATUS cli_samr_create_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_create_user(&q, domain_pol, acct_name, acb_info, unknown); - if (!samr_io_q_create_user("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_CREATE_USER, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!samr_io_r_create_user("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_CREATE_USER, + q, r, + qbuf, rbuf, + samr_io_q_create_user, + samr_io_r_create_user, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -1949,15 +1453,13 @@ NTSTATUS cli_samr_create_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, *rid = r.user_rid; done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } /* Set userinfo */ -NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_set_userinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *user_pol, uint16 switch_value, DATA_BLOB *sess_key, SAM_USERINFO_CTR *ctr) { @@ -1978,7 +1480,7 @@ NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Initialise parse structures */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); + prs_init(&qbuf, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); /* Marshall data and send request */ @@ -1988,16 +1490,12 @@ NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, init_samr_q_set_userinfo(&q, user_pol, sess_key, switch_value, ctr->info.id); - if (!samr_io_q_set_userinfo("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_SET_USERINFO, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!samr_io_r_set_userinfo("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_SET_USERINFO, + q, r, + qbuf, rbuf, + samr_io_q_set_userinfo, + samr_io_r_set_userinfo, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -2006,15 +1504,13 @@ NTSTATUS cli_samr_set_userinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, } done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } /* Set userinfo2 */ -NTSTATUS cli_samr_set_userinfo2(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_set_userinfo2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *user_pol, uint16 switch_value, DATA_BLOB *sess_key, SAM_USERINFO_CTR *ctr) { @@ -2033,25 +1529,16 @@ NTSTATUS cli_samr_set_userinfo2(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_set_userinfo2(&q, user_pol, sess_key, switch_value, ctr); - if (!samr_io_q_set_userinfo2("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_SET_USERINFO2, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!samr_io_r_set_userinfo2("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_SET_USERINFO2, + q, r, + qbuf, rbuf, + samr_io_q_set_userinfo2, + samr_io_r_set_userinfo2, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -2060,15 +1547,13 @@ NTSTATUS cli_samr_set_userinfo2(struct cli_state *cli, TALLOC_CTX *mem_ctx, } done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } /* Delete domain group */ -NTSTATUS cli_samr_delete_dom_group(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_delete_dom_group(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *group_pol) { prs_struct qbuf, rbuf; @@ -2081,40 +1566,27 @@ NTSTATUS cli_samr_delete_dom_group(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_delete_dom_group(&q, group_pol); - if (!samr_io_q_delete_dom_group("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_DELETE_DOM_GROUP, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!samr_io_r_delete_dom_group("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_DELETE_DOM_GROUP, + q, r, + qbuf, rbuf, + samr_io_q_delete_dom_group, + samr_io_r_delete_dom_group, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ result = r.status; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } /* Delete domain alias */ -NTSTATUS cli_samr_delete_dom_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_delete_dom_alias(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *alias_pol) { prs_struct qbuf, rbuf; @@ -2127,40 +1599,27 @@ NTSTATUS cli_samr_delete_dom_alias(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_delete_dom_alias(&q, alias_pol); - if (!samr_io_q_delete_dom_alias("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_DELETE_DOM_ALIAS, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!samr_io_r_delete_dom_alias("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_DELETE_DOM_ALIAS, + q, r, + qbuf, rbuf, + samr_io_q_delete_dom_alias, + samr_io_r_delete_dom_alias, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ result = r.status; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } /* Delete domain user */ -NTSTATUS cli_samr_delete_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_delete_dom_user(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *user_pol) { prs_struct qbuf, rbuf; @@ -2173,40 +1632,27 @@ NTSTATUS cli_samr_delete_dom_user(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_delete_dom_user(&q, user_pol); - if (!samr_io_q_delete_dom_user("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_DELETE_DOM_USER, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!samr_io_r_delete_dom_user("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_DELETE_DOM_USER, + q, r, + qbuf, rbuf, + samr_io_q_delete_dom_user, + samr_io_r_delete_dom_user, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ result = r.status; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } /* Remove foreign SID */ -NTSTATUS cli_samr_remove_sid_foreign_domain(struct cli_state *cli, +NTSTATUS rpccli_samr_remove_sid_foreign_domain(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *user_pol, DOM_SID *sid) @@ -2221,40 +1667,27 @@ NTSTATUS cli_samr_remove_sid_foreign_domain(struct cli_state *cli, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_remove_sid_foreign_domain(&q, user_pol, sid); - if (!samr_io_q_remove_sid_foreign_domain("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_REMOVE_SID_FOREIGN_DOMAIN, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!samr_io_r_remove_sid_foreign_domain("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_REMOVE_SID_FOREIGN_DOMAIN, + q, r, + qbuf, rbuf, + samr_io_q_remove_sid_foreign_domain, + samr_io_r_remove_sid_foreign_domain, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ result = r.status; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } /* Query user security object */ -NTSTATUS cli_samr_query_sec_obj(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_query_sec_obj(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *user_pol, uint16 switch_value, TALLOC_CTX *ctx, SEC_DESC_BUF **sec_desc_buf) { @@ -2268,41 +1701,28 @@ NTSTATUS cli_samr_query_sec_obj(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_query_sec_obj(&q, user_pol, switch_value); - if (!samr_io_q_query_sec_obj("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_QUERY_SEC_OBJECT, &qbuf, &rbuf)) { - goto done; - } - - /* Unmarshall response */ - - if (!samr_io_r_query_sec_obj("", &r, &rbuf, 0)) { - goto done; - } + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_QUERY_SEC_OBJECT, + q, r, + qbuf, rbuf, + samr_io_q_query_sec_obj, + samr_io_r_query_sec_obj, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ result = r.status; *sec_desc_buf=dup_sec_desc_buf(ctx, r.buf); - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } /* Get domain password info */ -NTSTATUS cli_samr_get_dom_pwinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_get_dom_pwinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint16 *unk_0, uint16 *unk_1) { prs_struct qbuf, rbuf; @@ -2315,23 +1735,16 @@ NTSTATUS cli_samr_get_dom_pwinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ - init_samr_q_get_dom_pwinfo(&q, cli->desthost); - - if (!samr_io_q_get_dom_pwinfo("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_GET_DOM_PWINFO, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ + init_samr_q_get_dom_pwinfo(&q, cli->cli->desthost); - if (!samr_io_r_get_dom_pwinfo("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_GET_DOM_PWINFO, + q, r, + qbuf, rbuf, + samr_io_q_get_dom_pwinfo, + samr_io_r_get_dom_pwinfo, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -2344,16 +1757,12 @@ NTSTATUS cli_samr_get_dom_pwinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, *unk_1 = r.unk_1; } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } /* Lookup Domain Name */ -NTSTATUS cli_samr_lookup_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_samr_lookup_domain(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *user_pol, char *domain_name, DOM_SID *sid) { @@ -2367,23 +1776,16 @@ NTSTATUS cli_samr_lookup_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ init_samr_q_lookup_domain(&q, user_pol, domain_name); - if (!samr_io_q_lookup_domain("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SAMR, SAMR_LOOKUP_DOMAIN, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!samr_io_r_lookup_domain("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC(cli, mem_ctx, PI_SAMR, SAMR_LOOKUP_DOMAIN, + q, r, + qbuf, rbuf, + samr_io_q_lookup_domain, + samr_io_r_lookup_domain, + NT_STATUS_UNSUCCESSFUL); /* Return output parameters */ @@ -2392,9 +1794,5 @@ NTSTATUS cli_samr_lookup_domain(struct cli_state *cli, TALLOC_CTX *mem_ctx, if (NT_STATUS_IS_OK(result)) sid_copy(sid, &r.dom_sid.sid); - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } diff --git a/source3/rpc_client/cli_shutdown.c b/source3/rpc_client/cli_shutdown.c index c342f255a9f..c06586e98ab 100644 --- a/source3/rpc_client/cli_shutdown.c +++ b/source3/rpc_client/cli_shutdown.c @@ -3,10 +3,7 @@ RPC Pipe client Copyright (C) Andrew Tridgell 1992-1998, - Copyright (C) Luke Kenneth Casson Leighton 1996-1998, - Copyright (C) Paul Ashton 1997-1998. - Copyright (C) Jeremy Allison 1999, - Copyright (C) Simo Sorce 2001, + Largely rewritten by Jeremy Allison (C) 2005. Copyright (C) Jim McDonough (jmcd@us.ibm.com) 2003. This program is free software; you can redistribute it and/or modify @@ -28,119 +25,95 @@ /* Shutdown a server */ -NTSTATUS cli_shutdown_init(struct cli_state * cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_shutdown_init(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *msg, uint32 timeout, BOOL do_reboot, BOOL force) { prs_struct qbuf; prs_struct rbuf; - SHUTDOWN_Q_INIT q_s; - SHUTDOWN_R_INIT r_s; + SHUTDOWN_Q_INIT q; + SHUTDOWN_R_INIT r; WERROR result = WERR_GENERAL_FAILURE; if (msg == NULL) return NT_STATUS_INVALID_PARAMETER; - ZERO_STRUCT (q_s); - ZERO_STRUCT (r_s); - - prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + ZERO_STRUCT (q); + ZERO_STRUCT (r); /* Marshall data and send request */ - init_shutdown_q_init(&q_s, msg, timeout, do_reboot, force); - - if (!shutdown_io_q_init("", &q_s, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SHUTDOWN, SHUTDOWN_INIT, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if(shutdown_io_r_init("", &r_s, &rbuf, 0)) - result = r_s.status; + init_shutdown_q_init(&q, msg, timeout, do_reboot, force); -done: - prs_mem_free(&rbuf); - prs_mem_free(&qbuf); + CLI_DO_RPC(cli, mem_ctx, PI_SHUTDOWN, SHUTDOWN_INIT, + q, r, + qbuf, rbuf, + shutdown_io_q_init, + shutdown_io_r_init, + NT_STATUS_UNSUCCESSFUL); + result = r.status; return werror_to_ntstatus(result); } /* Shutdown a server */ -NTSTATUS cli_shutdown_init_ex(struct cli_state * cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_shutdown_init_ex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *msg, uint32 timeout, BOOL do_reboot, BOOL force, uint32 reason) { prs_struct qbuf; prs_struct rbuf; - SHUTDOWN_Q_INIT_EX q_s; - SHUTDOWN_R_INIT_EX r_s; + SHUTDOWN_Q_INIT_EX q; + SHUTDOWN_R_INIT_EX r; WERROR result = WERR_GENERAL_FAILURE; if (msg == NULL) return NT_STATUS_INVALID_PARAMETER; - ZERO_STRUCT (q_s); - ZERO_STRUCT (r_s); - - prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); + ZERO_STRUCT (q); + ZERO_STRUCT (r); /* Marshall data and send request */ - init_shutdown_q_init_ex(&q_s, msg, timeout, do_reboot, force, reason); + init_shutdown_q_init_ex(&q, msg, timeout, do_reboot, force, reason); - if (!shutdown_io_q_init_ex("", &q_s, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SHUTDOWN, SHUTDOWN_INIT_EX, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if(shutdown_io_r_init_ex("", &r_s, &rbuf, 0)) - result = r_s.status; - -done: - prs_mem_free(&rbuf); - prs_mem_free(&qbuf); + CLI_DO_RPC(cli, mem_ctx, PI_SHUTDOWN, SHUTDOWN_INIT_EX, + q, r, + qbuf, rbuf, + shutdown_io_q_init_ex, + shutdown_io_r_init_ex, + NT_STATUS_UNSUCCESSFUL); + result = r.status; return werror_to_ntstatus(result); } /* Abort a server shutdown */ -NTSTATUS cli_shutdown_abort(struct cli_state * cli, TALLOC_CTX *mem_ctx) +NTSTATUS rpccli_shutdown_abort(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx) { prs_struct rbuf; prs_struct qbuf; - SHUTDOWN_Q_ABORT q_s; - SHUTDOWN_R_ABORT r_s; + SHUTDOWN_Q_ABORT q; + SHUTDOWN_R_ABORT r; WERROR result = WERR_GENERAL_FAILURE; - ZERO_STRUCT (q_s); - ZERO_STRUCT (r_s); + ZERO_STRUCT (q); + ZERO_STRUCT (r); - prs_init(&qbuf , MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Marshall data and send request */ - init_shutdown_q_abort(&q_s); - - if (!shutdown_io_q_abort("", &q_s, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SHUTDOWN, SHUTDOWN_ABORT, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (shutdown_io_r_abort("", &r_s, &rbuf, 0)) - result = r_s.status; + init_shutdown_q_abort(&q); -done: - prs_mem_free(&rbuf); - prs_mem_free(&qbuf ); + CLI_DO_RPC(cli, mem_ctx, PI_SHUTDOWN, SHUTDOWN_ABORT, + q, r, + qbuf, rbuf, + shutdown_io_q_abort, + shutdown_io_r_abort, + NT_STATUS_UNSUCCESSFUL); + result = r.status; return werror_to_ntstatus(result); } diff --git a/source3/rpc_client/cli_spoolss.c b/source3/rpc_client/cli_spoolss.c index 271382b71fe..4322bacfc87 100644 --- a/source3/rpc_client/cli_spoolss.c +++ b/source3/rpc_client/cli_spoolss.c @@ -5,8 +5,8 @@ Copyright (C) Gerald Carter 2001-2005, Copyright (C) Tim Potter 2000-2002, Copyright (C) Andrew Tridgell 1994-2000, - Copyright (C) Luke Kenneth Casson Leighton 1996-2000, Copyright (C) Jean-Francois Micouleau 1999-2000. + Copyright (C) Jeremy Allison 2005. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -301,7 +301,7 @@ static void decode_forms_1(TALLOC_CTX *mem_ctx, RPC_BUFFER *buffer, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_open_printer_ex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *printername, const char *datatype, uint32 access_required, const char *station, const char *username, POLICY_HND *pol) { @@ -315,7 +315,7 @@ WERROR cli_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_open_printer_ex( &in, printername, datatype, access_required, station, username ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_OPENPRINTEREX, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_OPENPRINTEREX, in, out, qbuf, rbuf, spoolss_io_q_open_printer_ex, @@ -330,7 +330,7 @@ WERROR cli_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_close_printer(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol) { prs_struct qbuf, rbuf; @@ -342,7 +342,7 @@ WERROR cli_spoolss_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_closeprinter( &in, pol ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_CLOSEPRINTER, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_CLOSEPRINTER, in, out, qbuf, rbuf, spoolss_io_q_closeprinter, @@ -355,7 +355,7 @@ WERROR cli_spoolss_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_enum_printers(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, char *name, uint32 flags, uint32 level, uint32 *num_printers, PRINTER_INFO_CTR *ctr) { @@ -372,7 +372,7 @@ WERROR cli_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx, rpcbuf_init(&buffer, offered, mem_ctx); make_spoolss_q_enumprinters( &in, flags, name, level, &buffer, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERS, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERS, in, out, qbuf, rbuf, spoolss_io_q_enumprinters, @@ -388,7 +388,7 @@ WERROR cli_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx, rpcbuf_init(&buffer, offered, mem_ctx); make_spoolss_q_enumprinters( &in, flags, name, level, &buffer, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERS, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERS, in, out, qbuf, rbuf, spoolss_io_q_enumprinters, @@ -422,7 +422,7 @@ WERROR cli_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_enum_ports(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_enum_ports(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 level, uint32 *num_ports, PORT_INFO_CTR *ctr) { prs_struct qbuf, rbuf; @@ -435,14 +435,14 @@ WERROR cli_spoolss_enum_ports(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(in); ZERO_STRUCT(out); - slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); strupper_m(server); offered = 0; rpcbuf_init(&buffer, offered, mem_ctx); make_spoolss_q_enumports( &in, server, level, &buffer, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPORTS, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPORTS, in, out, qbuf, rbuf, spoolss_io_q_enumports, @@ -458,7 +458,7 @@ WERROR cli_spoolss_enum_ports(struct cli_state *cli, TALLOC_CTX *mem_ctx, rpcbuf_init(&buffer, offered, mem_ctx); make_spoolss_q_enumports( &in, server, level, &buffer, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPORTS, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPORTS, in, out, qbuf, rbuf, spoolss_io_q_enumports, @@ -486,7 +486,7 @@ WERROR cli_spoolss_enum_ports(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_getprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint32 level, PRINTER_INFO_CTR *ctr) { @@ -505,7 +505,7 @@ WERROR cli_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, rpcbuf_init(&buffer, offered, mem_ctx); make_spoolss_q_getprinter( mem_ctx, &in, pol, level, &buffer, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTER, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTER, in, out, qbuf, rbuf, spoolss_io_q_getprinter, @@ -521,7 +521,7 @@ WERROR cli_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, rpcbuf_init(&buffer, offered, mem_ctx); make_spoolss_q_getprinter( mem_ctx, &in, pol, level, &buffer, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTER, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTER, in, out, qbuf, rbuf, spoolss_io_q_getprinter, @@ -556,7 +556,7 @@ WERROR cli_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_setprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_setprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint32 level, PRINTER_INFO_CTR *ctr, uint32 command) { @@ -569,7 +569,7 @@ WERROR cli_spoolss_setprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_setprinter( mem_ctx, &in, pol, level, ctr, command ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETPRINTER, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETPRINTER, in, out, qbuf, rbuf, spoolss_io_q_setprinter, @@ -582,7 +582,7 @@ WERROR cli_spoolss_setprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_getprinterdriver(struct cli_state *cli, +WERROR rpccli_spoolss_getprinterdriver(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint32 level, const char *env, int version, PRINTER_DRIVER_CTR *ctr) @@ -597,7 +597,7 @@ WERROR cli_spoolss_getprinterdriver(struct cli_state *cli, ZERO_STRUCT(in); ZERO_STRUCT(out); - fstrcpy(server, cli->desthost); + fstrcpy(server, cli->cli->desthost); strupper_m(server); offered = 0; @@ -605,7 +605,7 @@ WERROR cli_spoolss_getprinterdriver(struct cli_state *cli, make_spoolss_q_getprinterdriver2( &in, pol, env, level, version, 2, &buffer, offered); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDRIVER2, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDRIVER2, in, out, qbuf, rbuf, spoolss_io_q_getprinterdriver2, @@ -622,7 +622,7 @@ WERROR cli_spoolss_getprinterdriver(struct cli_state *cli, make_spoolss_q_getprinterdriver2( &in, pol, env, level, version, 2, &buffer, offered); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDRIVER2, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDRIVER2, in, out, qbuf, rbuf, spoolss_io_q_getprinterdriver2, @@ -651,7 +651,7 @@ WERROR cli_spoolss_getprinterdriver(struct cli_state *cli, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_enumprinterdrivers (struct cli_state *cli, +WERROR rpccli_spoolss_enumprinterdrivers (struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 level, const char *env, uint32 *num_drivers, @@ -667,7 +667,7 @@ WERROR cli_spoolss_enumprinterdrivers (struct cli_state *cli, ZERO_STRUCT(in); ZERO_STRUCT(out); - slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); strupper_m(server); offered = 0; @@ -675,7 +675,7 @@ WERROR cli_spoolss_enumprinterdrivers (struct cli_state *cli, make_spoolss_q_enumprinterdrivers( &in, server, env, level, &buffer, offered); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDRIVERS, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDRIVERS, in, out, qbuf, rbuf, spoolss_io_q_enumprinterdrivers, @@ -692,7 +692,7 @@ WERROR cli_spoolss_enumprinterdrivers (struct cli_state *cli, make_spoolss_q_enumprinterdrivers( &in, server, env, level, &buffer, offered); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDRIVERS, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDRIVERS, in, out, qbuf, rbuf, spoolss_io_q_enumprinterdrivers, @@ -727,7 +727,7 @@ WERROR cli_spoolss_enumprinterdrivers (struct cli_state *cli, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_getprinterdriverdir (struct cli_state *cli, +WERROR rpccli_spoolss_getprinterdriverdir (struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 level, char *env, DRIVER_DIRECTORY_CTR *ctr) @@ -742,7 +742,7 @@ WERROR cli_spoolss_getprinterdriverdir (struct cli_state *cli, ZERO_STRUCT(in); ZERO_STRUCT(out); - slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); strupper_m(server); offered = 0; @@ -750,7 +750,7 @@ WERROR cli_spoolss_getprinterdriverdir (struct cli_state *cli, make_spoolss_q_getprinterdriverdir( &in, server, env, level, &buffer, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDRIVERDIRECTORY, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDRIVERDIRECTORY, in, out, qbuf, rbuf, spoolss_io_q_getprinterdriverdir, @@ -767,7 +767,7 @@ WERROR cli_spoolss_getprinterdriverdir (struct cli_state *cli, make_spoolss_q_getprinterdriverdir( &in, server, env, level, &buffer, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDRIVERDIRECTORY, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDRIVERDIRECTORY, in, out, qbuf, rbuf, spoolss_io_q_getprinterdriverdir, @@ -786,7 +786,7 @@ WERROR cli_spoolss_getprinterdriverdir (struct cli_state *cli, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_addprinterdriver (struct cli_state *cli, +WERROR rpccli_spoolss_addprinterdriver (struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 level, PRINTER_DRIVER_CTR *ctr) { @@ -798,12 +798,12 @@ WERROR cli_spoolss_addprinterdriver (struct cli_state *cli, ZERO_STRUCT(in); ZERO_STRUCT(out); - slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); strupper_m(server); make_spoolss_q_addprinterdriver( mem_ctx, &in, server, level, ctr ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ADDPRINTERDRIVER, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ADDPRINTERDRIVER, in, out, qbuf, rbuf, spoolss_io_q_addprinterdriver, @@ -816,7 +816,7 @@ WERROR cli_spoolss_addprinterdriver (struct cli_state *cli, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_addprinterex (struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_addprinterex (struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 level, PRINTER_INFO_CTR*ctr) { prs_struct qbuf, rbuf; @@ -827,8 +827,8 @@ WERROR cli_spoolss_addprinterex (struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(in); ZERO_STRUCT(out); - slprintf(client, sizeof(fstring)-1, "\\\\%s", cli->desthost); - slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + slprintf(client, sizeof(fstring)-1, "\\\\%s", global_myname()); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); strupper_m(client); strupper_m(server); @@ -838,7 +838,7 @@ WERROR cli_spoolss_addprinterex (struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_addprinterex( mem_ctx, &in, server, client, user, level, ctr); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ADDPRINTEREX, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ADDPRINTEREX, in, out, qbuf, rbuf, spoolss_io_q_addprinterex, @@ -851,7 +851,7 @@ WERROR cli_spoolss_addprinterex (struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_deleteprinterdriverex(struct cli_state *cli, +WERROR rpccli_spoolss_deleteprinterdriverex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *arch, const char *driver, int version) { @@ -863,12 +863,12 @@ WERROR cli_spoolss_deleteprinterdriverex(struct cli_state *cli, ZERO_STRUCT(in); ZERO_STRUCT(out); - slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); strupper_m(server); make_spoolss_q_deleteprinterdriverex( mem_ctx, &in, server, arch, driver, version ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERDRIVEREX, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERDRIVEREX, in, out, qbuf, rbuf, spoolss_io_q_deleteprinterdriverex, @@ -881,7 +881,7 @@ WERROR cli_spoolss_deleteprinterdriverex(struct cli_state *cli, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_deleteprinterdriver (struct cli_state *cli, +WERROR rpccli_spoolss_deleteprinterdriver (struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *arch, const char *driver) { @@ -893,12 +893,12 @@ WERROR cli_spoolss_deleteprinterdriver (struct cli_state *cli, ZERO_STRUCT(in); ZERO_STRUCT(out); - slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); strupper_m(server); make_spoolss_q_deleteprinterdriver( mem_ctx, &in, server, arch, driver ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERDRIVER, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERDRIVER, in, out, qbuf, rbuf, spoolss_io_q_deleteprinterdriver, @@ -911,7 +911,7 @@ WERROR cli_spoolss_deleteprinterdriver (struct cli_state *cli, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_getprintprocessordirectory(struct cli_state *cli, +WERROR rpccli_spoolss_getprintprocessordirectory(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, char *name, char *environment, fstring procdir) @@ -931,7 +931,7 @@ WERROR cli_spoolss_getprintprocessordirectory(struct cli_state *cli, make_spoolss_q_getprintprocessordirectory( &in, name, environment, level, &buffer, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTPROCESSORDIRECTORY, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTPROCESSORDIRECTORY, in, out, qbuf, rbuf, spoolss_io_q_getprintprocessordirectory, @@ -948,7 +948,7 @@ WERROR cli_spoolss_getprintprocessordirectory(struct cli_state *cli, make_spoolss_q_getprintprocessordirectory( &in, name, environment, level, &buffer, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTPROCESSORDIRECTORY, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTPROCESSORDIRECTORY, in, out, qbuf, rbuf, spoolss_io_q_getprintprocessordirectory, @@ -967,7 +967,7 @@ WERROR cli_spoolss_getprintprocessordirectory(struct cli_state *cli, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *handle, uint32 level, FORM *form) { prs_struct qbuf, rbuf; @@ -979,7 +979,7 @@ WERROR cli_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_addform( &in, handle, level, form ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ADDFORM, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ADDFORM, in, out, qbuf, rbuf, spoolss_io_q_addform, @@ -992,7 +992,7 @@ WERROR cli_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *handle, uint32 level, const char *form_name, FORM *form) { @@ -1005,7 +1005,7 @@ WERROR cli_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_setform( &in, handle, level, form_name, form ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETFORM, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETFORM, in, out, qbuf, rbuf, spoolss_io_q_setform, @@ -1018,7 +1018,7 @@ WERROR cli_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *handle, const char *formname, uint32 level, FORM_1 *form) { @@ -1035,7 +1035,7 @@ WERROR cli_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx, rpcbuf_init(&buffer, offered, mem_ctx); make_spoolss_q_getform( &in, handle, formname, level, &buffer, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETFORM, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETFORM, in, out, qbuf, rbuf, spoolss_io_q_getform, @@ -1051,7 +1051,7 @@ WERROR cli_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx, rpcbuf_init(&buffer, offered, mem_ctx); make_spoolss_q_getform( &in, handle, formname, level, &buffer, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETFORM, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETFORM, in, out, qbuf, rbuf, spoolss_io_q_getform, @@ -1070,7 +1070,7 @@ WERROR cli_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_deleteform(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_deleteform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *handle, const char *form_name) { prs_struct qbuf, rbuf; @@ -1082,7 +1082,7 @@ WERROR cli_spoolss_deleteform(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_deleteform( &in, handle, form_name ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEFORM, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEFORM, in, out, qbuf, rbuf, spoolss_io_q_deleteform, @@ -1095,7 +1095,7 @@ WERROR cli_spoolss_deleteform(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_enumforms(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *handle, int level, uint32 *num_forms, FORM_1 **forms) { @@ -1112,7 +1112,7 @@ WERROR cli_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx, rpcbuf_init(&buffer, offered, mem_ctx); make_spoolss_q_enumforms( &in, handle, level, &buffer, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMFORMS, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMFORMS, in, out, qbuf, rbuf, spoolss_io_q_enumforms, @@ -1128,7 +1128,7 @@ WERROR cli_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx, rpcbuf_init(&buffer, offered, mem_ctx); make_spoolss_q_enumforms( &in, handle, level, &buffer, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMFORMS, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMFORMS, in, out, qbuf, rbuf, spoolss_io_q_enumforms, @@ -1149,7 +1149,7 @@ WERROR cli_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_enumjobs(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_enumjobs(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, uint32 level, uint32 firstjob, uint32 num_jobs, uint32 *returned, JOB_INFO_CTR *ctr) { @@ -1167,7 +1167,7 @@ WERROR cli_spoolss_enumjobs(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_enumjobs( &in, hnd, firstjob, num_jobs, level, &buffer, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMJOBS, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMJOBS, in, out, qbuf, rbuf, spoolss_io_q_enumjobs, @@ -1184,7 +1184,7 @@ WERROR cli_spoolss_enumjobs(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_enumjobs( &in, hnd, firstjob, num_jobs, level, &buffer, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMJOBS, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMJOBS, in, out, qbuf, rbuf, spoolss_io_q_enumjobs, @@ -1215,7 +1215,7 @@ WERROR cli_spoolss_enumjobs(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_setjob(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_setjob(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, uint32 jobid, uint32 level, uint32 command) { @@ -1228,7 +1228,7 @@ WERROR cli_spoolss_setjob(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_setjob( &in, hnd, jobid, level, command ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETJOB, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETJOB, in, out, qbuf, rbuf, spoolss_io_q_setjob, @@ -1241,7 +1241,7 @@ WERROR cli_spoolss_setjob(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_getjob(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_getjob(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, uint32 jobid, uint32 level, JOB_INFO_CTR *ctr) { @@ -1258,7 +1258,7 @@ WERROR cli_spoolss_getjob(struct cli_state *cli, TALLOC_CTX *mem_ctx, rpcbuf_init(&buffer, offered, mem_ctx); make_spoolss_q_getjob( &in, hnd, jobid, level, &buffer, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETJOB, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETJOB, in, out, qbuf, rbuf, spoolss_io_q_getjob, @@ -1274,7 +1274,7 @@ WERROR cli_spoolss_getjob(struct cli_state *cli, TALLOC_CTX *mem_ctx, rpcbuf_init(&buffer, offered, mem_ctx); make_spoolss_q_getjob( &in, hnd, jobid, level, &buffer, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETJOB, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETJOB, in, out, qbuf, rbuf, spoolss_io_q_getjob, @@ -1300,7 +1300,7 @@ WERROR cli_spoolss_getjob(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_startpageprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_startpageprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd) { prs_struct qbuf, rbuf; @@ -1312,7 +1312,7 @@ WERROR cli_spoolss_startpageprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_startpageprinter( &in, hnd ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_STARTPAGEPRINTER, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_STARTPAGEPRINTER, in, out, qbuf, rbuf, spoolss_io_q_startpageprinter, @@ -1325,7 +1325,7 @@ WERROR cli_spoolss_startpageprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_endpageprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_endpageprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd) { prs_struct qbuf, rbuf; @@ -1337,7 +1337,7 @@ WERROR cli_spoolss_endpageprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_endpageprinter( &in, hnd ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENDPAGEPRINTER, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENDPAGEPRINTER, in, out, qbuf, rbuf, spoolss_io_q_endpageprinter, @@ -1350,7 +1350,7 @@ WERROR cli_spoolss_endpageprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_startdocprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_startdocprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, char *docname, char *outputfile, char *datatype, uint32 *jobid) @@ -1366,7 +1366,7 @@ WERROR cli_spoolss_startdocprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_startdocprinter( &in, hnd, level, docname, outputfile, datatype ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_STARTDOCPRINTER, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_STARTDOCPRINTER, in, out, qbuf, rbuf, spoolss_io_q_startdocprinter, @@ -1381,7 +1381,7 @@ WERROR cli_spoolss_startdocprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_enddocprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_enddocprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd) { prs_struct qbuf, rbuf; @@ -1393,7 +1393,7 @@ WERROR cli_spoolss_enddocprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_enddocprinter( &in, hnd ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENDDOCPRINTER, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENDDOCPRINTER, in, out, qbuf, rbuf, spoolss_io_q_enddocprinter, @@ -1406,7 +1406,7 @@ WERROR cli_spoolss_enddocprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_getprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_getprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, const char *valuename, REGISTRY_VALUE *value) { @@ -1421,7 +1421,7 @@ WERROR cli_spoolss_getprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, offered = 0; make_spoolss_q_getprinterdata( &in, hnd, valuename, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDATA, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDATA, in, out, qbuf, rbuf, spoolss_io_q_getprinterdata, @@ -1436,7 +1436,7 @@ WERROR cli_spoolss_getprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_getprinterdata( &in, hnd, valuename, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDATA, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDATA, in, out, qbuf, rbuf, spoolss_io_q_getprinterdata, @@ -1459,7 +1459,7 @@ WERROR cli_spoolss_getprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_getprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_getprinterdataex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, const char *keyname, const char *valuename, REGISTRY_VALUE *value) @@ -1474,7 +1474,7 @@ WERROR cli_spoolss_getprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_getprinterdataex( &in, hnd, keyname, valuename, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDATAEX, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDATAEX, in, out, qbuf, rbuf, spoolss_io_q_getprinterdataex, @@ -1489,7 +1489,7 @@ WERROR cli_spoolss_getprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_getprinterdataex( &in, hnd, keyname, valuename, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDATAEX, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_GETPRINTERDATAEX, in, out, qbuf, rbuf, spoolss_io_q_getprinterdataex, @@ -1512,7 +1512,7 @@ WERROR cli_spoolss_getprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_setprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, REGISTRY_VALUE *value) { prs_struct qbuf, rbuf; @@ -1525,7 +1525,7 @@ WERROR cli_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_setprinterdata( &in, hnd, value->valuename, value->type, (char *)value->data_p, value->size); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETPRINTERDATA, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETPRINTERDATA, in, out, qbuf, rbuf, spoolss_io_q_setprinterdata, @@ -1538,7 +1538,7 @@ WERROR cli_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_setprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_setprinterdataex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, char *keyname, REGISTRY_VALUE *value) { @@ -1552,7 +1552,7 @@ WERROR cli_spoolss_setprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_setprinterdataex( &in, hnd, keyname, value->valuename, value->type, (char *)value->data_p, value->size); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETPRINTERDATAEX, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_SETPRINTERDATAEX, in, out, qbuf, rbuf, spoolss_io_q_setprinterdataex, @@ -1565,7 +1565,7 @@ WERROR cli_spoolss_setprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_enumprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_enumprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, uint32 ndx, uint32 value_offered, uint32 data_offered, uint32 *value_needed, uint32 *data_needed, @@ -1580,7 +1580,7 @@ WERROR cli_spoolss_enumprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_enumprinterdata( &in, hnd, ndx, value_offered, data_offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDATA, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDATA, in, out, qbuf, rbuf, spoolss_io_q_enumprinterdata, @@ -1609,7 +1609,7 @@ WERROR cli_spoolss_enumprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_enumprinterdataex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, const char *keyname, REGVAL_CTR *ctr) { @@ -1625,7 +1625,7 @@ WERROR cli_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx, offered = 0; make_spoolss_q_enumprinterdataex( &in, hnd, keyname, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDATAEX, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDATAEX, in, out, qbuf, rbuf, spoolss_io_q_enumprinterdataex, @@ -1640,7 +1640,7 @@ WERROR cli_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_enumprinterdataex( &in, hnd, keyname, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDATAEX, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERDATAEX, in, out, qbuf, rbuf, spoolss_io_q_enumprinterdataex, @@ -1666,7 +1666,7 @@ WERROR cli_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_writeprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_writeprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, uint32 data_size, char *data, uint32 *num_written) { @@ -1679,7 +1679,7 @@ WERROR cli_spoolss_writeprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_writeprinter( &in, hnd, data_size, data ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_WRITEPRINTER, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_WRITEPRINTER, in, out, qbuf, rbuf, spoolss_io_q_writeprinter, @@ -1695,7 +1695,7 @@ WERROR cli_spoolss_writeprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_deleteprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_deleteprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, char *valuename) { prs_struct qbuf, rbuf; @@ -1707,7 +1707,7 @@ WERROR cli_spoolss_deleteprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_deleteprinterdata( &in, hnd, valuename ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERDATA, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERDATA, in, out, qbuf, rbuf, spoolss_io_q_deleteprinterdata, @@ -1720,7 +1720,7 @@ WERROR cli_spoolss_deleteprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_deleteprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_deleteprinterdataex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, char *keyname, char *valuename) { @@ -1733,7 +1733,7 @@ WERROR cli_spoolss_deleteprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ct make_spoolss_q_deleteprinterdataex( &in, hnd, keyname, valuename ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERDATAEX, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERDATAEX, in, out, qbuf, rbuf, spoolss_io_q_deleteprinterdataex, @@ -1746,7 +1746,7 @@ WERROR cli_spoolss_deleteprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ct /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_enumprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_enumprinterkey(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, const char *keyname, uint16 **keylist, uint32 *len) { @@ -1760,7 +1760,7 @@ WERROR cli_spoolss_enumprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_enumprinterkey( &in, hnd, keyname, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERKEY, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERKEY, in, out, qbuf, rbuf, spoolss_io_q_enumprinterkey, @@ -1775,7 +1775,7 @@ WERROR cli_spoolss_enumprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_enumprinterkey( &in, hnd, keyname, offered ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERKEY, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ENUMPRINTERKEY, in, out, qbuf, rbuf, spoolss_io_q_enumprinterkey, @@ -1799,7 +1799,7 @@ WERROR cli_spoolss_enumprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** **********************************************************************/ -WERROR cli_spoolss_deleteprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_deleteprinterkey(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, char *keyname) { prs_struct qbuf, rbuf; @@ -1811,7 +1811,7 @@ WERROR cli_spoolss_deleteprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx, make_spoolss_q_deleteprinterkey( &in, hnd, keyname ); - CLI_DO_RPC( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERKEY, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_DELETEPRINTERKEY, in, out, qbuf, rbuf, spoolss_io_q_deleteprinterkey, diff --git a/source3/rpc_client/cli_spoolss_notify.c b/source3/rpc_client/cli_spoolss_notify.c index d6bcc8ba9c0..f8098943dbf 100644 --- a/source3/rpc_client/cli_spoolss_notify.c +++ b/source3/rpc_client/cli_spoolss_notify.c @@ -5,8 +5,8 @@ Copyright (C) Gerald Carter 2001-2002, Copyright (C) Tim Potter 2000-2002, Copyright (C) Andrew Tridgell 1994-2000, - Copyright (C) Luke Kenneth Casson Leighton 1996-2000, Copyright (C) Jean-Francois Micouleau 1999-2000. + Copyright (C) Jeremy Allison 2005. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -36,7 +36,7 @@ value) and this rpc establishes a back-channel over which printer notifications are performed. */ -WERROR cli_spoolss_reply_open_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_reply_open_printer(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *printer, uint32 printerlocal, uint32 type, POLICY_HND *handle) { @@ -47,37 +47,28 @@ WERROR cli_spoolss_reply_open_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx /* Initialise input parameters */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - make_spoolss_q_replyopenprinter(&q, printer, printerlocal, type); /* Marshall data and send request */ - if (!spoolss_io_q_replyopenprinter("", &q, &qbuf, 0) || - !rpc_api_pipe_req (cli, PI_SPOOLSS, SPOOLSS_REPLYOPENPRINTER, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!spoolss_io_r_replyopenprinter("", &r, &rbuf, 0)) - goto done; - + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_REPLYOPENPRINTER, + q, r, + qbuf, rbuf, + spoolss_io_q_replyopenprinter, + spoolss_io_r_replyopenprinter, + WERR_GENERAL_FAILURE ); + /* Return result */ memcpy(handle, &r.handle, sizeof(r.handle)); result = r.status; -done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } /* Close a back-channel notification connection */ -WERROR cli_spoolss_reply_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_reply_close_printer(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *handle) { prs_struct qbuf, rbuf; @@ -87,30 +78,20 @@ WERROR cli_spoolss_reply_close_printer(struct cli_state *cli, TALLOC_CTX *mem_ct /* Initialise input parameters */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - make_spoolss_q_reply_closeprinter(&q, handle); /* Marshall data and send request */ - if (!spoolss_io_q_replycloseprinter("", &q, &qbuf, 0) || - !rpc_api_pipe_req (cli, PI_SPOOLSS, SPOOLSS_REPLYCLOSEPRINTER, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!spoolss_io_r_replycloseprinter("", &r, &rbuf, 0)) - goto done; - + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_REPLYCLOSEPRINTER, + q, r, + qbuf, rbuf, + spoolss_io_q_replycloseprinter, + spoolss_io_r_replycloseprinter, + WERR_GENERAL_FAILURE ); + /* Return result */ result = r.status; - -done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } @@ -121,7 +102,7 @@ done: Also see cli_spolss_reply_rrpcn() *********************************************************************/ -WERROR cli_spoolss_routerreplyprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_routerreplyprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint32 condition, uint32 change_id) { prs_struct qbuf, rbuf; @@ -131,30 +112,20 @@ WERROR cli_spoolss_routerreplyprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx /* Initialise input parameters */ - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - make_spoolss_q_routerreplyprinter(&q, pol, condition, change_id); /* Marshall data and send request */ - if (!spoolss_io_q_routerreplyprinter("", &q, &qbuf, 0) || - !rpc_api_pipe_req (cli, PI_SPOOLSS, SPOOLSS_ROUTERREPLYPRINTER, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!spoolss_io_r_routerreplyprinter("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_ROUTERREPLYPRINTER, + q, r, + qbuf, rbuf, + spoolss_io_q_routerreplyprinter, + spoolss_io_r_routerreplyprinter, + WERR_GENERAL_FAILURE ); /* Return output parameters */ result = r.status; - -done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } @@ -165,7 +136,7 @@ done: Also see cli_spoolss_routereplyprinter() *********************************************************************/ -WERROR cli_spoolss_rrpcn(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_rrpcn(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint32 notify_data_len, SPOOL_NOTIFY_INFO_DATA *notify_data, uint32 change_low, uint32 change_high) @@ -179,11 +150,6 @@ WERROR cli_spoolss_rrpcn(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - ZERO_STRUCT(notify_info); /* Initialise input parameters */ @@ -201,14 +167,12 @@ WERROR cli_spoolss_rrpcn(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Marshall data and send request */ - if(!spoolss_io_q_reply_rrpcn("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SPOOLSS, SPOOLSS_RRPCN, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if(!spoolss_io_r_reply_rrpcn("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_RRPCN, + q, r, + qbuf, rbuf, + spoolss_io_q_reply_rrpcn, + spoolss_io_r_reply_rrpcn, + WERR_GENERAL_FAILURE ); if (r.unknown0 == 0x00080000) DEBUG(8,("cli_spoolss_reply_rrpcn: I think the spooler resonded that the notification was ignored.\n")); @@ -216,18 +180,13 @@ WERROR cli_spoolss_rrpcn(struct cli_state *cli, TALLOC_CTX *mem_ctx, DEBUG(8,("cli_spoolss_reply_rrpcn: unknown0 is non-zero [0x%x]\n", r.unknown0)); result = r.status; - -done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } /********************************************************************* *********************************************************************/ -WERROR cli_spoolss_rffpcnex(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_spoolss_rffpcnex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *pol, uint32 flags, uint32 options, const char *localmachine, uint32 printerlocal, SPOOL_NOTIFY_OPTION *option) @@ -240,11 +199,6 @@ WERROR cli_spoolss_rffpcnex(struct cli_state *cli, TALLOC_CTX *mem_ctx, ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Initialise input parameters */ make_spoolss_q_rffpcnex( @@ -253,20 +207,13 @@ WERROR cli_spoolss_rffpcnex(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Marshall data and send request */ - if(!spoolss_io_q_rffpcnex("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SPOOLSS, SPOOLSS_RFFPCNEX, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if(!spoolss_io_r_rffpcnex("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SPOOLSS, SPOOLSS_RFFPCNEX, + q, r, + qbuf, rbuf, + spoolss_io_q_rffpcnex, + spoolss_io_r_rffpcnex, + WERR_GENERAL_FAILURE ); result = r.status; - -done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } diff --git a/source3/rpc_client/cli_srvsvc.c b/source3/rpc_client/cli_srvsvc.c index b2449a79038..2c71d6b18ea 100644 --- a/source3/rpc_client/cli_srvsvc.c +++ b/source3/rpc_client/cli_srvsvc.c @@ -2,10 +2,10 @@ Unix SMB/CIFS implementation. NT Domain Authentication SMB / MSRPC client Copyright (C) Andrew Tridgell 1994-2000 - Copyright (C) Luke Kenneth Casson Leighton 1996-2000 Copyright (C) Tim Potter 2001 Copyright (C) Jim McDonough 2002 - + Copyright (C) Jeremy Allison 2005. + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -23,7 +23,7 @@ #include "includes.h" -WERROR cli_srvsvc_net_srv_get_info(struct cli_state *cli, +WERROR rpccli_srvsvc_net_srv_get_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 switch_value, SRV_INFO_CTR *ctr) { @@ -31,42 +31,33 @@ WERROR cli_srvsvc_net_srv_get_info(struct cli_state *cli, SRV_Q_NET_SRV_GET_INFO q; SRV_R_NET_SRV_GET_INFO r; WERROR result = W_ERROR(ERRgeneral); + fstring server; ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Initialise input parameters */ - init_srv_q_net_srv_get_info(&q, cli->srv_name_slash, switch_value); - - /* Marshall data and send request */ - - if (!srv_io_q_net_srv_get_info("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_SRV_GET_INFO, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); + strupper_m(server); + init_srv_q_net_srv_get_info(&q, server, switch_value); r.ctr = ctr; - if (!srv_io_r_net_srv_get_info("", &r, &rbuf, 0)) - goto done; - - result = r.status; + /* Marshall data and send request */ - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); + CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_SRV_GET_INFO, + q, r, + qbuf, rbuf, + srv_io_q_net_srv_get_info, + srv_io_r_net_srv_get_info, + WERR_GENERAL_FAILURE); + result = r.status; return result; } -WERROR cli_srvsvc_net_share_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_srvsvc_net_share_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 info_level, SRV_SHARE_INFO_CTR *ctr, int preferred_len, ENUM_HND *hnd) { @@ -74,31 +65,27 @@ WERROR cli_srvsvc_net_share_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx, SRV_Q_NET_SHARE_ENUM q; SRV_R_NET_SHARE_ENUM r; WERROR result = W_ERROR(ERRgeneral); + fstring server; int i; ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Initialise input parameters */ - init_srv_q_net_share_enum( - &q, cli->srv_name_slash, info_level, preferred_len, hnd); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); + strupper_m(server); - /* Marshall data and send request */ + init_srv_q_net_share_enum(&q, server, info_level, preferred_len, hnd); - if (!srv_io_q_net_share_enum("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_SHARE_ENUM_ALL, &qbuf, &rbuf)) - goto done; + /* Marshall data and send request */ - /* Unmarshall response */ - - if (!srv_io_r_net_share_enum("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_SHARE_ENUM_ALL, + q, r, + qbuf, rbuf, + srv_io_q_net_share_enum, + srv_io_r_net_share_enum, + WERR_GENERAL_FAILURE); result = r.status; @@ -215,14 +202,13 @@ WERROR cli_srvsvc_net_share_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx, } break; } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); + + done: return result; } -WERROR cli_srvsvc_net_share_get_info(struct cli_state *cli, +WERROR rpccli_srvsvc_net_share_get_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *sharename, uint32 info_level, @@ -232,30 +218,26 @@ WERROR cli_srvsvc_net_share_get_info(struct cli_state *cli, SRV_Q_NET_SHARE_GET_INFO q; SRV_R_NET_SHARE_GET_INFO r; WERROR result = W_ERROR(ERRgeneral); + fstring server; ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Initialise input parameters */ - init_srv_q_net_share_get_info(&q, cli->srv_name_slash, sharename, - info_level); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); + strupper_m(server); - /* Marshall data and send request */ + init_srv_q_net_share_get_info(&q, server, sharename, info_level); - if (!srv_io_q_net_share_get_info("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_SHARE_GET_INFO, &qbuf, &rbuf)) - goto done; + /* Marshall data and send request */ - /* Unmarshall response */ - - if (!srv_io_r_net_share_get_info("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_SHARE_GET_INFO, + q, r, + qbuf, rbuf, + srv_io_q_net_share_get_info, + srv_io_r_net_share_get_info, + WERR_GENERAL_FAILURE); result = r.status; @@ -363,14 +345,12 @@ WERROR cli_srvsvc_net_share_get_info(struct cli_state *cli, break; } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); + done: return result; } -WERROR cli_srvsvc_net_share_set_info(struct cli_state *cli, +WERROR rpccli_srvsvc_net_share_set_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *sharename, uint32 info_level, @@ -380,84 +360,64 @@ WERROR cli_srvsvc_net_share_set_info(struct cli_state *cli, SRV_Q_NET_SHARE_SET_INFO q; SRV_R_NET_SHARE_SET_INFO r; WERROR result = W_ERROR(ERRgeneral); + fstring server; ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Initialise input parameters */ - init_srv_q_net_share_set_info(&q, cli->srv_name_slash, sharename, - info_level, info); - - /* Marshall data and send request */ + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); + strupper_m(server); - if (!srv_io_q_net_share_set_info("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_SHARE_SET_INFO, &qbuf, &rbuf)) - goto done; + init_srv_q_net_share_set_info(&q, server, sharename, info_level, info); - /* Unmarshall response */ + /* Marshall data and send request */ - if (!srv_io_r_net_share_set_info("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_SHARE_SET_INFO, + q, r, + qbuf, rbuf, + srv_io_q_net_share_set_info, + srv_io_r_net_share_set_info, + WERR_GENERAL_FAILURE); result = r.status; - - if (!W_ERROR_IS_OK(result)) - goto done; - - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -WERROR cli_srvsvc_net_share_del(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_srvsvc_net_share_del(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *sharename) { prs_struct qbuf, rbuf; SRV_Q_NET_SHARE_DEL q; SRV_R_NET_SHARE_DEL r; WERROR result = W_ERROR(ERRgeneral); + fstring server; ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Initialise input parameters */ - init_srv_q_net_share_del(&q, cli->srv_name_slash, sharename); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); + strupper_m(server); - /* Marshall data and send request */ + init_srv_q_net_share_del(&q, server, sharename); - if (!srv_io_q_net_share_del("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_SHARE_DEL, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ + /* Marshall data and send request */ - if (!srv_io_r_net_share_del("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_SHARE_DEL, + q, r, + qbuf, rbuf, + srv_io_q_net_share_del, + srv_io_r_net_share_del, + WERR_GENERAL_FAILURE); result = r.status; - - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -WERROR cli_srvsvc_net_share_add(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_srvsvc_net_share_add(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, const char *netname, uint32 type, const char *remark, uint32 perms, uint32 max_uses, uint32 num_uses, @@ -468,85 +428,65 @@ WERROR cli_srvsvc_net_share_add(struct cli_state *cli, TALLOC_CTX *mem_ctx, SRV_Q_NET_SHARE_ADD q; SRV_R_NET_SHARE_ADD r; WERROR result = W_ERROR(ERRgeneral); + fstring server; ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); + strupper_m(server); - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - - init_srv_q_net_share_add(&q,cli->srv_name_slash, netname, type, remark, + init_srv_q_net_share_add(&q,server, netname, type, remark, perms, max_uses, num_uses, path, passwd, level, sd); /* Marshall data and send request */ - if (!srv_io_q_net_share_add("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_SHARE_ADD, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!srv_io_r_net_share_add("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_SHARE_ADD, + q, r, + qbuf, rbuf, + srv_io_q_net_share_add, + srv_io_r_net_share_add, + WERR_GENERAL_FAILURE); result = r.status; - - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - return result; } -WERROR cli_srvsvc_net_remote_tod(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_srvsvc_net_remote_tod(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, char *server, TIME_OF_DAY_INFO *tod) { prs_struct qbuf, rbuf; SRV_Q_NET_REMOTE_TOD q; SRV_R_NET_REMOTE_TOD r; WERROR result = W_ERROR(ERRgeneral); + fstring server_slash; ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Initialise input parameters */ - init_srv_q_net_remote_tod(&q, cli->srv_name_slash); - - /* Marshall data and send request */ - - if (!srv_io_q_net_remote_tod("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_REMOTE_TOD, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ + slprintf(server_slash, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); + strupper_m(server_slash); + init_srv_q_net_remote_tod(&q, server_slash); r.tod = tod; - if (!srv_io_r_net_remote_tod("", &r, &rbuf, 0)) - goto done; - - result = r.status; - - if (!W_ERROR_IS_OK(result)) - goto done; + /* Marshall data and send request */ - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); + CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_REMOTE_TOD, + q, r, + qbuf, rbuf, + srv_io_q_net_remote_tod, + srv_io_r_net_remote_tod, + WERR_GENERAL_FAILURE); + result = r.status; return result; } -WERROR cli_srvsvc_net_file_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_srvsvc_net_file_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 file_level, const char *user_name, SRV_FILE_INFO_CTR *ctr, int preferred_len, ENUM_HND *hnd) @@ -555,31 +495,28 @@ WERROR cli_srvsvc_net_file_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx, SRV_Q_NET_FILE_ENUM q; SRV_R_NET_FILE_ENUM r; WERROR result = W_ERROR(ERRgeneral); + fstring server; int i; ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Initialise input parameters */ - init_srv_q_net_file_enum(&q, cli->srv_name_slash, NULL, user_name, + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); + strupper_m(server); + + init_srv_q_net_file_enum(&q, server, NULL, user_name, file_level, ctr, preferred_len, hnd); /* Marshall data and send request */ - if (!srv_io_q_net_file_enum("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_FILE_ENUM, &qbuf, &rbuf)) - goto done; - - /* Unmarshall response */ - - if (!srv_io_r_net_file_enum("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_FILE_ENUM, + q, r, + qbuf, rbuf, + srv_io_q_net_file_enum, + srv_io_r_net_file_enum, + WERR_GENERAL_FAILURE); result = r.status; @@ -625,47 +562,38 @@ WERROR cli_srvsvc_net_file_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx, break; } - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); - + done: return result; } -WERROR cli_srvsvc_net_file_close(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_srvsvc_net_file_close(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 file_id) { prs_struct qbuf, rbuf; SRV_Q_NET_FILE_CLOSE q; SRV_R_NET_FILE_CLOSE r; WERROR result = W_ERROR(ERRgeneral); + fstring server; ZERO_STRUCT(q); ZERO_STRUCT(r); - /* Initialise parse structures */ - - prs_init(&qbuf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - /* Initialise input parameters */ - init_srv_q_net_file_close(&q, cli->srv_name_slash, file_id); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); + strupper_m(server); - /* Marshall data and send request */ - - if (!srv_io_q_net_file_close("", &q, &qbuf, 0) || - !rpc_api_pipe_req(cli, PI_SRVSVC, SRV_NET_FILE_CLOSE, &qbuf, &rbuf)) - goto done; + init_srv_q_net_file_close(&q, server, file_id); - /* Unmarshall response */ + /* Marshall data and send request */ - if (!srv_io_r_net_file_close("", &r, &rbuf, 0)) - goto done; + CLI_DO_RPC_WERR(cli, mem_ctx, PI_SRVSVC, SRV_NET_FILE_CLOSE, + q, r, + qbuf, rbuf, + srv_io_q_net_file_close, + srv_io_r_net_file_close, + WERR_GENERAL_FAILURE); result = r.status; - done: - prs_mem_free(&qbuf); - prs_mem_free(&rbuf); return result; } diff --git a/source3/rpc_client/cli_svcctl.c b/source3/rpc_client/cli_svcctl.c index 9f80bb79a39..2df27c2da5b 100644 --- a/source3/rpc_client/cli_svcctl.c +++ b/source3/rpc_client/cli_svcctl.c @@ -61,7 +61,7 @@ const char* svc_status_string( uint32 state ) /******************************************************************** ********************************************************************/ -WERROR cli_svcctl_open_scm( struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_svcctl_open_scm(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hSCM, uint32 access_desired ) { SVCCTL_Q_OPEN_SCMANAGER in; @@ -80,12 +80,12 @@ WERROR cli_svcctl_open_scm( struct cli_state *cli, TALLOC_CTX *mem_ctx, if ( !(in.servername = TALLOC_P( mem_ctx, UNISTR2 )) ) return WERR_NOMEM; - fstr_sprintf( server, "\\\\%s", cli->desthost ); + fstr_sprintf( server, "\\\\%s", cli->cli->desthost ); init_unistr2( in.servername, server, UNI_STR_TERMINATE ); in.access = access_desired; - CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_OPEN_SCMANAGER_W, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_OPEN_SCMANAGER_W, in, out, qbuf, rbuf, svcctl_io_q_open_scmanager, @@ -103,7 +103,7 @@ WERROR cli_svcctl_open_scm( struct cli_state *cli, TALLOC_CTX *mem_ctx, /******************************************************************** ********************************************************************/ -WERROR cli_svcctl_open_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_svcctl_open_service( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hSCM, POLICY_HND *hService, const char *servicename, uint32 access_desired ) { @@ -118,7 +118,7 @@ WERROR cli_svcctl_open_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, init_unistr2( &in.servicename, servicename, UNI_STR_TERMINATE ); in.access = access_desired; - CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_OPEN_SERVICE_W, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_OPEN_SERVICE_W, in, out, qbuf, rbuf, svcctl_io_q_open_service, @@ -136,7 +136,7 @@ WERROR cli_svcctl_open_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, /******************************************************************** ********************************************************************/ -WERROR cli_svcctl_close_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hService ) +WERROR rpccli_svcctl_close_service(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hService ) { SVCCTL_Q_CLOSE_SERVICE in; SVCCTL_R_CLOSE_SERVICE out; @@ -147,7 +147,7 @@ WERROR cli_svcctl_close_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, POL memcpy( &in.handle, hService, sizeof(POLICY_HND) ); - CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_CLOSE_SERVICE, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_CLOSE_SERVICE, in, out, qbuf, rbuf, svcctl_io_q_close_service, @@ -160,7 +160,7 @@ WERROR cli_svcctl_close_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, POL /******************************************************************* *******************************************************************/ -WERROR cli_svcctl_enumerate_services( struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_svcctl_enumerate_services( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hSCM, uint32 type, uint32 state, uint32 *returned, ENUM_SERVICES_STATUS **service_array ) { @@ -185,7 +185,7 @@ WERROR cli_svcctl_enumerate_services( struct cli_state *cli, TALLOC_CTX *mem_ctx /* first time is to get the buffer size */ in.buffer_size = 0; - CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_ENUM_SERVICES_STATUS_W, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_ENUM_SERVICES_STATUS_W, in, out, qbuf, rbuf, svcctl_io_q_enum_services_status, @@ -197,7 +197,7 @@ WERROR cli_svcctl_enumerate_services( struct cli_state *cli, TALLOC_CTX *mem_ctx if ( W_ERROR_EQUAL( out.status, WERR_MORE_DATA ) ) { in.buffer_size = out.needed; - CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_ENUM_SERVICES_STATUS_W, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_ENUM_SERVICES_STATUS_W, in, out, qbuf, rbuf, svcctl_io_q_enum_services_status, @@ -225,7 +225,7 @@ WERROR cli_svcctl_enumerate_services( struct cli_state *cli, TALLOC_CTX *mem_ctx /******************************************************************* *******************************************************************/ -WERROR cli_svcctl_query_status( struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_svcctl_query_status( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hService, SERVICE_STATUS *status ) { SVCCTL_Q_QUERY_STATUS in; @@ -237,7 +237,7 @@ WERROR cli_svcctl_query_status( struct cli_state *cli, TALLOC_CTX *mem_ctx, memcpy( &in.handle, hService, sizeof(POLICY_HND) ); - CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_STATUS, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_STATUS, in, out, qbuf, rbuf, svcctl_io_q_query_status, @@ -255,7 +255,7 @@ WERROR cli_svcctl_query_status( struct cli_state *cli, TALLOC_CTX *mem_ctx, /******************************************************************* *******************************************************************/ -WERROR cli_svcctl_query_config(struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_svcctl_query_config(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hService, SERVICE_CONFIG *config ) { SVCCTL_Q_QUERY_SERVICE_CONFIG in; @@ -269,7 +269,7 @@ WERROR cli_svcctl_query_config(struct cli_state *cli, TALLOC_CTX *mem_ctx, in.buffer_size = 0; - CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_SERVICE_CONFIG_W, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_SERVICE_CONFIG_W, in, out, qbuf, rbuf, svcctl_io_q_query_service_config, @@ -279,7 +279,7 @@ WERROR cli_svcctl_query_config(struct cli_state *cli, TALLOC_CTX *mem_ctx, if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) { in.buffer_size = out.needed; - CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_SERVICE_CONFIG_W, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_QUERY_SERVICE_CONFIG_W, in, out, qbuf, rbuf, svcctl_io_q_query_service_config, @@ -298,11 +298,30 @@ WERROR cli_svcctl_query_config(struct cli_state *cli, TALLOC_CTX *mem_ctx, config->startname = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); config->displayname = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); - copy_unistr2( config->executablepath, out.config.executablepath ); - copy_unistr2( config->loadordergroup, out.config.loadordergroup ); - copy_unistr2( config->dependencies, out.config.dependencies ); - copy_unistr2( config->startname, out.config.startname ); - copy_unistr2( config->displayname, out.config.displayname ); + if ( out.config.executablepath ) { + config->executablepath = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + copy_unistr2( config->executablepath, out.config.executablepath ); + } + + if ( out.config.loadordergroup ) { + config->loadordergroup = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + copy_unistr2( config->loadordergroup, out.config.loadordergroup ); + } + + if ( out.config.dependencies ) { + config->dependencies = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + copy_unistr2( config->dependencies, out.config.dependencies ); + } + + if ( out.config.startname ) { + config->startname = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + copy_unistr2( config->startname, out.config.startname ); + } + + if ( out.config.displayname ) { + config->displayname = TALLOC_ZERO_P( mem_ctx, UNISTR2 ); + copy_unistr2( config->displayname, out.config.displayname ); + } return out.status; } @@ -310,7 +329,7 @@ WERROR cli_svcctl_query_config(struct cli_state *cli, TALLOC_CTX *mem_ctx, /******************************************************************* *******************************************************************/ -WERROR cli_svcctl_start_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_svcctl_start_service( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hService, const char **parm_array, uint32 parmcount ) { @@ -326,7 +345,7 @@ WERROR cli_svcctl_start_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, in.parmcount = 0; in.parameters = NULL; - CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_START_SERVICE_W, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_START_SERVICE_W, in, out, qbuf, rbuf, svcctl_io_q_start_service, @@ -339,7 +358,7 @@ WERROR cli_svcctl_start_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, /******************************************************************* *******************************************************************/ -WERROR cli_svcctl_control_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_svcctl_control_service( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hService, uint32 control, SERVICE_STATUS *status ) { @@ -353,7 +372,7 @@ WERROR cli_svcctl_control_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, memcpy( &in.handle, hService, sizeof(POLICY_HND) ); in.control = control; - CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_CONTROL_SERVICE, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_CONTROL_SERVICE, in, out, qbuf, rbuf, svcctl_io_q_control_service, @@ -372,7 +391,7 @@ WERROR cli_svcctl_control_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, /******************************************************************* *******************************************************************/ -WERROR cli_svcctl_get_dispname( struct cli_state *cli, TALLOC_CTX *mem_ctx, +WERROR rpccli_svcctl_get_dispname( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, POLICY_HND *hService, fstring displayname ) { SVCCTL_Q_GET_DISPLAY_NAME in; @@ -385,7 +404,7 @@ WERROR cli_svcctl_get_dispname( struct cli_state *cli, TALLOC_CTX *mem_ctx, memcpy( &in.handle, hService, sizeof(POLICY_HND) ); in.display_name_len = 0; - CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_GET_DISPLAY_NAME, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_GET_DISPLAY_NAME, in, out, qbuf, rbuf, svcctl_io_q_get_display_name, @@ -397,7 +416,7 @@ WERROR cli_svcctl_get_dispname( struct cli_state *cli, TALLOC_CTX *mem_ctx, if ( W_ERROR_EQUAL( out.status, WERR_INSUFFICIENT_BUFFER ) ) { in.display_name_len = out.display_name_len; - CLI_DO_RPC( cli, mem_ctx, PI_SVCCTL, SVCCTL_GET_DISPLAY_NAME, + CLI_DO_RPC_WERR( cli, mem_ctx, PI_SVCCTL, SVCCTL_GET_DISPLAY_NAME, in, out, qbuf, rbuf, svcctl_io_q_get_display_name, @@ -412,4 +431,3 @@ WERROR cli_svcctl_get_dispname( struct cli_state *cli, TALLOC_CTX *mem_ctx, return out.status; } - diff --git a/source3/rpc_client/cli_wkssvc.c b/source3/rpc_client/cli_wkssvc.c index aea47443988..d8e97beb649 100644 --- a/source3/rpc_client/cli_wkssvc.c +++ b/source3/rpc_client/cli_wkssvc.c @@ -2,10 +2,10 @@ Unix SMB/CIFS implementation. NT Domain Authentication SMB / MSRPC client Copyright (C) Andrew Tridgell 1994-2000 - Copyright (C) Luke Kenneth Casson Leighton 1996-2000 Copyright (C) Tim Potter 2001 - Copytight (C) Rafal Szczesniak 2002 - + Copyright (C) Rafal Szczesniak 2002 + Copyright (C) Jeremy Allison 2005. + This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or @@ -33,61 +33,36 @@ * @return NTSTATUS of rpc call */ -NTSTATUS cli_wks_query_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, +NTSTATUS rpccli_wks_query_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, WKS_INFO_100 *wks100) { - prs_struct buf; + prs_struct qbuf; prs_struct rbuf; - WKS_Q_QUERY_INFO q_o; - WKS_R_QUERY_INFO r_o; + WKS_Q_QUERY_INFO q; + WKS_R_QUERY_INFO r; if (cli == NULL || wks100 == NULL) return NT_STATUS_UNSUCCESSFUL; - /* init rpc parse structures */ - prs_init(&buf, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL); - prs_init(&rbuf, 0, mem_ctx, UNMARSHALL); - DEBUG(4, ("WksQueryInfo\n")); /* init query structure with rpc call arguments */ - init_wks_q_query_info(&q_o, cli->desthost, 100); - - /* marshall data */ - if (!wks_io_q_query_info("", &q_o, &buf, 0)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return NT_STATUS_UNSUCCESSFUL; - } - - /* actual rpc call over \PIPE\wkssvc */ - if (!rpc_api_pipe_req(cli, PI_WKSSVC, WKS_QUERY_INFO, &buf, &rbuf)) { - prs_mem_free(&buf); - prs_mem_free(&rbuf); - return NT_STATUS_UNSUCCESSFUL; - } - - prs_mem_free(&buf); + init_wks_q_query_info(&q, cli->cli->desthost, 100); + r.wks100 = wks100; - r_o.wks100 = wks100; - - /* get call results from response buffer */ - if (!wks_io_r_query_info("", &r_o, &rbuf, 0)) { - prs_mem_free(&rbuf); - return NT_STATUS_UNSUCCESSFUL; - } - + CLI_DO_RPC(cli, mem_ctx, PI_WKSSVC, WKS_QUERY_INFO, + q, r, + qbuf, rbuf, + wks_io_q_query_info, + wks_io_r_query_info, + NT_STATUS_UNSUCCESSFUL); + /* check returnet status code */ - if (NT_STATUS_IS_ERR(r_o.status)) { + if (NT_STATUS_IS_ERR(r.status)) { /* report the error */ - DEBUG(0,("WKS_R_QUERY_INFO: %s\n", nt_errstr(r_o.status))); - prs_mem_free(&rbuf); - return r_o.status; + DEBUG(0,("WKS_R_QUERY_INFO: %s\n", nt_errstr(r.status))); + return r.status; } - /* do clean up */ - prs_mem_free(&rbuf); - return NT_STATUS_OK; } - diff --git a/source3/rpc_parse/parse_buffer.c b/source3/rpc_parse/parse_buffer.c index ff2a7cc2f6e..36d8eda8474 100644 --- a/source3/rpc_parse/parse_buffer.c +++ b/source3/rpc_parse/parse_buffer.c @@ -106,7 +106,7 @@ BOOL prs_rpcbuffer_p(const char *desc, prs_struct *ps, int depth, RPC_BUFFER **b /* caputure the pointer value to stream */ - data_p = (uint32) *buffer; + data_p = *buffer ? 0xf000baaa : 0; if ( !prs_uint32("ptr", ps, depth, &data_p )) return False; diff --git a/source3/rpc_parse/parse_dfs.c b/source3/rpc_parse/parse_dfs.c index 3f7b2a4cd59..f102e950042 100644 --- a/source3/rpc_parse/parse_dfs.c +++ b/source3/rpc_parse/parse_dfs.c @@ -22,8 +22,6 @@ */ #include "includes.h" -#include "nterr.h" -#include "rpc_parse.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_PARSE diff --git a/source3/rpc_parse/parse_ds.c b/source3/rpc_parse/parse_ds.c index 9155419ae43..c6131452226 100644 --- a/source3/rpc_parse/parse_ds.c +++ b/source3/rpc_parse/parse_ds.c @@ -24,12 +24,13 @@ /************************************************************************ ************************************************************************/ -static BOOL ds_io_dominfobasic( const char *desc, prs_struct *ps, int depth, DSROLE_PRIMARY_DOMAIN_INFO_BASIC **basic) +static BOOL ds_io_dominfobasic(const char *desc, DSROLE_PRIMARY_DOMAIN_INFO_BASIC **basic, prs_struct *ps, int depth) { DSROLE_PRIMARY_DOMAIN_INFO_BASIC *p = *basic; - if ( UNMARSHALLING(ps) ) + if ( UNMARSHALLING(ps) ) { p = *basic = PRS_ALLOC_MEM(ps, DSROLE_PRIMARY_DOMAIN_INFO_BASIC, 1); + } if ( !p ) return False; @@ -75,7 +76,7 @@ static BOOL ds_io_dominfobasic( const char *desc, prs_struct *ps, int depth, DSR /************************************************************************ ************************************************************************/ -BOOL ds_io_q_getprimdominfo( const char *desc, prs_struct *ps, int depth, DS_Q_GETPRIMDOMINFO *q_u) +BOOL ds_io_q_getprimdominfo( const char *desc, DS_Q_GETPRIMDOMINFO *q_u, prs_struct *ps, int depth) { prs_debug(ps, depth, desc, "ds_io_q_getprimdominfo"); depth++; @@ -92,7 +93,7 @@ BOOL ds_io_q_getprimdominfo( const char *desc, prs_struct *ps, int depth, DS_Q_G /************************************************************************ ************************************************************************/ -BOOL ds_io_r_getprimdominfo( const char *desc, prs_struct *ps, int depth, DS_R_GETPRIMDOMINFO *r_u) +BOOL ds_io_r_getprimdominfo( const char *desc, DS_R_GETPRIMDOMINFO *r_u, prs_struct *ps, int depth) { prs_debug(ps, depth, desc, "ds_io_r_getprimdominfo"); depth++; @@ -114,7 +115,7 @@ BOOL ds_io_r_getprimdominfo( const char *desc, prs_struct *ps, int depth, DS_R_G switch ( r_u->level ) { case DsRolePrimaryDomainInfoBasic: - if ( !ds_io_dominfobasic( "dominfobasic", ps, depth, &r_u->info.basic ) ) + if ( !ds_io_dominfobasic( "dominfobasic", &r_u->info.basic, ps, depth) ) return False; break; default: @@ -135,8 +136,7 @@ BOOL ds_io_r_getprimdominfo( const char *desc, prs_struct *ps, int depth, DS_R_G initialize a DS_ENUM_DOM_TRUSTS structure ************************************************************************/ -BOOL init_q_ds_enum_domain_trusts( DS_Q_ENUM_DOM_TRUSTS *q, const char *server, - uint32 flags ) +BOOL init_q_ds_enum_domain_trusts( DS_Q_ENUM_DOM_TRUSTS *q, const char *server, uint32 flags ) { q->flags = flags; @@ -153,7 +153,7 @@ BOOL init_q_ds_enum_domain_trusts( DS_Q_ENUM_DOM_TRUSTS *q, const char *server, /************************************************************************ ************************************************************************/ -static BOOL ds_io_domain_trusts( const char *desc, prs_struct *ps, int depth, DS_DOMAIN_TRUSTS *trust) +static BOOL ds_io_domain_trusts( const char *desc, DS_DOMAIN_TRUSTS *trust, prs_struct *ps, int depth) { prs_debug(ps, depth, desc, "ds_io_dom_trusts_ctr"); depth++; @@ -188,7 +188,7 @@ static BOOL ds_io_domain_trusts( const char *desc, prs_struct *ps, int depth, DS /************************************************************************ ************************************************************************/ -static BOOL ds_io_dom_trusts_ctr( const char *desc, prs_struct *ps, int depth, DS_DOMAIN_TRUSTS_CTR *ctr) +static BOOL ds_io_dom_trusts_ctr( const char *desc, DS_DOMAIN_TRUSTS_CTR *ctr, prs_struct *ps, int depth) { int i; @@ -217,7 +217,7 @@ static BOOL ds_io_dom_trusts_ctr( const char *desc, prs_struct *ps, int depth, D we need another loop to read the UNISTR2's and SID's */ for ( i=0; imax_count;i++ ) { - if ( !ds_io_domain_trusts("domain_trusts", ps, depth, &ctr->trusts[i] ) ) + if ( !ds_io_domain_trusts("domain_trusts", &ctr->trusts[i], ps, depth) ) return False; } @@ -248,7 +248,7 @@ static BOOL ds_io_dom_trusts_ctr( const char *desc, prs_struct *ps, int depth, D initialize a DS_ENUM_DOM_TRUSTS request ************************************************************************/ -BOOL ds_io_q_enum_domain_trusts( const char *desc, prs_struct *ps, int depth, DS_Q_ENUM_DOM_TRUSTS *q_u) +BOOL ds_io_q_enum_domain_trusts( const char *desc, DS_Q_ENUM_DOM_TRUSTS *q_u, prs_struct *ps, int depth) { prs_debug(ps, depth, desc, "ds_io_q_enum_domain_trusts"); depth++; @@ -274,7 +274,7 @@ BOOL ds_io_q_enum_domain_trusts( const char *desc, prs_struct *ps, int depth, DS /************************************************************************ ************************************************************************/ -BOOL ds_io_r_enum_domain_trusts( const char *desc, prs_struct *ps, int depth, DS_R_ENUM_DOM_TRUSTS *r_u) +BOOL ds_io_r_enum_domain_trusts( const char *desc, DS_R_ENUM_DOM_TRUSTS *r_u, prs_struct *ps, int depth) { prs_debug(ps, depth, desc, "ds_io_r_enum_domain_trusts"); depth++; @@ -286,7 +286,7 @@ BOOL ds_io_r_enum_domain_trusts( const char *desc, prs_struct *ps, int depth, DS return False; if ( r_u->num_domains ) { - if ( !ds_io_dom_trusts_ctr("domains", ps, depth, &r_u->domains ) ) + if ( !ds_io_dom_trusts_ctr("domains", &r_u->domains, ps, depth) ) return False; } @@ -298,5 +298,3 @@ BOOL ds_io_r_enum_domain_trusts( const char *desc, prs_struct *ps, int depth, DS return True; } - - diff --git a/source3/rpc_parse/parse_echo.c b/source3/rpc_parse/parse_echo.c index b4aa8de24ab..48dda7b1715 100644 --- a/source3/rpc_parse/parse_echo.c +++ b/source3/rpc_parse/parse_echo.c @@ -21,8 +21,6 @@ */ #include "includes.h" -#include "nterr.h" -#include "rpc_parse.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_PARSE diff --git a/source3/rpc_parse/parse_eventlog.c b/source3/rpc_parse/parse_eventlog.c index 734f52fffb3..1b57272ca4c 100644 --- a/source3/rpc_parse/parse_eventlog.c +++ b/source3/rpc_parse/parse_eventlog.c @@ -23,9 +23,24 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_PARSE -/* - * called from eventlog_q_open_eventlog (srv_eventlog.c) - */ +/******************************************************************** +********************************************************************/ + +BOOL prs_ev_open_unknown0( const char *desc, prs_struct *ps, int depth, EVENTLOG_OPEN_UNKNOWN0 *u ) +{ + if ( !u ) + return False; + + if ( !prs_uint16("", ps, depth, &u->unknown1) ) + return False; + if ( !prs_uint16("", ps, depth, &u->unknown2) ) + return False; + + return True; +} + +/******************************************************************** +********************************************************************/ BOOL eventlog_io_q_open_eventlog(const char *desc, EVENTLOG_Q_OPEN_EVENTLOG *q_u, prs_struct *ps, int depth) @@ -33,62 +48,28 @@ BOOL eventlog_io_q_open_eventlog(const char *desc, EVENTLOG_Q_OPEN_EVENTLOG *q_u if(q_u == NULL) return False; - /** Data format seems to be: - UNKNOWN structure - uint32 unknown - uint16 unknown - uint16 unknown - Eventlog name - uint16 eventlog name length - uint16 eventlog name size - Character Array - uint32 unknown - uint32 max count - uint32 offset - uint32 actual count - UNISTR2 log file name - Server Name - uint16 server name length - uint16 server name size - Character Array - UNISTR2 server name - */ - prs_debug(ps, depth, desc, "eventlog_io_q_open_eventlog"); depth++; if(!prs_align(ps)) return False; - /* Munch unknown bits */ - - if(!prs_uint32("", ps, depth, &q_u->unknown1)) - return False; - if(!prs_uint16("", ps, depth, &q_u->unknown2)) - return False; - if(!prs_uint16("", ps, depth, &q_u->unknown3)) - return False; - if(!prs_align(ps)) + if ( !prs_pointer("", ps, depth, (void**)&q_u->unknown0, sizeof(EVENTLOG_OPEN_UNKNOWN0), (PRS_POINTER_CAST)prs_ev_open_unknown0)) return False; - /* Get name of log source */ - - if(!prs_uint16("sourcename_length", ps, depth, &q_u->sourcename_length)) - return False; - if(!prs_uint16("sourcename_size", ps, depth, &q_u->sourcename_size)) + if ( !prs_unistr4("logname", ps, depth, &q_u->logname) ) return False; - if(!prs_uint32("sourcename_ptr", ps, depth, &q_u->sourcename_ptr)) + if ( !prs_align(ps) ) return False; - if(!smb_io_unistr2("", &q_u->sourcename, q_u->sourcename_ptr, ps, depth)) + + if ( !prs_unistr4("servername", ps, depth, &q_u->servername) ) return False; - if(!prs_align(ps)) + if ( !prs_align(ps) ) return False; - /* Get server name */ - - if(!prs_uint32("servername_ptr", ps, depth, &q_u->servername_ptr)) + if ( !prs_uint32("unknown1", ps, depth, &q_u->unknown1) ) return False; - if(!smb_io_unistr2("", &q_u->servername, q_u->servername_ptr, ps, depth)) + if ( !prs_uint32("unknown2", ps, depth, &q_u->unknown2) ) return False; return True; @@ -424,17 +405,8 @@ BOOL eventlog_io_q_clear_eventlog(const char *desc, EVENTLOG_Q_CLEAR_EVENTLOG *q return False; if(!(smb_io_pol_hnd("log handle", &(q_u->handle), ps, depth))) return False; - if(!prs_align(ps)) - return False; - if(!(prs_uint32("unknown1", ps, depth, &q_u->unknown1))) - return False; - if(!(prs_uint16("backup_file_length", ps, depth, &q_u->backup_file_length))) - return False; - if(!(prs_uint16("backup_file_size", ps, depth, &q_u->backup_file_size))) - return False; - if(!prs_uint32("backup_file_ptr", ps, depth, &q_u->backup_file_ptr)) - return False; - if(!smb_io_unistr2("backup file", &q_u->backup_file, q_u->backup_file_ptr, ps, depth)) + + if ( !prs_unistr4("backupfile", ps, depth, &q_u->backupfile) ) return False; return True; diff --git a/source3/rpc_parse/parse_misc.c b/source3/rpc_parse/parse_misc.c index 921e366f11a..8bbb97f226d 100644 --- a/source3/rpc_parse/parse_misc.c +++ b/source3/rpc_parse/parse_misc.c @@ -296,7 +296,7 @@ BOOL smb_io_dom_sid2_p(const char *desc, prs_struct *ps, int depth, DOM_SID2 **s /* caputure the pointer value to stream */ - data_p = (uint32) *sid2; + data_p = *sid2 ? 0xf000baaa : 0; if ( !prs_uint32("dom_sid2_p", ps, depth, &data_p )) return False; @@ -1003,7 +1003,7 @@ BOOL prs_io_unistr2_p(const char *desc, prs_struct *ps, int depth, UNISTR2 **uni /* caputure the pointer value to stream */ - data_p = (uint32) *uni2; + data_p = *uni2 ? 0xf000baaa : 0; if ( !prs_uint32("ptr", ps, depth, &data_p )) return False; @@ -1038,7 +1038,7 @@ BOOL prs_io_unistr2(const char *desc, prs_struct *ps, int depth, UNISTR2 *uni2 ) /* just pass off to smb_io_unstr2() passing the uni2 address as the pointer (like you would expect) */ - return smb_io_unistr2( desc, uni2, (uint32)uni2, ps, depth ); + return smb_io_unistr2( desc, uni2, uni2 ? 1 : 0, ps, depth ); } /******************************************************************* @@ -1139,7 +1139,7 @@ BOOL prs_unistr4_str(const char *desc, prs_struct *ps, int depth, UNISTR4 *uni4) } /******************************************************************* - Reads or writes a UNISTR2_ARRAY structure. + Reads or writes a UNISTR4_ARRAY structure. ********************************************************************/ BOOL prs_unistr4_array(const char *desc, prs_struct *ps, int depth, UNISTR4_ARRAY *array ) diff --git a/source3/rpc_parse/parse_net.c b/source3/rpc_parse/parse_net.c index 3a050148c9f..35533e360a1 100644 --- a/source3/rpc_parse/parse_net.c +++ b/source3/rpc_parse/parse_net.c @@ -671,7 +671,7 @@ BOOL net_io_q_trust_dom(const char *desc, NET_Q_TRUST_DOM_LIST *q_l, prs_struct void init_q_req_chal(NET_Q_REQ_CHAL *q_c, const char *logon_srv, const char *logon_clnt, - DOM_CHAL *clnt_chal) + const DOM_CHAL *clnt_chal) { DEBUG(5,("init_q_req_chal: %d\n", __LINE__)); @@ -860,7 +860,7 @@ BOOL net_io_r_auth_2(const char *desc, NET_R_AUTH_2 *r_a, prs_struct *ps, int de void init_q_auth_3(NET_Q_AUTH_3 *q_a, const char *logon_srv, const char *acct_name, uint16 sec_chan, const char *comp_name, - DOM_CHAL *clnt_chal, uint32 clnt_flgs) + const DOM_CHAL *clnt_chal, uint32 clnt_flgs) { DEBUG(5,("init_q_auth_3: %d\n", __LINE__)); @@ -1496,7 +1496,7 @@ void init_net_user_info3(TALLOC_CTX *ctx, NET_USER_INFO_3 *usr, ********************************************************************/ BOOL net_io_user_info3(const char *desc, NET_USER_INFO_3 *usr, prs_struct *ps, - int depth, uint16 validation_level) + int depth, uint16 validation_level, BOOL kerb_validation_level) { unsigned int i; @@ -1595,6 +1595,18 @@ BOOL net_io_user_info3(const char *desc, NET_USER_INFO_3 *usr, prs_struct *ps, } } + /* get kerb validation info (not really part of user_info_3) - Guenther */ + + if (kerb_validation_level) { + + if(!prs_uint32("ptr_res_group_dom_sid", ps, depth, &usr->ptr_res_group_dom_sid)) + return False; + if(!prs_uint32("res_group_count", ps, depth, &usr->res_group_count)) + return False; + if(!prs_uint32("ptr_res_groups", ps, depth, &usr->ptr_res_groups)) + return False; + } + if(!smb_io_unistr2("uni_user_name", &usr->uni_user_name, usr->hdr_user_name.buffer, ps, depth)) /* username unicode string */ return False; if(!smb_io_unistr2("uni_full_name", &usr->uni_full_name, usr->hdr_full_name.buffer, ps, depth)) /* user's full name unicode string */ @@ -1636,6 +1648,11 @@ BOOL net_io_user_info3(const char *desc, NET_USER_INFO_3 *usr, prs_struct *ps, uint32 num_other_sids = usr->num_other_sids; + if (!(usr->user_flgs & LOGON_EXTRA_SIDS)) { + DEBUG(10,("net_io_user_info3: user_flgs attribute does not have LOGON_EXTRA_SIDS\n")); + /* return False; */ + } + if (!prs_uint32("num_other_sids", ps, depth, &num_other_sids)) return False; @@ -1724,8 +1741,10 @@ BOOL net_io_r_sam_logon(const char *desc, NET_R_SAM_LOGON *r_l, prs_struct *ps, if(!prs_uint32("buffer_creds", ps, depth, &r_l->buffer_creds)) /* undocumented buffer pointer */ return False; - if(!smb_io_cred("", &r_l->srv_creds, ps, depth)) /* server credentials. server time stamp appears to be ignored. */ - return False; + if (&r_l->buffer_creds) { + if(!smb_io_cred("", &r_l->srv_creds, ps, depth)) /* server credentials. server time stamp appears to be ignored. */ + return False; + } if(!prs_uint16("switch_value", ps, depth, &r_l->switch_value)) return False; @@ -1733,11 +1752,11 @@ BOOL net_io_r_sam_logon(const char *desc, NET_R_SAM_LOGON *r_l, prs_struct *ps, return False; #if 1 /* W2k always needs this - even for bad passwd. JRA */ - if(!net_io_user_info3("", r_l->user, ps, depth, r_l->switch_value)) + if(!net_io_user_info3("", r_l->user, ps, depth, r_l->switch_value, False)) return False; #else if (r_l->switch_value != 0) { - if(!net_io_user_info3("", r_l->user, ps, depth, r_l->switch_value)) + if(!net_io_user_info3("", r_l->user, ps, depth, r_l->switch_value, False)) return False; } #endif @@ -2139,9 +2158,8 @@ BOOL make_sam_account_info(SAM_ACCOUNT_INFO * info, /******************************************************************* reads or writes a structure. ********************************************************************/ -static BOOL net_io_sam_account_info(const char *desc, uint8 sess_key[16], - SAM_ACCOUNT_INFO * info, prs_struct *ps, - int depth) +static BOOL net_io_sam_account_info(const char *desc, SAM_ACCOUNT_INFO *info, + prs_struct *ps, int depth) { BUFHDR2 hdr_priv_data; uint32 i; @@ -2295,7 +2313,7 @@ static BOOL net_io_sam_account_info(const char *desc, uint8 sess_key[16], if (ps->io) { /* reading */ - if (!prs_hash1(ps, ps->data_offset, sess_key, len)) + if (!prs_hash1(ps, ps->data_offset, len)) return False; } if (!net_io_sam_passwd_info("pass", &info->pass, @@ -2305,7 +2323,7 @@ static BOOL net_io_sam_account_info(const char *desc, uint8 sess_key[16], if (!ps->io) { /* writing */ - if (!prs_hash1(ps, old_offset, sess_key, len)) + if (!prs_hash1(ps, old_offset, len)) return False; } } @@ -2834,7 +2852,7 @@ static BOOL net_io_sam_privs_info(const char *desc, SAM_DELTA_PRIVS *info, /******************************************************************* reads or writes a structure. ********************************************************************/ -static BOOL net_io_sam_delta_ctr(const char *desc, uint8 sess_key[16], +static BOOL net_io_sam_delta_ctr(const char *desc, SAM_DELTA_CTR * delta, uint16 type, prs_struct *ps, int depth) { @@ -2859,7 +2877,7 @@ static BOOL net_io_sam_delta_ctr(const char *desc, uint8 sess_key[16], break; case SAM_DELTA_ACCOUNT_INFO: - if (!net_io_sam_account_info("", sess_key, &delta->account_info, ps, depth)) + if (!net_io_sam_account_info("", &delta->account_info, ps, depth)) return False; break; @@ -2912,7 +2930,7 @@ static BOOL net_io_sam_delta_ctr(const char *desc, uint8 sess_key[16], /******************************************************************* reads or writes a structure. ********************************************************************/ -BOOL net_io_r_sam_sync(const char *desc, uint8 sess_key[16], +BOOL net_io_r_sam_sync(const char *desc, NET_R_SAM_SYNC * r_s, prs_struct *ps, int depth) { uint32 i; @@ -2976,7 +2994,7 @@ BOOL net_io_r_sam_sync(const char *desc, uint8 sess_key[16], for (i = 0; i < r_s->num_deltas2; i++) { if (!net_io_sam_delta_ctr( - "", sess_key, &r_s->deltas[i], + "", &r_s->deltas[i], r_s->hdr_deltas[i].type3, ps, depth)) { DEBUG(0, ("hmm, failed on i=%d\n", i)); @@ -3048,7 +3066,7 @@ BOOL net_io_q_sam_deltas(const char *desc, NET_Q_SAM_DELTAS *q_s, prs_struct *ps /******************************************************************* reads or writes a structure. ********************************************************************/ -BOOL net_io_r_sam_deltas(const char *desc, uint8 sess_key[16], +BOOL net_io_r_sam_deltas(const char *desc, NET_R_SAM_DELTAS *r_s, prs_struct *ps, int depth) { unsigned int i; @@ -3104,7 +3122,7 @@ BOOL net_io_r_sam_deltas(const char *desc, uint8 sess_key[16], for (i = 0; i < r_s->num_deltas; i++) { if (!net_io_sam_delta_ctr( - "", sess_key, + "", &r_s->deltas[i], r_s->hdr_deltas[i].type2, ps, depth)) diff --git a/source3/rpc_parse/parse_ntsvcs.c b/source3/rpc_parse/parse_ntsvcs.c new file mode 100644 index 00000000000..f2e44560252 --- /dev/null +++ b/source3/rpc_parse/parse_ntsvcs.c @@ -0,0 +1,415 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Gerald (Jerry) Carter 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" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_PARSE + +/******************************************************************* +********************************************************************/ + +BOOL ntsvcs_io_q_get_version(const char *desc, NTSVCS_Q_GET_VERSION *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "ntsvcs_io_q_get_version"); + depth++; + + /* there is nothing to parse in this PDU */ + + return True; + +} + +/******************************************************************* +********************************************************************/ + +BOOL ntsvcs_io_r_get_version(const char *desc, NTSVCS_R_GET_VERSION *r_u, prs_struct *ps, int depth) +{ + if ( !r_u ) + return False; + + prs_debug(ps, depth, desc, "ntsvcs_io_r_get_version"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("version", ps, depth, &r_u->version)) + return False; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL ntsvcs_io_q_get_device_list_size(const char *desc, NTSVCS_Q_GET_DEVICE_LIST_SIZE *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "ntsvcs_io_q_get_device_list_size"); + depth++; + + if(!prs_align(ps)) + return False; + + if ( !prs_pointer("devicename", ps, depth, (void**)&q_u->devicename, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2) ) + return False; + if( !prs_align(ps) ) + return False; + + if ( !prs_uint32("flags", ps, depth, &q_u->flags) ) + return False; + + return True; + +} + +/******************************************************************* +********************************************************************/ + +BOOL ntsvcs_io_r_get_device_list_size(const char *desc, NTSVCS_R_GET_DEVICE_LIST_SIZE *r_u, prs_struct *ps, int depth) +{ + if ( !r_u ) + return False; + + prs_debug(ps, depth, desc, "ntsvcs_io_r_get_device_list_size"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!prs_uint32("size", ps, depth, &r_u->size)) + return False; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + + +/******************************************************************* +********************************************************************/ + +BOOL ntsvcs_io_q_get_device_list(const char *desc, NTSVCS_Q_GET_DEVICE_LIST *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "ntsvcs_io_q_get_device_list"); + depth++; + + if(!prs_align(ps)) + return False; + + if ( !prs_pointer("devicename", ps, depth, (void**)&q_u->devicename, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2) ) + return False; + if( !prs_align(ps) ) + return False; + + if ( !prs_uint32("buffer_size", ps, depth, &q_u->buffer_size) ) + return False; + if ( !prs_uint32("flags", ps, depth, &q_u->flags) ) + return False; + + return True; + +} + +/******************************************************************* +********************************************************************/ + +BOOL ntsvcs_io_r_get_device_list(const char *desc, NTSVCS_R_GET_DEVICE_LIST *r_u, prs_struct *ps, int depth) +{ + if ( !r_u ) + return False; + + prs_debug(ps, depth, desc, "ntsvcs_io_r_get_device_list_size"); + depth++; + + if(!prs_align(ps)) + return False; + + if ( !prs_io_unistr2("devicepath", ps, depth, &r_u->devicepath) ) + return False; + if(!prs_align(ps)) + return False; + + if(!prs_uint32("needed", ps, depth, &r_u->needed)) + return False; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL ntsvcs_io_q_validate_device_instance(const char *desc, NTSVCS_Q_VALIDATE_DEVICE_INSTANCE *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "ntsvcs_io_q_validate_device_instance"); + depth++; + + if(!prs_align(ps)) + return False; + + if ( !prs_io_unistr2("devicepath", ps, depth, &q_u->devicepath) ) + return False; + if( !prs_align(ps) ) + return False; + + if ( !prs_uint32("flags", ps, depth, &q_u->flags) ) + return False; + + return True; + +} + +/******************************************************************* +********************************************************************/ + +BOOL ntsvcs_io_r_validate_device_instance(const char *desc, NTSVCS_R_VALIDATE_DEVICE_INSTANCE *r_u, prs_struct *ps, int depth) +{ + if ( !r_u ) + return False; + + prs_debug(ps, depth, desc, "ntsvcs_io_r_validate_device_instance"); + depth++; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL ntsvcs_io_q_get_device_reg_property(const char *desc, NTSVCS_Q_GET_DEVICE_REG_PROPERTY *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "ntsvcs_io_q_get_device_reg_property"); + depth++; + + if(!prs_align(ps)) + return False; + + if ( !prs_io_unistr2("devicepath", ps, depth, &q_u->devicepath) ) + return False; + if( !prs_align(ps) ) + return False; + + if ( !prs_uint32("property", ps, depth, &q_u->property) ) + return False; + if ( !prs_uint32("unknown2", ps, depth, &q_u->unknown2) ) + return False; + if ( !prs_uint32("buffer_size1", ps, depth, &q_u->buffer_size1) ) + return False; + if ( !prs_uint32("buffer_size2", ps, depth, &q_u->buffer_size2) ) + return False; + if ( !prs_uint32("unknown5", ps, depth, &q_u->unknown5) ) + return False; + + return True; + +} + +/******************************************************************* +********************************************************************/ + +BOOL ntsvcs_io_r_get_device_reg_property(const char *desc, NTSVCS_R_GET_DEVICE_REG_PROPERTY *r_u, prs_struct *ps, int depth) +{ + if ( !r_u ) + return False; + + prs_debug(ps, depth, desc, "ntsvcs_io_r_get_device_reg_property"); + depth++; + + if ( !prs_align(ps) ) + return False; + + if ( !prs_uint32("unknown1", ps, depth, &r_u->unknown1) ) + return False; + + if ( !smb_io_regval_buffer("value", ps, depth, &r_u->value) ) + return False; + if ( !prs_align(ps) ) + return False; + + if ( !prs_uint32("size", ps, depth, &r_u->size) ) + return False; + + if ( !prs_uint32("needed", ps, depth, &r_u->needed) ) + return False; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL ntsvcs_io_q_get_hw_profile_info(const char *desc, NTSVCS_Q_GET_HW_PROFILE_INFO *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "ntsvcs_io_q_get_hw_profile_info"); + depth++; + + if(!prs_align(ps)) + return False; + + if ( !prs_uint32("index", ps, depth, &q_u->index) ) + return False; + + q_u->buffer_size = 0x000000a8; + + if ( UNMARSHALLING(ps) ) + q_u->buffer = TALLOC_ARRAY(get_talloc_ctx(), uint8, q_u->buffer_size ); + + if ( !prs_uint8s(True, "buffer", ps, depth, q_u->buffer, q_u->buffer_size) ) + return False; + + if ( !prs_uint32("buffer_size", ps, depth, &q_u->buffer_size) ) + return False; + + if ( !prs_uint32("unknown1", ps, depth, &q_u->unknown1) ) + return False; + + return True; + +} + +/******************************************************************* +********************************************************************/ + +BOOL ntsvcs_io_r_get_hw_profile_info(const char *desc, NTSVCS_R_GET_HW_PROFILE_INFO *r_u, prs_struct *ps, int depth) +{ + if ( !r_u ) + return False; + + prs_debug(ps, depth, desc, "ntsvcs_io_r_get_device_reg_property"); + depth++; + + if ( !prs_align(ps) ) + return False; + + if ( UNMARSHALLING(ps) ) + r_u->buffer = TALLOC_ARRAY(get_talloc_ctx(), uint8, r_u->buffer_size ); + + if ( !prs_uint8s(True, "buffer", ps, depth, r_u->buffer, r_u->buffer_size) ) + return False; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL ntsvcs_io_q_hw_profile_flags(const char *desc, NTSVCS_Q_HW_PROFILE_FLAGS *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "ntsvcs_io_q_hw_profile_flags"); + depth++; + + if(!prs_align(ps)) + return False; + + if ( !prs_uint32("unknown1", ps, depth, &q_u->unknown1) ) + return False; + + + if ( !prs_io_unistr2("devicepath", ps, depth, &q_u->devicepath) ) + return False; + if( !prs_align(ps) ) + return False; + + if ( !prs_uint32("unknown2", ps, depth, &q_u->unknown2) ) + return False; + if ( !prs_uint32("unknown3", ps, depth, &q_u->unknown3) ) + return False; + if ( !prs_uint32("unknown4", ps, depth, &q_u->unknown4) ) + return False; + if ( !prs_uint32("unknown5", ps, depth, &q_u->unknown5) ) + return False; + if ( !prs_uint32("unknown6", ps, depth, &q_u->unknown6) ) + return False; + if ( !prs_uint32("unknown7", ps, depth, &q_u->unknown7) ) + return False; + + if ( !prs_uint32("unknown1", ps, depth, &q_u->unknown1) ) + return False; + + return True; + +} + +/******************************************************************* +********************************************************************/ + +BOOL ntsvcs_io_r_hw_profile_flags(const char *desc, NTSVCS_R_HW_PROFILE_FLAGS *r_u, prs_struct *ps, int depth) +{ + if ( !r_u ) + return False; + + prs_debug(ps, depth, desc, "ntsvcs_io_r_hw_profile_flags"); + depth++; + + if ( !prs_align(ps) ) + return False; + + if ( !prs_uint32("unknown1", ps, depth, &r_u->unknown1) ) + return False; + if ( !prs_uint32("unknown2", ps, depth, &r_u->unknown2) ) + return False; + if ( !prs_uint32("unknown3", ps, depth, &r_u->unknown3) ) + return False; + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + + + + diff --git a/source3/rpc_parse/parse_prs.c b/source3/rpc_parse/parse_prs.c index 709a5d39af6..d174bad444d 100644 --- a/source3/rpc_parse/parse_prs.c +++ b/source3/rpc_parse/parse_prs.c @@ -34,7 +34,6 @@ void prs_dump(char *name, int v, prs_struct *ps) prs_dump_region(name, v, ps, ps->data_offset, ps->buffer_size); } - /** * Dump from the start of the prs to the current location. **/ @@ -43,7 +42,6 @@ void prs_dump_before(char *name, int v, prs_struct *ps) prs_dump_region(name, v, ps, 0, ps->data_offset); } - /** * Dump everything from the start of the prs up to the current location. **/ @@ -52,6 +50,7 @@ void prs_dump_region(char *name, int v, prs_struct *ps, { int fd, i; pstring fname; + ssize_t sz; if (DEBUGLEVEL < 50) return; for (i=1;i<100;i++) { if (v != -1) { @@ -63,26 +62,28 @@ void prs_dump_region(char *name, int v, prs_struct *ps, if (fd != -1 || errno != EEXIST) break; } if (fd != -1) { - write(fd, ps->data_p + from_off, to_off - from_off); - close(fd); - DEBUG(0,("created %s\n", fname)); + sz = write(fd, ps->data_p + from_off, to_off - from_off); + i = close(fd); + if ( (sz != to_off-from_off) || (i != 0) ) { + DEBUG(0,("Error writing/closing %s: %ld!=%ld %d\n", fname, (unsigned long)sz, (unsigned long)to_off-from_off, i )); + } else { + DEBUG(0,("created %s\n", fname)); + } } } - - /******************************************************************* - debug output for parsing info. + Debug output for parsing info - XXXX side-effect of this function is to increase the debug depth XXXX + XXXX side-effect of this function is to increase the debug depth XXXX. + +********************************************************************/ - ********************************************************************/ void prs_debug(prs_struct *ps, int depth, const char *desc, const char *fn_name) { DEBUG(5+depth, ("%s%06x %s %s\n", tab_depth(depth), ps->data_offset, fn_name, desc)); } - /** * Initialise an expandable parse structure. * @@ -91,6 +92,7 @@ void prs_debug(prs_struct *ps, int depth, const char *desc, const char *fn_name) * * @return False if allocation fails, otherwise True. **/ + BOOL prs_init(prs_struct *ps, uint32 size, TALLOC_CTX *ctx, BOOL io) { ZERO_STRUCTP(ps); @@ -111,6 +113,9 @@ BOOL prs_init(prs_struct *ps, uint32 size, TALLOC_CTX *ctx, BOOL io) } memset(ps->data_p, '\0', (size_t)size); ps->is_dynamic = True; /* We own this memory. */ + } else if (MARSHALLING(ps)) { + /* If size is zero and we're marshalling we should allocate memory on demand. */ + ps->is_dynamic = True; } return True; @@ -254,7 +259,7 @@ BOOL prs_grow(prs_struct *ps, uint32 extra_space) * is greater. */ - new_size = MAX(MAX_PDU_FRAG_LEN,extra_space); + new_size = MAX(RPC_MAX_PDU_FRAG_LEN,extra_space); if((new_data = SMB_MALLOC(new_size)) == NULL) { DEBUG(0,("prs_grow: Malloc failure for size %u.\n", (unsigned int)new_size)); @@ -398,7 +403,7 @@ BOOL prs_append_some_prs_data(prs_struct *dst, prs_struct *src, int32 start, uin Append the data from a buffer into a parse_struct. ********************************************************************/ -BOOL prs_copy_data_in(prs_struct *dst, char *src, uint32 len) +BOOL prs_copy_data_in(prs_struct *dst, const char *src, uint32 len) { if (len == 0) return True; @@ -564,6 +569,15 @@ void prs_force_dynamic(prs_struct *ps) ps->is_dynamic=True; } +/******************************************************************* + Associate a session key with a parse struct. + ********************************************************************/ + +void prs_set_session_key(prs_struct *ps, const char sess_key[16]) +{ + ps->sess_key = sess_key; +} + /******************************************************************* Stream a uint8. ********************************************************************/ @@ -596,9 +610,9 @@ BOOL prs_pointer( const char *name, prs_struct *ps, int depth, { uint32 data_p; - /* caputure the pointer value to stream */ + /* output f000baaa to stream if the pointer is non-zero. */ - data_p = (uint32) *data; + data_p = *data ? 0xf000baaa : 0; if ( !prs_uint32("ptr", ps, depth, &data_p )) return False; @@ -1387,7 +1401,7 @@ int tdb_prs_fetch(TDB_CONTEXT *tdb, char *keystr, prs_struct *ps, TALLOC_CTX *me hash a stream. ********************************************************************/ -BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16], int len) +BOOL prs_hash1(prs_struct *ps, uint32 offset, int len) { char *q; @@ -1396,10 +1410,10 @@ BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16], int len) #ifdef DEBUG_PASSWORD DEBUG(100, ("prs_hash1\n")); - dump_data(100, sess_key, 16); + dump_data(100, ps->sess_key, 16); dump_data(100, q, len); #endif - SamOEMhash((uchar *) q, sess_key, len); + SamOEMhash((uchar *) q, ps->sess_key, len); #ifdef DEBUG_PASSWORD dump_data(100, q, len); @@ -1413,9 +1427,9 @@ BOOL prs_hash1(prs_struct *ps, uint32 offset, uint8 sess_key[16], int len) MD5 it with the session key. ********************************************************************/ -static void netsec_digest(struct netsec_auth_struct *a, - int auth_flags, - RPC_AUTH_NETSEC_CHK * verf, +static void schannel_digest(struct schannel_auth_struct *a, + enum pipe_auth_level auth_level, + RPC_AUTH_SCHANNEL_CHK * verf, char *data, size_t data_len, uchar digest_final[16]) { @@ -1429,7 +1443,7 @@ static void netsec_digest(struct netsec_auth_struct *a, out of order */ MD5Update(&ctx3, zeros, sizeof(zeros)); MD5Update(&ctx3, verf->sig, sizeof(verf->sig)); - if (auth_flags & AUTH_PIPE_SEAL) { + if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) { MD5Update(&ctx3, verf->confounder, sizeof(verf->confounder)); } MD5Update(&ctx3, (const unsigned char *)data, data_len); @@ -1445,8 +1459,8 @@ static void netsec_digest(struct netsec_auth_struct *a, Calculate the key with which to encode the data payload ********************************************************************/ -static void netsec_get_sealing_key(struct netsec_auth_struct *a, - RPC_AUTH_NETSEC_CHK *verf, +static void schannel_get_sealing_key(struct schannel_auth_struct *a, + RPC_AUTH_SCHANNEL_CHK *verf, uchar sealing_key[16]) { static uchar zeros[4]; @@ -1473,8 +1487,8 @@ static void netsec_get_sealing_key(struct netsec_auth_struct *a, Encode or Decode the sequence number (which is symmetric) ********************************************************************/ -static void netsec_deal_with_seq_num(struct netsec_auth_struct *a, - RPC_AUTH_NETSEC_CHK *verf) +static void schannel_deal_with_seq_num(struct schannel_auth_struct *a, + RPC_AUTH_SCHANNEL_CHK *verf) { static uchar zeros[4]; uchar sequence_key[16]; @@ -1493,10 +1507,10 @@ static void netsec_deal_with_seq_num(struct netsec_auth_struct *a, } /******************************************************************* -creates an RPC_AUTH_NETSEC_CHK structure. +creates an RPC_AUTH_SCHANNEL_CHK structure. ********************************************************************/ -static BOOL init_rpc_auth_netsec_chk(RPC_AUTH_NETSEC_CHK * chk, +static BOOL init_rpc_auth_schannel_chk(RPC_AUTH_SCHANNEL_CHK * chk, const uchar sig[8], const uchar packet_digest[8], const uchar seq_num[8], const uchar confounder[8]) @@ -1513,15 +1527,15 @@ static BOOL init_rpc_auth_netsec_chk(RPC_AUTH_NETSEC_CHK * chk, } /******************************************************************* - Encode a blob of data using the netsec (schannel) alogrithm, also produceing + Encode a blob of data using the schannel alogrithm, also produceing a checksum over the original data. We currently only support signing and sealing togeather - the signing-only code is close, but not quite compatible with what MS does. ********************************************************************/ -void netsec_encode(struct netsec_auth_struct *a, int auth_flags, - enum netsec_direction direction, - RPC_AUTH_NETSEC_CHK * verf, +void schannel_encode(struct schannel_auth_struct *a, enum pipe_auth_level auth_level, + enum schannel_direction direction, + RPC_AUTH_SCHANNEL_CHK * verf, char *data, size_t data_len) { uchar digest_final[16]; @@ -1529,16 +1543,16 @@ void netsec_encode(struct netsec_auth_struct *a, int auth_flags, uchar seq_num[8]; static const uchar nullbytes[8]; - static const uchar netsec_seal_sig[8] = NETSEC_SEAL_SIGNATURE; - static const uchar netsec_sign_sig[8] = NETSEC_SIGN_SIGNATURE; - const uchar *netsec_sig = NULL; + static const uchar schannel_seal_sig[8] = SCHANNEL_SEAL_SIGNATURE; + static const uchar schannel_sign_sig[8] = SCHANNEL_SIGN_SIGNATURE; + const uchar *schannel_sig = NULL; - DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len)); + DEBUG(10,("SCHANNEL: schannel_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len)); - if (auth_flags & AUTH_PIPE_SEAL) { - netsec_sig = netsec_seal_sig; - } else if (auth_flags & AUTH_PIPE_SIGN) { - netsec_sig = netsec_sign_sig; + if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) { + schannel_sig = schannel_seal_sig; + } else { + schannel_sig = schannel_sign_sig; } /* fill the 'confounder' with random data */ @@ -1559,18 +1573,18 @@ void netsec_encode(struct netsec_auth_struct *a, int auth_flags, dump_data_pw("verf->seq_num:\n", seq_num, sizeof(verf->seq_num)); - init_rpc_auth_netsec_chk(verf, netsec_sig, nullbytes, + init_rpc_auth_schannel_chk(verf, schannel_sig, nullbytes, seq_num, confounder); /* produce a digest of the packet to prove it's legit (before we seal it) */ - netsec_digest(a, auth_flags, verf, data, data_len, digest_final); + schannel_digest(a, auth_level, verf, data, data_len, digest_final); memcpy(verf->packet_digest, digest_final, sizeof(verf->packet_digest)); - if (auth_flags & AUTH_PIPE_SEAL) { + if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) { uchar sealing_key[16]; /* get the key to encode the data with */ - netsec_get_sealing_key(a, verf, sealing_key); + schannel_get_sealing_key(a, verf, sealing_key); /* encode the verification data */ dump_data_pw("verf->confounder:\n", verf->confounder, sizeof(verf->confounder)); @@ -1587,35 +1601,35 @@ void netsec_encode(struct netsec_auth_struct *a, int auth_flags, /* encode the sequence number (key based on packet digest) */ /* needs to be done after the sealing, as the original version is used in the sealing stuff... */ - netsec_deal_with_seq_num(a, verf); + schannel_deal_with_seq_num(a, verf); return; } /******************************************************************* - Decode a blob of data using the netsec (schannel) alogrithm, also verifiying + Decode a blob of data using the schannel alogrithm, also verifiying a checksum over the original data. We currently can verify signed messages, as well as decode sealed messages ********************************************************************/ -BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags, - enum netsec_direction direction, - RPC_AUTH_NETSEC_CHK * verf, char *data, size_t data_len) +BOOL schannel_decode(struct schannel_auth_struct *a, enum pipe_auth_level auth_level, + enum schannel_direction direction, + RPC_AUTH_SCHANNEL_CHK * verf, char *data, size_t data_len) { uchar digest_final[16]; - static const uchar netsec_seal_sig[8] = NETSEC_SEAL_SIGNATURE; - static const uchar netsec_sign_sig[8] = NETSEC_SIGN_SIGNATURE; - const uchar *netsec_sig = NULL; + static const uchar schannel_seal_sig[8] = SCHANNEL_SEAL_SIGNATURE; + static const uchar schannel_sign_sig[8] = SCHANNEL_SIGN_SIGNATURE; + const uchar *schannel_sig = NULL; uchar seq_num[8]; - DEBUG(10,("SCHANNEL: netsec_encode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len)); + DEBUG(10,("SCHANNEL: schannel_decode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len)); - if (auth_flags & AUTH_PIPE_SEAL) { - netsec_sig = netsec_seal_sig; - } else if (auth_flags & AUTH_PIPE_SIGN) { - netsec_sig = netsec_sign_sig; + if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) { + schannel_sig = schannel_seal_sig; + } else { + schannel_sig = schannel_sign_sig; } /* Create the expected sequence number for comparison */ @@ -1630,7 +1644,7 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags, break; } - DEBUG(10,("SCHANNEL: netsec_decode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len)); + DEBUG(10,("SCHANNEL: schannel_decode seq_num=%d data_len=%lu\n", a->seq_num, (unsigned long)data_len)); dump_data_pw("a->sess_key:\n", a->sess_key, sizeof(a->sess_key)); dump_data_pw("seq_num:\n", seq_num, sizeof(seq_num)); @@ -1638,7 +1652,7 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags, /* extract the sequence number (key based on supplied packet digest) */ /* needs to be done before the sealing, as the original version is used in the sealing stuff... */ - netsec_deal_with_seq_num(a, verf); + schannel_deal_with_seq_num(a, verf); if (memcmp(verf->seq_num, seq_num, sizeof(seq_num))) { /* don't even bother with the below if the sequence number is out */ @@ -1646,7 +1660,7 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags, digest, as supplied by the client. We check that it's a valid checksum after the decode, below */ - DEBUG(2, ("netsec_decode: FAILED: packet sequence number:\n")); + DEBUG(2, ("schannel_decode: FAILED: packet sequence number:\n")); dump_data(2, (const char*)verf->seq_num, sizeof(verf->seq_num)); DEBUG(2, ("should be:\n")); dump_data(2, (const char*)seq_num, sizeof(seq_num)); @@ -1654,20 +1668,20 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags, return False; } - if (memcmp(verf->sig, netsec_sig, sizeof(verf->sig))) { + if (memcmp(verf->sig, schannel_sig, sizeof(verf->sig))) { /* Validate that the other end sent the expected header */ - DEBUG(2, ("netsec_decode: FAILED: packet header:\n")); + DEBUG(2, ("schannel_decode: FAILED: packet header:\n")); dump_data(2, (const char*)verf->sig, sizeof(verf->sig)); DEBUG(2, ("should be:\n")); - dump_data(2, (const char*)netsec_sig, sizeof(netsec_sig)); + dump_data(2, (const char*)schannel_sig, sizeof(schannel_sig)); return False; } - if (auth_flags & AUTH_PIPE_SEAL) { + if (auth_level == PIPE_AUTH_LEVEL_PRIVACY) { uchar sealing_key[16]; /* get the key to extract the data with */ - netsec_get_sealing_key(a, verf, sealing_key); + schannel_get_sealing_key(a, verf, sealing_key); /* extract the verification data */ dump_data_pw("verf->confounder:\n", verf->confounder, @@ -1684,7 +1698,7 @@ BOOL netsec_decode(struct netsec_auth_struct *a, int auth_flags, } /* digest includes 'data' after unsealing */ - netsec_digest(a, auth_flags, verf, data, data_len, digest_final); + schannel_digest(a, auth_level, verf, data, data_len, digest_final); dump_data_pw("Calculated digest:\n", digest_final, sizeof(digest_final)); diff --git a/source3/rpc_parse/parse_reg.c b/source3/rpc_parse/parse_reg.c index be452033fe2..295fead1035 100644 --- a/source3/rpc_parse/parse_reg.c +++ b/source3/rpc_parse/parse_reg.c @@ -33,7 +33,7 @@ Fill in a REGVAL_BUFFER for the data given a REGISTRY_VALUE *******************************************************************/ -static uint32 reg_init_regval_buffer( REGVAL_BUFFER *buf2, REGISTRY_VALUE *val ) +uint32 reg_init_regval_buffer( REGVAL_BUFFER *buf2, REGISTRY_VALUE *val ) { uint32 real_size = 0; diff --git a/source3/rpc_parse/parse_rpc.c b/source3/rpc_parse/parse_rpc.c index ce081b92e83..ea4ec2c8639 100644 --- a/source3/rpc_parse/parse_rpc.c +++ b/source3/rpc_parse/parse_rpc.c @@ -191,6 +191,26 @@ interface/version dce/rpc pipe identification }, 0x00 \ } +#define SYNT_UNIXINFO_V0 \ +{ \ + { \ + 0x9c54e310, 0xa955, 0x4885, \ + { 0xbd, 0x31 }, \ + { 0x78, 0x78, \ + 0x71, 0x47, 0xdf, 0xa6 } \ + }, 0x00 \ +} + +#define SYNT_NTSVCS_V1 \ +{ \ + { \ + 0x8d9f4e40, 0xa03d, 0x11ce, \ + { 0x8f, 0x69}, \ + { 0x08, 0x00, \ + 0x3e, 0x30, 0x05, 0x1b } \ + }, 0x01 \ +} + /* * IMPORTANT!! If you update this structure, make sure to * update the index #defines in smb.h. @@ -212,9 +232,19 @@ const struct pipe_id_info pipe_names [] = { PIPE_SHUTDOWN, SYNT_SHUTDOWN_V1 , PIPE_SHUTDOWN , TRANS_SYNT_V2 }, { PIPE_SVCCTL , SYNT_SVCCTL_V2 , PIPE_NTSVCS , TRANS_SYNT_V2 }, { PIPE_EVENTLOG, SYNT_EVENTLOG_V0 , PIPE_EVENTLOG , TRANS_SYNT_V2 }, + { PIPE_NTSVCS , SYNT_NTSVCS_V1 , PIPE_NTSVCS , TRANS_SYNT_V2 }, { NULL , SYNT_NONE_V0 , NULL , SYNT_NONE_V0 } }; +/**************************************************************************** + Return the pipe name from the index. + ****************************************************************************/ + +const char *cli_get_pipe_name(int pipe_idx) +{ + return &pipe_names[pipe_idx].client_pipe[5]; +} + /******************************************************************* Inits an RPC_HDR structure. ********************************************************************/ @@ -658,8 +688,8 @@ void init_rpc_hdr_auth(RPC_HDR_AUTH *rai, uint8 auth_pad_len, uint32 auth_context_id) { - rai->auth_type = auth_type; /* nt lm ssp 0x0a */ - rai->auth_level = auth_level; /* 0x06 */ + rai->auth_type = auth_type; + rai->auth_level = auth_level; rai->auth_pad_len = auth_pad_len; rai->auth_reserved = 0; rai->auth_context_id = auth_context_id; @@ -680,9 +710,9 @@ BOOL smb_io_rpc_hdr_auth(const char *desc, RPC_HDR_AUTH *rai, prs_struct *ps, in if(!prs_align(ps)) return False; - if(!prs_uint8 ("auth_type ", ps, depth, &rai->auth_type)) /* 0x0a nt lm ssp */ + if(!prs_uint8 ("auth_type ", ps, depth, &rai->auth_type)) return False; - if(!prs_uint8 ("auth_level ", ps, depth, &rai->auth_level)) /* 0x06 */ + if(!prs_uint8 ("auth_level ", ps, depth, &rai->auth_level)) return False; if(!prs_uint8 ("auth_pad_len ", ps, depth, &rai->auth_pad_len)) return False; @@ -694,43 +724,6 @@ BOOL smb_io_rpc_hdr_auth(const char *desc, RPC_HDR_AUTH *rai, prs_struct *ps, in return True; } - -/******************************************************************* - Init an RPC_HDR_AUTHA structure. -********************************************************************/ - -void init_rpc_hdr_autha(RPC_HDR_AUTHA *rai, - uint16 max_tsize, uint16 max_rsize, - RPC_HDR_AUTH *auth) -{ - rai->max_tsize = max_tsize; /* maximum transmission fragment size (0x1630) */ - rai->max_rsize = max_rsize; /* max receive fragment size (0x1630) */ - rai->auth = *auth; -} - -/******************************************************************* - Reads or writes an RPC_HDR_AUTHA structure. -********************************************************************/ - -BOOL smb_io_rpc_hdr_autha(const char *desc, RPC_HDR_AUTHA *rai, prs_struct *ps, int depth) -{ - if (rai == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_rpc_hdr_autha"); - depth++; - - if(!prs_uint16("max_tsize ", ps, depth, &rai->max_tsize)) - return False; - if(!prs_uint16("max_rsize ", ps, depth, &rai->max_rsize)) - return False; - - if(!smb_io_rpc_hdr_auth("auth", &rai->auth, ps, depth)) - return False; - - return True; -} - /******************************************************************* Checks an RPC_AUTH_VERIFIER structure. ********************************************************************/ @@ -775,17 +768,15 @@ BOOL smb_io_rpc_auth_verifier(const char *desc, RPC_AUTH_VERIFIER *rav, prs_stru } /******************************************************************* - This parses an RPC_AUTH_VERIFIER for NETLOGON schannel. I think - assuming "NTLMSSP" in sm_io_rpc_auth_verifier is somewhat wrong. - I have to look at that later... + This parses an RPC_AUTH_VERIFIER for schannel. I think ********************************************************************/ -BOOL smb_io_rpc_netsec_verifier(const char *desc, RPC_AUTH_VERIFIER *rav, prs_struct *ps, int depth) +BOOL smb_io_rpc_schannel_verifier(const char *desc, RPC_AUTH_VERIFIER *rav, prs_struct *ps, int depth) { if (rav == NULL) return False; - prs_debug(ps, depth, desc, "smb_io_rpc_auth_verifier"); + prs_debug(ps, depth, desc, "smb_io_rpc_schannel_verifier"); depth++; if(!prs_string("signature", ps, depth, rav->signature, sizeof(rav->signature))) @@ -797,424 +788,10 @@ BOOL smb_io_rpc_netsec_verifier(const char *desc, RPC_AUTH_VERIFIER *rav, prs_st } /******************************************************************* - Inits an RPC_AUTH_NTLMSSP_NEG structure. -********************************************************************/ - -void init_rpc_auth_ntlmssp_neg(RPC_AUTH_NTLMSSP_NEG *neg, - uint32 neg_flgs, - const char *myname, const char *domain) -{ - int len_myname = strlen(myname); - int len_domain = strlen(domain); - - neg->neg_flgs = neg_flgs ; /* 0x00b2b3 */ - - init_str_hdr(&neg->hdr_domain, len_domain, len_domain, 0x20 + len_myname); - init_str_hdr(&neg->hdr_myname, len_myname, len_myname, 0x20); - - fstrcpy(neg->myname, myname); - fstrcpy(neg->domain, domain); -} - -/******************************************************************* - Reads or writes an RPC_AUTH_NTLMSSP_NEG structure. - - *** lkclXXXX HACK ALERT! *** -********************************************************************/ - -BOOL smb_io_rpc_auth_ntlmssp_neg(const char *desc, RPC_AUTH_NTLMSSP_NEG *neg, prs_struct *ps, int depth) -{ - uint32 start_offset = prs_offset(ps); - if (neg == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_rpc_auth_ntlmssp_neg"); - depth++; - - if(!prs_uint32("neg_flgs ", ps, depth, &neg->neg_flgs)) - return False; - - if (ps->io) { - uint32 old_offset; - uint32 old_neg_flags = neg->neg_flgs; - - /* reading */ - - ZERO_STRUCTP(neg); - - neg->neg_flgs = old_neg_flags; - - if(!smb_io_strhdr("hdr_domain", &neg->hdr_domain, ps, depth)) - return False; - if(!smb_io_strhdr("hdr_myname", &neg->hdr_myname, ps, depth)) - return False; - - old_offset = prs_offset(ps); - - if(!prs_set_offset(ps, neg->hdr_myname.buffer + start_offset - 12)) - return False; - - if(!prs_uint8s(True, "myname", ps, depth, (uint8*)neg->myname, - MIN(neg->hdr_myname.str_str_len, sizeof(neg->myname)))) - return False; - - old_offset += neg->hdr_myname.str_str_len; - - if(!prs_set_offset(ps, neg->hdr_domain.buffer + start_offset - 12)) - return False; - - if(!prs_uint8s(True, "domain", ps, depth, (uint8*)neg->domain, - MIN(neg->hdr_domain.str_str_len, sizeof(neg->domain )))) - return False; - - old_offset += neg->hdr_domain .str_str_len; - - if(!prs_set_offset(ps, old_offset)) - return False; - } else { - /* writing */ - if(!smb_io_strhdr("hdr_domain", &neg->hdr_domain, ps, depth)) - return False; - if(!smb_io_strhdr("hdr_myname", &neg->hdr_myname, ps, depth)) - return False; - - if(!prs_uint8s(True, "myname", ps, depth, (uint8*)neg->myname, - MIN(neg->hdr_myname.str_str_len, sizeof(neg->myname)))) - return False; - if(!prs_uint8s(True, "domain", ps, depth, (uint8*)neg->domain, - MIN(neg->hdr_domain.str_str_len, sizeof(neg->domain )))) - return False; - } - - return True; -} - -/******************************************************************* -creates an RPC_AUTH_NTLMSSP_CHAL structure. -********************************************************************/ - -void init_rpc_auth_ntlmssp_chal(RPC_AUTH_NTLMSSP_CHAL *chl, - uint32 neg_flags, - uint8 challenge[8]) -{ - chl->unknown_1 = 0x0; - chl->unknown_2 = 0x00000028; - chl->neg_flags = neg_flags; /* 0x0082b1 */ - - memcpy(chl->challenge, challenge, sizeof(chl->challenge)); - memset((char *)chl->reserved , '\0', sizeof(chl->reserved)); -} - -/******************************************************************* - Reads or writes an RPC_AUTH_NTLMSSP_CHAL structure. -********************************************************************/ - -BOOL smb_io_rpc_auth_ntlmssp_chal(const char *desc, RPC_AUTH_NTLMSSP_CHAL *chl, prs_struct *ps, int depth) -{ - if (chl == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_rpc_auth_ntlmssp_chal"); - depth++; - - if(!prs_uint32("unknown_1", ps, depth, &chl->unknown_1)) /* 0x0000 0000 */ - return False; - if(!prs_uint32("unknown_2", ps, depth, &chl->unknown_2)) /* 0x0000 b2b3 */ - return False; - if(!prs_uint32("neg_flags", ps, depth, &chl->neg_flags)) /* 0x0000 82b1 */ - return False; - - if(!prs_uint8s (False, "challenge", ps, depth, chl->challenge, sizeof(chl->challenge))) - return False; - if(!prs_uint8s (False, "reserved ", ps, depth, chl->reserved , sizeof(chl->reserved ))) - return False; - - return True; -} - -/******************************************************************* - Inits an RPC_AUTH_NTLMSSP_RESP structure. - - *** lkclXXXX FUDGE! HAVE TO MANUALLY SPECIFY OFFSET HERE (0x1c bytes) *** - *** lkclXXXX the actual offset is at the start of the auth verifier *** -********************************************************************/ - -void init_rpc_auth_ntlmssp_resp(RPC_AUTH_NTLMSSP_RESP *rsp, - uchar lm_resp[24], uchar nt_resp[24], - const char *domain, const char *user, const char *wks, - uint32 neg_flags) -{ - uint32 offset; - int dom_len = strlen(domain); - int wks_len = strlen(wks); - int usr_len = strlen(user); - int lm_len = (lm_resp != NULL) ? 24 : 0; - int nt_len = (nt_resp != NULL) ? 24 : 0; - - DEBUG(5,("make_rpc_auth_ntlmssp_resp\n")); - -#ifdef DEBUG_PASSWORD - DEBUG(100,("lm_resp\n")); - dump_data(100, (char *)lm_resp, 24); - DEBUG(100,("nt_resp\n")); - dump_data(100, (char *)nt_resp, 24); -#endif - - DEBUG(6,("dom: %s user: %s wks: %s neg_flgs: 0x%x\n", - domain, user, wks, neg_flags)); - - offset = 0x40; - - if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) { - dom_len *= 2; - wks_len *= 2; - usr_len *= 2; - } - - init_str_hdr(&rsp->hdr_domain, dom_len, dom_len, offset); - offset += dom_len; - - init_str_hdr(&rsp->hdr_usr, usr_len, usr_len, offset); - offset += usr_len; - - init_str_hdr(&rsp->hdr_wks, wks_len, wks_len, offset); - offset += wks_len; - - init_str_hdr(&rsp->hdr_lm_resp, lm_len, lm_len, offset); - offset += lm_len; - - init_str_hdr(&rsp->hdr_nt_resp, nt_len, nt_len, offset); - offset += nt_len; - - init_str_hdr(&rsp->hdr_sess_key, 0, 0, offset); - - rsp->neg_flags = neg_flags; - - memcpy(rsp->lm_resp, lm_resp, 24); - memcpy(rsp->nt_resp, nt_resp, 24); - - if (neg_flags & NTLMSSP_NEGOTIATE_UNICODE) { - rpcstr_push(rsp->domain, domain, sizeof(rsp->domain), 0); - rpcstr_push(rsp->user, user, sizeof(rsp->user), 0); - rpcstr_push(rsp->wks, wks, sizeof(rsp->wks), 0); - } else { - fstrcpy(rsp->domain, domain); - fstrcpy(rsp->user, user); - fstrcpy(rsp->wks, wks); - } - - rsp->sess_key[0] = 0; -} - -/******************************************************************* - Reads or writes an RPC_AUTH_NTLMSSP_RESP structure. - - *** lkclXXXX FUDGE! HAVE TO MANUALLY SPECIFY OFFSET HERE (0x1c bytes) *** - *** lkclXXXX the actual offset is at the start of the auth verifier *** -********************************************************************/ - -BOOL smb_io_rpc_auth_ntlmssp_resp(const char *desc, RPC_AUTH_NTLMSSP_RESP *rsp, prs_struct *ps, int depth) -{ - if (rsp == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_rpc_auth_ntlmssp_resp"); - depth++; - - if (ps->io) { - uint32 old_offset; - - /* reading */ - - ZERO_STRUCTP(rsp); - - if(!smb_io_strhdr("hdr_lm_resp ", &rsp->hdr_lm_resp, ps, depth)) - return False; - if(!smb_io_strhdr("hdr_nt_resp ", &rsp->hdr_nt_resp, ps, depth)) - return False; - if(!smb_io_strhdr("hdr_domain ", &rsp->hdr_domain, ps, depth)) - return False; - if(!smb_io_strhdr("hdr_user ", &rsp->hdr_usr, ps, depth)) - return False; - if(!smb_io_strhdr("hdr_wks ", &rsp->hdr_wks, ps, depth)) - return False; - if(!smb_io_strhdr("hdr_sess_key", &rsp->hdr_sess_key, ps, depth)) - return False; - - if(!prs_uint32("neg_flags", ps, depth, &rsp->neg_flags)) /* 0x0000 82b1 */ - return False; - - old_offset = prs_offset(ps); - - if(!prs_set_offset(ps, rsp->hdr_domain.buffer + 0xc)) - return False; - - if(!prs_uint8s(True , "domain ", ps, depth, (uint8*)rsp->domain, - MIN(rsp->hdr_domain.str_str_len, sizeof(rsp->domain)))) - return False; - - old_offset += rsp->hdr_domain.str_str_len; - - if(!prs_set_offset(ps, rsp->hdr_usr.buffer + 0xc)) - return False; - - if(!prs_uint8s(True , "user ", ps, depth, (uint8*)rsp->user, - MIN(rsp->hdr_usr.str_str_len, sizeof(rsp->user)))) - return False; - - old_offset += rsp->hdr_usr.str_str_len; - - if(!prs_set_offset(ps, rsp->hdr_wks.buffer + 0xc)) - return False; - - if(!prs_uint8s(True, "wks ", ps, depth, (uint8*)rsp->wks, - MIN(rsp->hdr_wks.str_str_len, sizeof(rsp->wks)))) - return False; - - old_offset += rsp->hdr_wks.str_str_len; - - if(!prs_set_offset(ps, rsp->hdr_lm_resp.buffer + 0xc)) - return False; - - if(!prs_uint8s(False, "lm_resp ", ps, depth, (uint8*)rsp->lm_resp, - MIN(rsp->hdr_lm_resp.str_str_len, sizeof(rsp->lm_resp )))) - return False; - - old_offset += rsp->hdr_lm_resp.str_str_len; - - if(!prs_set_offset(ps, rsp->hdr_nt_resp.buffer + 0xc)) - return False; - - if(!prs_uint8s(False, "nt_resp ", ps, depth, (uint8*)rsp->nt_resp, - MIN(rsp->hdr_nt_resp.str_str_len, sizeof(rsp->nt_resp )))) - return False; - - old_offset += rsp->hdr_nt_resp.str_str_len; - - if (rsp->hdr_sess_key.str_str_len != 0) { - - if(!prs_set_offset(ps, rsp->hdr_sess_key.buffer + 0x10)) - return False; - - old_offset += rsp->hdr_sess_key.str_str_len; - - if(!prs_uint8s(False, "sess_key", ps, depth, (uint8*)rsp->sess_key, - MIN(rsp->hdr_sess_key.str_str_len, sizeof(rsp->sess_key)))) - return False; - } - - if(!prs_set_offset(ps, old_offset)) - return False; - } else { - /* writing */ - if(!smb_io_strhdr("hdr_lm_resp ", &rsp->hdr_lm_resp, ps, depth)) - return False; - if(!smb_io_strhdr("hdr_nt_resp ", &rsp->hdr_nt_resp, ps, depth)) - return False; - if(!smb_io_strhdr("hdr_domain ", &rsp->hdr_domain, ps, depth)) - return False; - if(!smb_io_strhdr("hdr_user ", &rsp->hdr_usr, ps, depth)) - return False; - if(!smb_io_strhdr("hdr_wks ", &rsp->hdr_wks, ps, depth)) - return False; - if(!smb_io_strhdr("hdr_sess_key", &rsp->hdr_sess_key, ps, depth)) - return False; - - if(!prs_uint32("neg_flags", ps, depth, &rsp->neg_flags)) /* 0x0000 82b1 */ - return False; - - if(!prs_uint8s(True , "domain ", ps, depth, (uint8*)rsp->domain, - MIN(rsp->hdr_domain.str_str_len, sizeof(rsp->domain)))) - return False; - - if(!prs_uint8s(True , "user ", ps, depth, (uint8*)rsp->user, - MIN(rsp->hdr_usr.str_str_len, sizeof(rsp->user)))) - return False; - - if(!prs_uint8s(True , "wks ", ps, depth, (uint8*)rsp->wks, - MIN(rsp->hdr_wks.str_str_len, sizeof(rsp->wks)))) - return False; - if(!prs_uint8s(False, "lm_resp ", ps, depth, (uint8*)rsp->lm_resp, - MIN(rsp->hdr_lm_resp .str_str_len, sizeof(rsp->lm_resp)))) - return False; - if(!prs_uint8s(False, "nt_resp ", ps, depth, (uint8*)rsp->nt_resp, - MIN(rsp->hdr_nt_resp .str_str_len, sizeof(rsp->nt_resp )))) - return False; - if(!prs_uint8s(False, "sess_key", ps, depth, (uint8*)rsp->sess_key, - MIN(rsp->hdr_sess_key.str_str_len, sizeof(rsp->sess_key)))) - return False; - } - - return True; -} - -/******************************************************************* - Checks an RPC_AUTH_NTLMSSP_CHK structure. -********************************************************************/ - -BOOL rpc_auth_ntlmssp_chk(RPC_AUTH_NTLMSSP_CHK *chk, uint32 crc32, uint32 seq_num) -{ - if (chk == NULL) - return False; - - if (chk->crc32 != crc32 || - chk->ver != NTLMSSP_SIGN_VERSION || - chk->seq_num != seq_num) - { - DEBUG(5,("verify failed - crc %x ver %x seq %d\n", - chk->crc32, chk->ver, chk->seq_num)); - - DEBUG(5,("verify expect - crc %x ver %x seq %d\n", - crc32, NTLMSSP_SIGN_VERSION, seq_num)); - return False; - } - return True; -} - -/******************************************************************* - Inits an RPC_AUTH_NTLMSSP_CHK structure. -********************************************************************/ - -void init_rpc_auth_ntlmssp_chk(RPC_AUTH_NTLMSSP_CHK *chk, - uint32 ver, uint32 crc32, uint32 seq_num) -{ - chk->ver = ver; - chk->reserved = 0x0; - chk->crc32 = crc32; - chk->seq_num = seq_num; -} - -/******************************************************************* - Reads or writes an RPC_AUTH_NTLMSSP_CHK structure. +creates an RPC_AUTH_SCHANNEL_NEG structure. ********************************************************************/ -BOOL smb_io_rpc_auth_ntlmssp_chk(const char *desc, RPC_AUTH_NTLMSSP_CHK *chk, prs_struct *ps, int depth) -{ - if (chk == NULL) - return False; - - prs_debug(ps, depth, desc, "smb_io_rpc_auth_ntlmssp_chk"); - depth++; - - if(!prs_align(ps)) - return False; - - if(!prs_uint32("ver ", ps, depth, &chk->ver)) - return False; - if(!prs_uint32("reserved", ps, depth, &chk->reserved)) - return False; - if(!prs_uint32("crc32 ", ps, depth, &chk->crc32)) - return False; - if(!prs_uint32("seq_num ", ps, depth, &chk->seq_num)) - return False; - - return True; -} - -/******************************************************************* -creates an RPC_AUTH_NETSEC_NEG structure. -********************************************************************/ -void init_rpc_auth_netsec_neg(RPC_AUTH_NETSEC_NEG *neg, +void init_rpc_auth_schannel_neg(RPC_AUTH_SCHANNEL_NEG *neg, const char *domain, const char *myname) { neg->type1 = 0; @@ -1224,16 +801,16 @@ void init_rpc_auth_netsec_neg(RPC_AUTH_NETSEC_NEG *neg, } /******************************************************************* - Reads or writes an RPC_AUTH_NETSEC_NEG structure. + Reads or writes an RPC_AUTH_SCHANNEL_NEG structure. ********************************************************************/ -BOOL smb_io_rpc_auth_netsec_neg(const char *desc, RPC_AUTH_NETSEC_NEG *neg, +BOOL smb_io_rpc_auth_schannel_neg(const char *desc, RPC_AUTH_SCHANNEL_NEG *neg, prs_struct *ps, int depth) { if (neg == NULL) return False; - prs_debug(ps, depth, desc, "smb_io_rpc_auth_netsec_neg"); + prs_debug(ps, depth, desc, "smb_io_rpc_auth_schannel_neg"); depth++; if(!prs_align(ps)) @@ -1252,16 +829,17 @@ BOOL smb_io_rpc_auth_netsec_neg(const char *desc, RPC_AUTH_NETSEC_NEG *neg, } /******************************************************************* -reads or writes an RPC_AUTH_NETSEC_CHK structure. +reads or writes an RPC_AUTH_SCHANNEL_CHK structure. ********************************************************************/ -BOOL smb_io_rpc_auth_netsec_chk(const char *desc, int auth_len, - RPC_AUTH_NETSEC_CHK * chk, + +BOOL smb_io_rpc_auth_schannel_chk(const char *desc, int auth_len, + RPC_AUTH_SCHANNEL_CHK * chk, prs_struct *ps, int depth) { if (chk == NULL) return False; - prs_debug(ps, depth, desc, "smb_io_rpc_auth_netsec_chk"); + prs_debug(ps, depth, desc, "smb_io_rpc_auth_schannel_chk"); depth++; if ( !prs_uint8s(False, "sig ", ps, depth, chk->sig, sizeof(chk->sig)) ) @@ -1273,7 +851,7 @@ BOOL smb_io_rpc_auth_netsec_chk(const char *desc, int auth_len, if ( !prs_uint8s(False, "packet_digest", ps, depth, chk->packet_digest, sizeof(chk->packet_digest)) ) return False; - if ( auth_len == RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN ) { + if ( auth_len == RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN ) { if ( !prs_uint8s(False, "confounder", ps, depth, chk->confounder, sizeof(chk->confounder)) ) return False; } diff --git a/source3/rpc_parse/parse_samr.c b/source3/rpc_parse/parse_samr.c index 6b0193c6e46..1aaebf71e39 100644 --- a/source3/rpc_parse/parse_samr.c +++ b/source3/rpc_parse/parse_samr.c @@ -25,8 +25,6 @@ */ #include "includes.h" -#include "rpc_parse.h" -#include "nterr.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_PARSE @@ -7038,9 +7036,9 @@ inits a SAMR_R_GET_DOM_PWINFO structure. void init_samr_q_chgpasswd_user(SAMR_Q_CHGPASSWD_USER * q_u, const char *dest_host, const char *user_name, - const char nt_newpass[516], + const uchar nt_newpass[516], const uchar nt_oldhash[16], - const char lm_newpass[516], + const uchar lm_newpass[516], const uchar lm_oldhash[16]) { DEBUG(5, ("init_samr_q_chgpasswd_user\n")); diff --git a/source3/rpc_parse/parse_svcctl.c b/source3/rpc_parse/parse_svcctl.c index b86ca23df15..e1a7ad84273 100644 --- a/source3/rpc_parse/parse_svcctl.c +++ b/source3/rpc_parse/parse_svcctl.c @@ -100,40 +100,48 @@ static BOOL svcctl_io_service_config( const char *desc, SERVICE_CONFIG *config, return True; } + /******************************************************************* ********************************************************************/ -BOOL svcctl_io_service_description( const char *desc, UNISTR2 *svcdesc, prs_struct *ps, int depth ) +BOOL svcctl_io_enum_services_status( const char *desc, ENUM_SERVICES_STATUS *enum_status, RPC_BUFFER *buffer, int depth ) { - - prs_debug(ps, depth, desc, "svcctl_io_service_description"); + prs_struct *ps=&buffer->prs; + + prs_debug(ps, depth, desc, "svcctl_io_enum_services_status"); depth++; - - if (!prs_io_unistr2("", ps, depth, svcdesc)) + + if ( !smb_io_relstr("servicename", buffer, depth, &enum_status->servicename) ) + return False; + if ( !smb_io_relstr("displayname", buffer, depth, &enum_status->displayname) ) return False; + if ( !svcctl_io_service_status("svc_status", &enum_status->status, ps, depth) ) + return False; + return True; } - /******************************************************************* ********************************************************************/ -BOOL svcctl_io_enum_services_status( const char *desc, ENUM_SERVICES_STATUS *enum_status, RPC_BUFFER *buffer, int depth ) +BOOL svcctl_io_service_status_process( const char *desc, SERVICE_STATUS_PROCESS *status, RPC_BUFFER *buffer, int depth ) { prs_struct *ps=&buffer->prs; - - prs_debug(ps, depth, desc, "svcctl_io_enum_services_status"); + + prs_debug(ps, depth, desc, "svcctl_io_service_status_process"); depth++; - - if ( !smb_io_relstr("servicename", buffer, depth, &enum_status->servicename) ) + + if ( !svcctl_io_service_status("status", &status->status, ps, depth) ) return False; - if ( !smb_io_relstr("displayname", buffer, depth, &enum_status->displayname) ) + if(!prs_align(ps)) return False; - if ( !svcctl_io_service_status("svc_status", &enum_status->status, ps, depth) ) + if(!prs_uint32("process_id", ps, depth, &status->process_id)) return False; - + if(!prs_uint32("service_flags", ps, depth, &status->service_flags)) + return False; + return True; } @@ -151,6 +159,45 @@ uint32 svcctl_sizeof_enum_services_status( ENUM_SERVICES_STATUS *status ) return size; } +/******************************************************************** +********************************************************************/ + +static uint32 sizeof_unistr2( UNISTR2 *string ) +{ + uint32 size = 0; + + if ( !string ) + return 0; + + size = sizeof(uint32) * 3; /* length fields */ + size += 2 * string->uni_max_len; /* string data */ + size += size % 4; /* alignment */ + + return size; +} + +/******************************************************************** +********************************************************************/ + +uint32 svcctl_sizeof_service_config( SERVICE_CONFIG *config ) +{ + uint32 size = 0; + + size = sizeof(uint32) * 4; /* static uint32 fields */ + + /* now add the UNISTR2 + pointer sizes */ + + size += sizeof(uint32) * sizeof_unistr2(config->executablepath); + size += sizeof(uint32) * sizeof_unistr2(config->loadordergroup); + size += sizeof(uint32) * sizeof_unistr2(config->dependencies); + size += sizeof(uint32) * sizeof_unistr2(config->startname); + size += sizeof(uint32) * sizeof_unistr2(config->displayname); + + return size; +} + + + /******************************************************************* ********************************************************************/ @@ -694,7 +741,7 @@ BOOL svcctl_io_q_query_service_config2(const char *desc, SVCCTL_Q_QUERY_SERVICE_ if(!smb_io_pol_hnd("service_pol", &q_u->handle, ps, depth)) return False; - if(!prs_uint32("info_level", ps, depth, &q_u->info_level)) + if(!prs_uint32("level", ps, depth, &q_u->level)) return False; if(!prs_uint32("buffer_size", ps, depth, &q_u->buffer_size)) @@ -705,36 +752,145 @@ BOOL svcctl_io_q_query_service_config2(const char *desc, SVCCTL_Q_QUERY_SERVICE_ /******************************************************************* - Creates a service description response buffer. - The format seems to be DWORD:length of buffer - DWORD:offset (fixed as four) - UNISTR: unicode description in the rest of the buffer ********************************************************************/ -void init_service_description_buffer(RPC_DATA_BLOB *str, const char *service_desc, int blob_length) +void init_service_description_buffer(SERVICE_DESCRIPTION *desc, const char *service_desc ) { - uint32 offset; - uint8 *bp; + desc->unknown = 0x04; /* always 0x0000 0004 (no idea what this is) */ + init_unistr( &desc->description, service_desc ); +} - ZERO_STRUCTP(str); +/******************************************************************* +********************************************************************/ - offset = 4; +BOOL svcctl_io_service_description( const char *desc, SERVICE_DESCRIPTION *description, RPC_BUFFER *buffer, int depth ) +{ + prs_struct *ps = &buffer->prs; - /* set up string lengths. */ + prs_debug(ps, depth, desc, "svcctl_io_service_description"); + depth++; - str->buf_len = create_rpc_blob(str, blob_length); - DEBUG(10, ("init_service_description buffer: Allocated a blob of [%d] \n",str->buf_len)); + if ( !prs_uint32("unknown", ps, depth, &description->unknown) ) + return False; + if ( !prs_unistr("description", ps, depth, &description->description) ) + return False; - if ( str && str->buffer && str->buf_len) { - memset(str->buffer,0,str->buf_len); - memcpy(str->buffer, &offset, sizeof(uint32)); - bp = &str->buffer[4]; - if (service_desc) { - rpcstr_push(bp, service_desc,str->buf_len-4,0); + return True; +} + +/******************************************************************* +********************************************************************/ + +uint32 svcctl_sizeof_service_description( SERVICE_DESCRIPTION *desc ) +{ + if ( !desc ) + return 0; + + /* make sure to include the terminating NULL */ + return ( sizeof(uint32) + (2*(str_len_uni(&desc->description)+1)) ); +} + +/******************************************************************* +********************************************************************/ + +static BOOL svcctl_io_action( const char *desc, SC_ACTION *action, prs_struct *ps, int depth ) +{ + + prs_debug(ps, depth, desc, "svcctl_io_action"); + depth++; + + if ( !prs_uint32("type", ps, depth, &action->type) ) + return False; + if ( !prs_uint32("delay", ps, depth, &action->delay) ) + return False; + + return True; +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_service_fa( const char *desc, SERVICE_FAILURE_ACTIONS *fa, RPC_BUFFER *buffer, int depth ) +{ + prs_struct *ps = &buffer->prs; + int i; + + prs_debug(ps, depth, desc, "svcctl_io_service_description"); + depth++; + + if ( !prs_uint32("reset_period", ps, depth, &fa->reset_period) ) + return False; + + if ( !prs_pointer( desc, ps, depth, (void**)&fa->rebootmsg, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) ) + return False; + if ( !prs_pointer( desc, ps, depth, (void**)&fa->command, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) ) + return False; + + if ( !prs_uint32("num_actions", ps, depth, &fa->num_actions) ) + return False; + + if ( UNMARSHALLING(ps) && fa->num_actions ) { + if ( !(fa->actions = TALLOC_ARRAY( get_talloc_ctx(), SC_ACTION, fa->num_actions )) ) { + DEBUG(0,("svcctl_io_service_fa: talloc() failure!\n")); + return False; } } + + for ( i=0; inum_actions; i++ ) { + if ( !svcctl_io_action( "actions", &fa->actions[i], ps, depth ) ) + return False; + } + + return True; +} + +/******************************************************************* +********************************************************************/ + +uint32 svcctl_sizeof_service_fa( SERVICE_FAILURE_ACTIONS *fa) +{ + uint32 size = 0; + + if ( !fa ) + return 0; + + size = sizeof(uint32) * 2; + size += sizeof_unistr2( fa->rebootmsg ); + size += sizeof_unistr2( fa->command ); + size += sizeof(SC_ACTION) * fa->num_actions; + + return size; } +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_r_query_service_config2(const char *desc, SVCCTL_R_QUERY_SERVICE_CONFIG2 *r_u, prs_struct *ps, int depth) +{ + if ( !r_u ) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_r_query_service_config2"); + depth++; + + if ( !prs_align(ps) ) + return False; + + if (!prs_rpcbuffer("", ps, depth, &r_u->buffer)) + return False; + if(!prs_align(ps)) + return False; + + if (!prs_uint32("needed", ps, depth, &r_u->needed)) + return False; + + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; + + return True; +} + + /******************************************************************* ********************************************************************/ @@ -752,7 +908,7 @@ BOOL svcctl_io_q_query_service_status_ex(const char *desc, SVCCTL_Q_QUERY_SERVIC if(!smb_io_pol_hnd("service_pol", &q_u->handle, ps, depth)) return False; - if(!prs_uint32("info_level", ps, depth, &q_u->info_level)) + if(!prs_uint32("level", ps, depth, &q_u->level)) return False; if(!prs_uint32("buffer_size", ps, depth, &q_u->buffer_size)) @@ -771,7 +927,7 @@ BOOL svcctl_io_r_query_service_status_ex(const char *desc, SVCCTL_R_QUERY_SERVIC return False; prs_debug(ps, depth, desc, "svcctl_io_r_query_service_status_ex"); - depth++; + depth++; if (!prs_rpcbuffer("", ps, depth, &r_u->buffer)) return False; @@ -791,37 +947,80 @@ BOOL svcctl_io_r_query_service_status_ex(const char *desc, SVCCTL_R_QUERY_SERVIC /******************************************************************* ********************************************************************/ -BOOL svcctl_io_r_query_service_config2(const char *desc, SVCCTL_R_QUERY_SERVICE_CONFIG2 *r_u, prs_struct *ps, int depth) +BOOL svcctl_io_q_lock_service_db(const char *desc, SVCCTL_Q_LOCK_SERVICE_DB *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_q_lock_service_db"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("scm_handle", &q_u->handle, ps, depth)) + return False; + + return True; + +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_r_lock_service_db(const char *desc, SVCCTL_R_LOCK_SERVICE_DB *r_u, prs_struct *ps, int depth) { if ( !r_u ) return False; - prs_debug(ps, depth, desc, "svcctl_io_r_query_service_config2"); + prs_debug(ps, depth, desc, "svcctl_io_r_lock_service_db"); depth++; if(!prs_align(ps)) return False; - if(!prs_uint32("returned", ps, depth, &r_u->returned)) + if(!smb_io_pol_hnd("lock_handle", &r_u->h_lock, ps, depth)) return False; - if (r_u->returned > 4) { - if (!prs_uint32("offset", ps, depth, &r_u->offset)) - return False; + if(!prs_werror("status", ps, depth, &r_u->status)) + return False; - if ( !prs_pointer( desc, ps, depth, (void**)&r_u->description, sizeof(UNISTR2), (PRS_POINTER_CAST)prs_io_unistr2 ) ) - return False; + return True; +} - if(!prs_align(ps)) - return False; - } else { - /* offset does double duty here */ - r_u->offset = 0; - if (!prs_uint32("offset", ps, depth, &r_u->offset)) - return False; - } +/******************************************************************* +********************************************************************/ - if (!prs_uint32("needed", ps, depth, &r_u->needed)) +BOOL svcctl_io_q_unlock_service_db(const char *desc, SVCCTL_Q_UNLOCK_SERVICE_DB *q_u, prs_struct *ps, int depth) +{ + if (q_u == NULL) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_q_unlock_service_db"); + depth++; + + if(!prs_align(ps)) + return False; + + if(!smb_io_pol_hnd("h_lock", &q_u->h_lock, ps, depth)) + return False; + + return True; + +} + +/******************************************************************* +********************************************************************/ + +BOOL svcctl_io_r_unlock_service_db(const char *desc, SVCCTL_R_UNLOCK_SERVICE_DB *r_u, prs_struct *ps, int depth) +{ + if ( !r_u ) + return False; + + prs_debug(ps, depth, desc, "svcctl_io_r_unlock_service_db"); + depth++; + + if(!prs_align(ps)) return False; if(!prs_werror("status", ps, depth, &r_u->status)) @@ -831,3 +1030,5 @@ BOOL svcctl_io_r_query_service_config2(const char *desc, SVCCTL_R_QUERY_SERVICE_ } + + diff --git a/source3/rpc_server/srv_eventlog.c b/source3/rpc_server/srv_eventlog.c index 65b10e8fe40..ae15d43f4ba 100644 --- a/source3/rpc_server/srv_eventlog.c +++ b/source3/rpc_server/srv_eventlog.c @@ -27,7 +27,6 @@ static BOOL api_eventlog_open_eventlog(pipes_struct *p) { EVENTLOG_Q_OPEN_EVENTLOG q_u; EVENTLOG_R_OPEN_EVENTLOG r_u; - prs_struct *data = &p->in_data.data; prs_struct *rdata = &p->out_data.rdata; @@ -53,7 +52,6 @@ static BOOL api_eventlog_close_eventlog(pipes_struct *p) { EVENTLOG_Q_CLOSE_EVENTLOG q_u; EVENTLOG_R_CLOSE_EVENTLOG r_u; - prs_struct *data = &p->in_data.data; prs_struct *rdata = &p->out_data.rdata; @@ -79,7 +77,6 @@ static BOOL api_eventlog_get_num_records(pipes_struct *p) { EVENTLOG_Q_GET_NUM_RECORDS q_u; EVENTLOG_R_GET_NUM_RECORDS r_u; - prs_struct *data = &p->in_data.data; prs_struct *rdata = &p->out_data.rdata; @@ -105,7 +102,6 @@ static BOOL api_eventlog_get_oldest_entry(pipes_struct *p) { EVENTLOG_Q_GET_OLDEST_ENTRY q_u; EVENTLOG_R_GET_OLDEST_ENTRY r_u; - prs_struct *data = &p->in_data.data; prs_struct *rdata = &p->out_data.rdata; @@ -131,7 +127,6 @@ static BOOL api_eventlog_read_eventlog(pipes_struct *p) { EVENTLOG_Q_READ_EVENTLOG q_u; EVENTLOG_R_READ_EVENTLOG r_u; - prs_struct *data = &p->in_data.data; prs_struct *rdata = &p->out_data.rdata; @@ -157,7 +152,6 @@ static BOOL api_eventlog_clear_eventlog(pipes_struct *p) { EVENTLOG_Q_CLEAR_EVENTLOG q_u; EVENTLOG_R_CLEAR_EVENTLOG r_u; - prs_struct *data = &p->in_data.data; prs_struct *rdata = &p->out_data.rdata; diff --git a/source3/rpc_server/srv_eventlog_nt.c b/source3/rpc_server/srv_eventlog_nt.c index a9b0c9bed80..414c99d28e2 100644 --- a/source3/rpc_server/srv_eventlog_nt.c +++ b/source3/rpc_server/srv_eventlog_nt.c @@ -1,7 +1,8 @@ /* * Unix SMB/CIFS implementation. * RPC Pipe client / server routines - * Copyright (C) Marcin Krzysztof Porwit 2005. + * Copyright (C) Marcin Krzysztof Porwit 2005, + * Copyright (C) Gerald (Jerry) Carter 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 @@ -23,56 +24,152 @@ #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV -typedef struct eventlog_info +typedef struct { + char *logname; + char *servername; + uint32 num_records; + uint32 oldest_entry; + uint32 flags; +} EventlogInfo; + + +/******************************************************************** + Inform the external eventlog machinery of default values (on startup + probably) +********************************************************************/ + +void eventlog_refresh_external_parameters( NT_USER_TOKEN *token ) { - /* for use by the \PIPE\eventlog policy */ - fstring source_log_file_name; - fstring source_server_name; - fstring handle_string; - uint32 num_records; - uint32 oldest_entry; - uint32 active_entry; - uint32 flags; -} Eventlog_info; + const char **elogs = lp_eventlog_list(); + int i; + + if ( !elogs ) + return ; + + if ( !*lp_eventlog_control_cmd() ) + return; + + for ( i=0; elogs[i]; i++ ) { + + DEBUG(10,("eventlog_refresh_external_parameters: Refreshing =>[%s]\n", + elogs[i])); + + if ( !control_eventlog_hook( token, elogs[i] ) ) { + DEBUG(0,("eventlog_refresh_external_parameters: failed to refresh [%s]\n", + elogs[i])); + } + } + + return; +} + +/******************************************************************** +********************************************************************/ static void free_eventlog_info(void *ptr) { - struct eventlog_info *info = (struct eventlog_info *)ptr; - memset(info->source_log_file_name, '0', sizeof(*(info->source_log_file_name))); - memset(info->source_server_name, '0', sizeof(*(info->source_server_name))); - memset(info->handle_string, '0', sizeof(*(info->handle_string))); - memset(info, 0, sizeof(*(info))); - SAFE_FREE(info); + TALLOC_FREE( ptr ); } -static Eventlog_info *find_eventlog_info_by_hnd(pipes_struct *p, - POLICY_HND *handle) +/******************************************************************** +********************************************************************/ + +static EventlogInfo *find_eventlog_info_by_hnd(pipes_struct *p, POLICY_HND *handle) { - Eventlog_info *info = NULL; + EventlogInfo *info; - if(!(find_policy_by_hnd(p,handle,(void **)&info))) - { - DEBUG(2,("find_eventlog_info_by_hnd: eventlog not found.\n")); - } + if ( !find_policy_by_hnd(p,handle,(void **)&info) ) { + DEBUG(2,("find_eventlog_info_by_hnd: eventlog not found.\n")); + return NULL; + } - return info; + return info; } -void policy_handle_to_string(POLICY_HND *handle, fstring *dest) +/******************************************************************** + Callout to control the specified event log - passing out only + the MaxSize and Retention values, along with eventlog name + uses smbrun... + INPUT: + OUTPUT: nothing +********************************************************************/ + +BOOL control_eventlog_hook(NT_USER_TOKEN *token, const char *elogname ) { - memset(dest, 0, sizeof(*dest)); - snprintf((char *)dest, sizeof(*dest), "%08X-%08X-%04X-%04X-%02X%02X%02X%02X%02X", - handle->data1, - handle->data2, - handle->data3, - handle->data4, - handle->data5[0], - handle->data5[1], - handle->data5[2], - handle->data5[3], - handle->data5[4]); + char *cmd = lp_eventlog_control_cmd(); + pstring command; + int ret; + int fd = -1; + uint32 uiMaxSize, uiRetention; + pstring path; + REGISTRY_KEY *keyinfo; + REGISTRY_VALUE *val; + REGVAL_CTR *values; + WERROR wresult; + + if ( !cmd || !*cmd ) { + DEBUG(0, ("control_eventlog_hook: No \"eventlog control command\" defined in smb.conf!\n")); + return False; + } + + /* set resonable defaults. 512Kb on size and 1 week on time */ + + uiMaxSize = 0x80000; + uiRetention = 604800; + + /* the general idea is to internally open the registry + key and retreive the values. That way we can continue + to use the same fetch/store api that we use in + srv_reg_nt.c */ + + pstr_sprintf( path, "%s/%s", KEY_EVENTLOG, elogname ); + wresult = regkey_open_internal( &keyinfo, path, token, REG_KEY_READ ); + + if ( !W_ERROR_IS_OK( wresult ) ) { + DEBUG(4,("control_eventlog_hook: Failed to open key [%s] (%s)\n", + path, dos_errstr(wresult) )); + return False; + } + + if ( !(values = TALLOC_ZERO_P( keyinfo, REGVAL_CTR )) ) { + TALLOC_FREE( keyinfo ); + DEBUG(0,("control_eventlog_hook: talloc() failed!\n")); + + return False; + } + fetch_reg_values( keyinfo, values ); + + if ( (val = regval_ctr_getvalue( values, "Retention" )) != NULL ) + uiRetention = IVAL( regval_data_p(val), 0 ); + + if ( (val = regval_ctr_getvalue( values, "MaxSize" )) != NULL ) + uiMaxSize = IVAL( regval_data_p(val), 0 ); + + TALLOC_FREE( keyinfo ); + + /* now run the command */ + + pstr_sprintf(command, "%s \"%s\" %u %u", cmd, elogname, uiRetention, uiMaxSize ); + + DEBUG(10, ("control_eventlog_hook: Running [%s]\n", command)); + ret = smbrun(command, &fd); + DEBUGADD(10, ("returned [%d]\n", ret)); + + if ( ret != 0 ) { + DEBUG(10,("control_eventlog_hook: Command returned [%d]\n", ret)); + if (fd != -1 ) + close(fd); + return False; + } + + close(fd); + return True; } + +/******************************************************************** +********************************************************************/ + /** * Callout to open the specified event log * @@ -81,109 +178,53 @@ void policy_handle_to_string(POLICY_HND *handle, fstring *dest) * OUTPUT: the string "SUCCESS" if the command succeeded * no such string if there was a failure. */ -static BOOL _eventlog_open_eventlog_hook(Eventlog_info *info) +static BOOL open_eventlog_hook( EventlogInfo *info ) { - char *cmd = lp_eventlog_open_cmd(); - char **qlines; - pstring command; - int numlines = 0; - int ret; - int fd = -1; - - if(cmd == NULL || strlen(cmd) == 0) - { - DEBUG(0, ("Must define an \"eventlog open command\" entry in the config.\n")); - return False; - } - - memset(command, 0, sizeof(command)); - slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", - cmd, - info->source_log_file_name, - info->handle_string); - - DEBUG(10, ("Running [%s]\n", command)); - ret = smbrun(command, &fd); - DEBUGADD(10, ("returned [%d]\n", ret)); - - if(ret != 0) - { - if(fd != -1) - close(fd); - return False; - } + char *cmd = lp_eventlog_open_cmd(); + char **qlines; + pstring command; + int numlines = 0; + int ret; + int fd = -1; + + if ( !cmd || !*cmd ) { + DEBUG(0, ("Must define an \"eventlog open command\" entry in the config.\n")); + return False; + } + + pstr_sprintf(command, "%s \"%s\"", cmd, info->logname ); - qlines = fd_lines_load(fd, &numlines); - DEBUGADD(10, ("Lines returned = [%d]\n", numlines)); - close(fd); + DEBUG(10, ("Running [%s]\n", command)); + ret = smbrun(command, &fd); + DEBUGADD(10, ("returned [%d]\n", ret)); - if(numlines) - { - DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0])); - if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS"))) - { - DEBUGADD(10, ("Able to open [%s].\n", info->source_log_file_name)); - file_lines_free(qlines); - return True; + if(ret != 0) { + if(fd != -1) { + close(fd); + } + return False; } - } - file_lines_free(qlines); - return False; -} + qlines = fd_lines_load(fd, &numlines); + DEBUGADD(10, ("Lines returned = [%d]\n", numlines)); + close(fd); -WERROR _eventlog_open_eventlog(pipes_struct *p, - EVENTLOG_Q_OPEN_EVENTLOG *q_u, - EVENTLOG_R_OPEN_EVENTLOG *r_u) -{ - Eventlog_info *info = NULL; - - if(!q_u || !r_u) - return WERR_NOMEM; - - if((info = SMB_MALLOC_P(Eventlog_info)) == NULL) - return WERR_NOMEM; - - ZERO_STRUCTP(info); - - if(q_u->servername_ptr != 0) - { - unistr2_to_ascii(info->source_server_name, &(q_u->servername), sizeof(info->source_server_name)); - } - else - { - /* if servername == NULL, use the local computer */ - fstrcpy(info->source_server_name, global_myname()); - } - DEBUG(10, ("_eventlog_open_eventlog: Using [%s] as the server name.\n", info->source_server_name)); - - if(q_u->sourcename_ptr != 0) - { - unistr2_to_ascii(info->source_log_file_name, &(q_u->sourcename), sizeof(info->source_log_file_name)); - } - else - { - /* if sourcename == NULL, default to "Application" log */ - fstrcpy(info->source_log_file_name, "Application"); - } - DEBUG(10, ("_eventlog_open_eventlog: Using [%s] as the source log file.\n", info->source_log_file_name)); - - if(!create_policy_hnd(p, &(r_u->handle), free_eventlog_info, (void *)info)) - { - free_eventlog_info(info); - return WERR_NOMEM; - } - - policy_handle_to_string(&r_u->handle, &info->handle_string); - - if(!(_eventlog_open_eventlog_hook(info))) - { - close_policy_hnd(p, &r_u->handle); - return WERR_BADFILE; - } - - return WERR_OK; + if(numlines) { + DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0])); + if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS"))) { + DEBUGADD(10, ("Able to open [%s].\n", info->logname)); + file_lines_free(qlines); + return True; + } + } + + file_lines_free(qlines); + + return False; } + +/******************************************************************** +********************************************************************/ /** * Callout to get the number of records in the specified event log * @@ -192,74 +233,52 @@ WERROR _eventlog_open_eventlog(pipes_struct *p, * OUTPUT: A single line with a single integer containing the number of * entries in the log. If there are no entries in the log, return 0. */ -static BOOL _eventlog_get_num_records_hook(Eventlog_info *info) -{ - char *cmd = lp_eventlog_num_records_cmd(); - char **qlines; - pstring command; - int numlines = 0; - int ret; - int fd = -1; - - if(cmd == NULL || strlen(cmd) == 0) - { - DEBUG(0, ("Must define an \"eventlog num records command\" entry in the config.\n")); - return False; - } - - memset(command, 0, sizeof(command)); - slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", - cmd, - info->source_log_file_name, - info->handle_string); - - DEBUG(10, ("Running [%s]\n", command)); - ret = smbrun(command, &fd); - DEBUGADD(10, ("returned [%d]\n", ret)); - - if(ret != 0) - { - if(fd != -1) - close(fd); - return False; - } - qlines = fd_lines_load(fd, &numlines); - DEBUGADD(10, ("Lines returned = [%d]\n", numlines)); - close(fd); +static BOOL get_num_records_hook(EventlogInfo *info) +{ + char *cmd = lp_eventlog_num_records_cmd(); + char **qlines; + pstring command; + int numlines = 0; + int ret; + int fd = -1; + + if ( !cmd || !*cmd ) { + DEBUG(0, ("Must define an \"eventlog num records command\" entry in the config.\n")); + return False; + } - if(numlines) - { - DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0])); - sscanf(qlines[0], "%d", &(info->num_records)); - file_lines_free(qlines); - return True; - } + pstr_sprintf( command, "%s \"%s\"", cmd, info->logname ); - file_lines_free(qlines); - return False; -} + DEBUG(10, ("Running [%s]\n", command)); + ret = smbrun(command, &fd); + DEBUGADD(10, ("returned [%d]\n", ret)); -WERROR _eventlog_get_num_records(pipes_struct *p, - EVENTLOG_Q_GET_NUM_RECORDS *q_u, - EVENTLOG_R_GET_NUM_RECORDS *r_u) -{ - Eventlog_info *info = NULL; - POLICY_HND *handle = NULL; + if(ret != 0) { + if(fd != -1) { + close(fd); + } + return False; + } - if(!q_u || !r_u) - return WERR_NOMEM; + qlines = fd_lines_load(fd, &numlines); + DEBUGADD(10, ("Lines returned = [%d]\n", numlines)); + close(fd); - handle = &(q_u->handle); - info = find_eventlog_info_by_hnd(p, handle); + if(numlines) { + DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0])); + sscanf(qlines[0], "%d", &(info->num_records)); + file_lines_free(qlines); + return True; + } - if(!(_eventlog_get_num_records_hook(info))) - return WERR_BADFILE; + file_lines_free(qlines); + return False; +} - r_u->num_records = info->num_records; +/******************************************************************** +********************************************************************/ - return WERR_OK; -} /** * Callout to find the oldest record in the log * @@ -269,75 +288,51 @@ WERROR _eventlog_get_num_records(pipes_struct *p, * oldest entry. Must be 1 or greater. * If there are no entries in the log, returns a 0 */ -static BOOL _eventlog_get_oldest_entry_hook(Eventlog_info *info) -{ - char *cmd = lp_eventlog_oldest_record_cmd(); - char **qlines; - pstring command; - int numlines = 0; - int ret; - int fd = -1; - - if(cmd == NULL || strlen(cmd) == 0) - { - DEBUG(0, ("Must define an \"eventlog oldest record command\" entry in the config.\n")); - return False; - } - - memset(command, 0, sizeof(command)); - slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", - cmd, - info->source_log_file_name, - info->handle_string); - - DEBUG(10, ("Running [%s]\n", command)); - ret = smbrun(command, &fd); - DEBUGADD(10, ("returned [%d]\n", ret)); - - if(ret != 0) - { - if(fd != -1) - close(fd); - return False; - } - qlines = fd_lines_load(fd, &numlines); - DEBUGADD(10, ("Lines returned = [%d]\n", numlines)); - close(fd); - - if(numlines) - { - DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0])); - sscanf(qlines[0], "%d", &(info->oldest_entry)); - file_lines_free(qlines); - return True; - } - - file_lines_free(qlines); - return False; -} - -WERROR _eventlog_get_oldest_entry(pipes_struct *p, - EVENTLOG_Q_GET_OLDEST_ENTRY *q_u, - EVENTLOG_R_GET_OLDEST_ENTRY *r_u) +static BOOL get_oldest_entry_hook(EventlogInfo *info) { - Eventlog_info *info = NULL; - POLICY_HND *handle = NULL; + char *cmd = lp_eventlog_oldest_record_cmd(); + char **qlines; + pstring command; + int numlines = 0; + int ret; + int fd = -1; + + if ( !cmd || !*cmd ) { + DEBUG(0, ("Must define an \"eventlog oldest record command\" entry in the config.\n")); + return False; + } + + pstr_sprintf( command, "%s \"%s\"", cmd, info->logname ); - if(!q_u || !r_u) - return WERR_NOMEM; + DEBUG(10, ("Running [%s]\n", command)); + ret = smbrun(command, &fd); + DEBUGADD(10, ("returned [%d]\n", ret)); - handle = &(q_u->handle); - info = find_eventlog_info_by_hnd(p, handle); + if(ret != 0) { + if(fd != -1) { + close(fd); + } + return False; + } - if(!(_eventlog_get_oldest_entry_hook(info))) - return WERR_BADFILE; + qlines = fd_lines_load(fd, &numlines); + DEBUGADD(10, ("Lines returned = [%d]\n", numlines)); + close(fd); - r_u->oldest_entry = info->oldest_entry; + if(numlines) { + DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0])); + sscanf(qlines[0], "%d", &(info->oldest_entry)); + file_lines_free(qlines); + return True; + } - return WERR_OK; + file_lines_free(qlines); + return False; } +/******************************************************************** +********************************************************************/ /** * Callout to close the specified event log * @@ -346,270 +341,206 @@ WERROR _eventlog_get_oldest_entry(pipes_struct *p, * OUTPUT: the string "SUCCESS" if the command succeeded * no such string if there was a failure. */ -static BOOL _eventlog_close_eventlog_hook(Eventlog_info *info) + +static BOOL close_eventlog_hook(EventlogInfo *info) { - char *cmd = lp_eventlog_close_cmd(); - char **qlines; - pstring command; - int numlines = 0; - int ret; - int fd = -1; - - if(cmd == NULL || strlen(cmd) == 0) - { - DEBUG(0, ("Must define an \"eventlog close command\" entry in the config.\n")); - return False; - } - - memset(command, 0, sizeof(command)); - slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", - cmd, - info->source_log_file_name, - info->handle_string); - - DEBUG(10, ("Running [%s]\n", command)); - ret = smbrun(command, &fd); - DEBUGADD(10, ("returned [%d]\n", ret)); - - if(ret != 0) - { - if(fd != -1) - close(fd); - return False; - } + char *cmd = lp_eventlog_close_cmd(); + char **qlines; + pstring command; + int numlines = 0; + int ret; + int fd = -1; + + if ( !cmd || !*cmd ) { + DEBUG(0, ("Must define an \"eventlog close command\" entry in the config.\n")); + return False; + } - qlines = fd_lines_load(fd, &numlines); - DEBUGADD(10, ("Lines returned = [%d]\n", numlines)); - close(fd); + pstr_sprintf( command, "%s \"%s\"", cmd, info->logname ); - if(numlines) - { - DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0])); - if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS"))) - { - DEBUGADD(10, ("Able to close [%s].\n", info->source_log_file_name)); - file_lines_free(qlines); - return True; - } - } + DEBUG(10, ("Running [%s]\n", command)); + ret = smbrun(command, &fd); + DEBUGADD(10, ("returned [%d]\n", ret)); - file_lines_free(qlines); - return False; -} + if(ret != 0) { + if(fd != -1) { + close(fd); + } + return False; + } -WERROR _eventlog_close_eventlog(pipes_struct *p, - EVENTLOG_Q_CLOSE_EVENTLOG *q_u, - EVENTLOG_R_CLOSE_EVENTLOG *r_u) -{ - Eventlog_info *info = NULL; - POLICY_HND *handle; + qlines = fd_lines_load(fd, &numlines); + DEBUGADD(10, ("Lines returned = [%d]\n", numlines)); + close(fd); - if(!q_u || !r_u) - return WERR_NOMEM; + if(numlines) { + DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0])); + if(0 == strncmp(qlines[0], "SUCCESS", 7)) { + DEBUGADD(10, ("Able to close [%s].\n", info->logname)); + file_lines_free(qlines); + return True; + } + } - handle = &(q_u->handle); - - info = find_eventlog_info_by_hnd(p, handle); - if(!(_eventlog_close_eventlog_hook(info))) - return WERR_BADFILE; - - if(!(close_policy_hnd(p, handle))) - { - /* WERR_NOMEM is probably not the correct error, but until I figure out a better - one it will have to do */ - return WERR_NOMEM; - } - - return WERR_OK; + file_lines_free(qlines); + return False; } -static BOOL _eventlog_read_parse_line(char *line, Eventlog_entry *entry, BOOL *eor) +/******************************************************************** +********************************************************************/ + +static BOOL parse_logentry(char *line, Eventlog_entry *entry, BOOL *eor) { - char *start = NULL, *stop = NULL; - pstring temp; - int temp_len = 0, i; + char *start = NULL, *stop = NULL; + pstring temp; + int temp_len = 0, i; - start = line; + start = line; - /* empty line signyfiying record delimeter, or we're at the end of the buffer */ - if(start == NULL || strlen(start) == 0) - { - DEBUG(6, ("_eventlog_read_parse_line: found end-of-record indicator.\n")); - *eor = True; - return True; - } - if(!(stop = strchr(line, ':'))) - return False; + /* empty line signyfiying record delimeter, or we're at the end of the buffer */ + if(start == NULL || strlen(start) == 0) { + DEBUG(6, ("parse_logentry: found end-of-record indicator.\n")); + *eor = True; + return True; + } + if(!(stop = strchr(line, ':'))) { + return False; + } - DEBUG(6, ("_eventlog_read_parse_line: trying to parse [%s].\n", line)); - - if(0 == strncmp(start, "LEN", stop - start)) - { - /* This will get recomputed later anyway -- probably not necessary */ - entry->record.length = atoi(stop + 1); - } - else if(0 == strncmp(start, "RS1", stop - start)) - { - /* For now all these reserved entries seem to have the same value, - which can be hardcoded to int(1699505740) for now */ - entry->record.reserved1 = atoi(stop + 1); - } - else if(0 == strncmp(start, "RCN", stop - start)) - { - entry->record.record_number = atoi(stop + 1); - } - else if(0 == strncmp(start, "TMG", stop - start)) - { - entry->record.time_generated = atoi(stop + 1); - } - else if(0 == strncmp(start, "TMW", stop - start)) - { - entry->record.time_written = atoi(stop + 1); - } - else if(0 == strncmp(start, "EID", stop - start)) - { - entry->record.event_id = atoi(stop + 1); - } - else if(0 == strncmp(start, "ETP", stop - start)) - { - if(strstr(start, "ERROR")) - { - entry->record.event_type = EVENTLOG_ERROR_TYPE; - } - else if(strstr(start, "WARNING")) - { - entry->record.event_type = EVENTLOG_WARNING_TYPE; - } - else if(strstr(start, "INFO")) - { - entry->record.event_type = EVENTLOG_INFORMATION_TYPE; - } - else if(strstr(start, "AUDIT_SUCCESS")) - { - entry->record.event_type = EVENTLOG_AUDIT_SUCCESS; - } - else if(strstr(start, "AUDIT_FAILURE")) - { - entry->record.event_type = EVENTLOG_AUDIT_FAILURE; - } - else if(strstr(start, "SUCCESS")) - { - entry->record.event_type = EVENTLOG_SUCCESS; - } - else - { - /* some other eventlog type -- currently not defined in MSDN docs, so error out */ - return False; - } - } + DEBUG(6, ("parse_logentry: trying to parse [%s].\n", line)); + + if(0 == strncmp(start, "LEN", stop - start)) { + /* This will get recomputed later anyway -- probably not necessary */ + entry->record.length = atoi(stop + 1); + } else if(0 == strncmp(start, "RS1", stop - start)) { + /* For now all these reserved entries seem to have the same value, + which can be hardcoded to int(1699505740) for now */ + entry->record.reserved1 = atoi(stop + 1); + } else if(0 == strncmp(start, "RCN", stop - start)) { + entry->record.record_number = atoi(stop + 1); + } else if(0 == strncmp(start, "TMG", stop - start)) { + entry->record.time_generated = atoi(stop + 1); + } else if(0 == strncmp(start, "TMW", stop - start)) { + entry->record.time_written = atoi(stop + 1); + } else if(0 == strncmp(start, "EID", stop - start)) { + entry->record.event_id = atoi(stop + 1); + } else if(0 == strncmp(start, "ETP", stop - start)) { + if(strstr(start, "ERROR")) { + entry->record.event_type = EVENTLOG_ERROR_TYPE; + } else if(strstr(start, "WARNING")) { + entry->record.event_type = EVENTLOG_WARNING_TYPE; + } else if(strstr(start, "INFO")) { + entry->record.event_type = EVENTLOG_INFORMATION_TYPE; + } else if(strstr(start, "AUDIT_SUCCESS")) { + entry->record.event_type = EVENTLOG_AUDIT_SUCCESS; + } else if(strstr(start, "AUDIT_FAILURE")) { + entry->record.event_type = EVENTLOG_AUDIT_FAILURE; + } else if(strstr(start, "SUCCESS")) { + entry->record.event_type = EVENTLOG_SUCCESS; + } else { + /* some other eventlog type -- currently not defined in MSDN docs, so error out */ + return False; + } + } /* - else if(0 == strncmp(start, "NST", stop - start)) - { - entry->record.num_strings = atoi(stop + 1); - } + else if(0 == strncmp(start, "NST", stop - start)) + { + entry->record.num_strings = atoi(stop + 1); + } */ - else if(0 == strncmp(start, "ECT", stop - start)) - { - entry->record.event_category = atoi(stop + 1); - } - else if(0 == strncmp(start, "RS2", stop - start)) - { - entry->record.reserved2 = atoi(stop + 1); - } - else if(0 == strncmp(start, "CRN", stop - start)) - { - entry->record.closing_record_number = atoi(stop + 1); - } - else if(0 == strncmp(start, "USL", stop - start)) - { - entry->record.user_sid_length = atoi(stop + 1); - } - else if(0 == strncmp(start, "SRC", stop - start)) - { - memset(temp, 0, sizeof(temp)); - stop++; - while(isspace(stop[0])) - stop++; - temp_len = strlen(stop); - strncpy(temp, stop, temp_len); - rpcstr_push((void *)(entry->data_record.source_name), temp, - sizeof(entry->data_record.source_name), STR_TERMINATE); - entry->data_record.source_name_len = (strlen_w(entry->data_record.source_name)* 2) + 2; - } - else if(0 == strncmp(start, "SRN", stop - start)) - { - memset(temp, 0, sizeof(temp)); - stop++; - while(isspace(stop[0])) - stop++; - temp_len = strlen(stop); - strncpy(temp, stop, temp_len); - rpcstr_push((void *)(entry->data_record.computer_name), temp, - sizeof(entry->data_record.computer_name), STR_TERMINATE); - entry->data_record.computer_name_len = (strlen_w(entry->data_record.computer_name)* 2) + 2; - } - else if(0 == strncmp(start, "SID", stop - start)) - { - memset(temp, 0, sizeof(temp)); - stop++; - while(isspace(stop[0])) - stop++; - temp_len = strlen(stop); - strncpy(temp, stop, temp_len); - rpcstr_push((void *)(entry->data_record.sid), temp, - sizeof(entry->data_record.sid), STR_TERMINATE); - entry->record.user_sid_length = (strlen_w(entry->data_record.sid) * 2) + 2; - } - else if(0 == strncmp(start, "STR", stop - start)) - { - /* skip past initial ":" */ - stop++; - /* now skip any other leading whitespace */ - while(isspace(stop[0])) - stop++; - temp_len = strlen(stop); - memset(temp, 0, sizeof(temp)); - strncpy(temp, stop, temp_len); - rpcstr_push((void *)(entry->data_record.strings + entry->data_record.strings_len), - temp, - sizeof(entry->data_record.strings) - entry->data_record.strings_len, - STR_TERMINATE); - entry->data_record.strings_len += temp_len + 1; - fprintf(stderr, "Dumping strings:\n"); - for(i = 0; i < entry->data_record.strings_len; i++) - { - fputc((char)entry->data_record.strings[i], stderr); - } - fprintf(stderr, "\nDone\n"); - entry->record.num_strings++; - } - else if(0 == strncmp(start, "DAT", stop - start)) - { - /* Now that we're done processing the STR data, adjust the length to account for - unicode, then proceed with the DAT data. */ - entry->data_record.strings_len *= 2; - /* skip past initial ":" */ - stop++; - /* now skip any other leading whitespace */ - while(isspace(stop[0])) - stop++; - memset(temp, 0, sizeof(temp)); - temp_len = strlen(stop); - strncpy(temp, stop, temp_len); - rpcstr_push((void *)(entry->data_record.user_data), temp, - sizeof(entry->data_record.user_data), STR_TERMINATE); - entry->data_record.user_data_len = (strlen_w((const smb_ucs2_t *)entry->data_record.user_data) * 2) + 2; - } - else - { - /* some other eventlog entry -- not implemented, so dropping on the floor */ - DEBUG(10, ("Unknown entry [%s]. Ignoring.\n", line)); - /* For now return true so that we can keep on parsing this mess. Eventually - we will return False here. */ + else if(0 == strncmp(start, "ECT", stop - start)) { + entry->record.event_category = atoi(stop + 1); + } else if(0 == strncmp(start, "RS2", stop - start)) { + entry->record.reserved2 = atoi(stop + 1); + } else if(0 == strncmp(start, "CRN", stop - start)) { + entry->record.closing_record_number = atoi(stop + 1); + } else if(0 == strncmp(start, "USL", stop - start)) { + entry->record.user_sid_length = atoi(stop + 1); + } else if(0 == strncmp(start, "SRC", stop - start)) { + memset(temp, 0, sizeof(temp)); + stop++; + while(isspace(stop[0])) { + stop++; + } + temp_len = strlen(stop); + strncpy(temp, stop, temp_len); + rpcstr_push((void *)(entry->data_record.source_name), temp, + sizeof(entry->data_record.source_name), STR_TERMINATE); + entry->data_record.source_name_len = (strlen_w(entry->data_record.source_name)* 2) + 2; + } else if(0 == strncmp(start, "SRN", stop - start)) { + memset(temp, 0, sizeof(temp)); + stop++; + while(isspace(stop[0])) { + stop++; + } + temp_len = strlen(stop); + strncpy(temp, stop, temp_len); + rpcstr_push((void *)(entry->data_record.computer_name), temp, + sizeof(entry->data_record.computer_name), STR_TERMINATE); + entry->data_record.computer_name_len = (strlen_w(entry->data_record.computer_name)* 2) + 2; + } else if(0 == strncmp(start, "SID", stop - start)) { + memset(temp, 0, sizeof(temp)); + stop++; + while(isspace(stop[0])) { + stop++; + } + temp_len = strlen(stop); + strncpy(temp, stop, temp_len); + rpcstr_push((void *)(entry->data_record.sid), temp, + sizeof(entry->data_record.sid), STR_TERMINATE); + entry->record.user_sid_length = (strlen_w(entry->data_record.sid) * 2) + 2; + } else if(0 == strncmp(start, "STR", stop - start)) { + /* skip past initial ":" */ + stop++; + /* now skip any other leading whitespace */ + while(isspace(stop[0])) { + stop++; + } + temp_len = strlen(stop); + memset(temp, 0, sizeof(temp)); + strncpy(temp, stop, temp_len); + rpcstr_push((void *)(entry->data_record.strings + entry->data_record.strings_len), + temp, + sizeof(entry->data_record.strings) - entry->data_record.strings_len, + STR_TERMINATE); + entry->data_record.strings_len += temp_len + 1; + fprintf(stderr, "Dumping strings:\n"); + for(i = 0; i < entry->data_record.strings_len; i++) { + fputc((char)entry->data_record.strings[i], stderr); + } + fprintf(stderr, "\nDone\n"); + entry->record.num_strings++; + } else if(0 == strncmp(start, "DAT", stop - start)) { + /* Now that we're done processing the STR data, adjust the length to account for + unicode, then proceed with the DAT data. */ + entry->data_record.strings_len *= 2; + /* skip past initial ":" */ + stop++; + /* now skip any other leading whitespace */ + while(isspace(stop[0])) { + stop++; + } + entry->data_record.user_data_len = strlen(stop); + memset(entry->data_record.user_data, 0, sizeof(entry->data_record.user_data)); + if(entry->data_record.user_data_len > 0) { + /* copy no more than the first 1024 bytes */ + if(entry->data_record.user_data_len > sizeof(entry->data_record.user_data)) + entry->data_record.user_data_len = sizeof(entry->data_record.user_data); + memcpy(entry->data_record.user_data, stop, entry->data_record.user_data_len); + } + } else { + /* some other eventlog entry -- not implemented, so dropping on the floor */ + DEBUG(10, ("Unknown entry [%s]. Ignoring.\n", line)); + /* For now return true so that we can keep on parsing this mess. Eventually + we will return False here. */ + return True; + } return True; - } - return True; } + +/******************************************************************** +********************************************************************/ + /** * Callout to read entries from the specified event log * @@ -640,254 +571,162 @@ static BOOL _eventlog_read_parse_line(char *line, Eventlog_entry *entry, BOOL *e * DAT:[(uint8)] - The user-defined data portion of the event log. Can not be multiple lines. * - end-of-record indicator */ -static BOOL _eventlog_read_eventlog_hook(Eventlog_info *info, - Eventlog_entry *entry, - const char *direction, - int starting_record, - int buffer_size, - BOOL *eof, - char ***buffer, - int *numlines) + +static BOOL read_eventlog_hook(EventlogInfo *info, Eventlog_entry *entry, + const char *direction, int starting_record, + int buffer_size, BOOL *eof, + char ***buffer, int *numlines) { - char *cmd = lp_eventlog_read_cmd(); - pstring command; - int ret; - int fd = -1; + char *cmd = lp_eventlog_read_cmd(); + pstring command; + int ret; + int fd = -1; - if(info == NULL) - return False; + if ( !info ) + return False; - if(cmd == NULL || strlen(cmd) == 0) - { - DEBUG(0, ("Must define an \"eventlog read command\" entry in the config.\n")); - return False; - } - - slprintf(command, sizeof(command)-1, "%s \"%s\" %s %d %d \"%s\"", - cmd, - info->source_log_file_name, - direction, - starting_record, - buffer_size, - info->handle_string); - - *numlines = 0; - - DEBUG(10, ("Running [%s]\n", command)); - ret = smbrun(command, &fd); - DEBUGADD(10, ("returned [%d]\n", ret)); - - if(ret != 0) - { - if(fd != -1) - close(fd); - return False; - } + if ( !cmd || !*cmd ) { + DEBUG(0, ("Must define an \"eventlog read command\" entry in the config.\n")); + return False; + } - *buffer = fd_lines_load(fd, numlines); - DEBUGADD(10, ("Lines returned = [%d]\n", *numlines)); - close(fd); + pstr_sprintf( command, "%s \"%s\" %s %d %d", + cmd, info->logname, direction, starting_record, buffer_size ); + + *numlines = 0; + + DEBUG(10, ("Running [%s]\n", command)); + ret = smbrun(command, &fd); + DEBUGADD(10, ("returned [%d]\n", ret)); + + if(ret != 0) { + if(fd != -1) { + close(fd); + } + return False; + } + + *buffer = fd_lines_load(fd, numlines); + DEBUGADD(10, ("Lines returned = [%d]\n", *numlines)); + close(fd); - if(*numlines) - { - /* - for(i = 0; i < numlines; i++) - { - DEBUGADD(10, ("Line[%d] = %s\n", i, qlines[i])); - _eventlog_read_parse_line(qlines[i], entry); + if(*numlines) { + /* + for(i = 0; i < numlines; i++) + { + DEBUGADD(10, ("Line[%d] = %s\n", i, qlines[i])); + parse_logentry(qlines[i], entry); + } + file_lines_free(qlines); + */ + *eof = False; + return True; } - file_lines_free(qlines); - */ - *eof = False; - return True; - } - *eof = True; + *eof = True; /* file_lines_free(qlines);*/ - return False; + return False; } - -static Eventlog_entry *_eventlog_read_package_entry(prs_struct *ps, + +/******************************************************************** +********************************************************************/ + +static Eventlog_entry *read_package_entry(prs_struct *ps, EVENTLOG_Q_READ_EVENTLOG *q_u, EVENTLOG_R_READ_EVENTLOG *r_u, Eventlog_entry *entry) { - uint8 *offset; - Eventlog_entry *ee_new = NULL; - - ee_new = PRS_ALLOC_MEM(ps, Eventlog_entry, 1); - if(ee_new == NULL) - return NULL; - - entry->data_record.sid_padding = ((4 - ((entry->data_record.source_name_len - + entry->data_record.computer_name_len) % 4)) %4); - entry->data_record.data_padding = (4 - ((entry->data_record.strings_len - + entry->data_record.user_data_len) % 4)) % 4; - entry->record.length = sizeof(Eventlog_record); - entry->record.length += entry->data_record.source_name_len; - entry->record.length += entry->data_record.computer_name_len; - if(entry->record.user_sid_length == 0) - { - /* Should not pad to a DWORD boundary for writing out the sid if there is - no SID, so just propagate the padding to pad the data */ - entry->data_record.data_padding += entry->data_record.sid_padding; - entry->data_record.sid_padding = 0; - } - DEBUG(10, ("sid_padding is [%d].\n", entry->data_record.sid_padding)); - DEBUG(10, ("data_padding is [%d].\n", entry->data_record.data_padding)); - - entry->record.length += entry->data_record.sid_padding; - entry->record.length += entry->record.user_sid_length; - entry->record.length += entry->data_record.strings_len; - entry->record.length += entry->data_record.user_data_len; - entry->record.length += entry->data_record.data_padding; - /* need another copy of length at the end of the data */ - entry->record.length += sizeof(entry->record.length); - DEBUG(10, ("entry->record.length is [%d].\n", entry->record.length)); - entry->data = PRS_ALLOC_MEM(ps, uint8, entry->record.length - sizeof(Eventlog_record) - sizeof(entry->record.length)); - if(entry->data == NULL) - return NULL; - offset = entry->data; - memcpy(offset, &(entry->data_record.source_name), entry->data_record.source_name_len); - offset += entry->data_record.source_name_len; - memcpy(offset, &(entry->data_record.computer_name), entry->data_record.computer_name_len); - offset += entry->data_record.computer_name_len; - /* SID needs to be DWORD-aligned */ - offset += entry->data_record.sid_padding; - entry->record.user_sid_offset = sizeof(Eventlog_record) + (offset - entry->data); - memcpy(offset, &(entry->data_record.sid), entry->record.user_sid_length); - offset += entry->record.user_sid_length; - /* Now do the strings */ - entry->record.string_offset = sizeof(Eventlog_record) + (offset - entry->data); - memcpy(offset, &(entry->data_record.strings), entry->data_record.strings_len); - offset += entry->data_record.strings_len; - /* Now do the data */ - entry->record.data_length = entry->data_record.user_data_len; - entry->record.data_offset = sizeof(Eventlog_record) + (offset - entry->data); - memcpy(offset, &(entry->data_record.user_data), entry->data_record.user_data_len); - offset += entry->data_record.user_data_len; - - memcpy(&(ee_new->record), &entry->record, sizeof(Eventlog_record)); - memcpy(&(ee_new->data_record), &entry->data_record, sizeof(Eventlog_data_record)); - ee_new->data = entry->data; - - return ee_new; -} + uint8 *offset; + Eventlog_entry *ee_new = NULL; -static BOOL _eventlog_add_record_to_resp(EVENTLOG_R_READ_EVENTLOG *r_u, Eventlog_entry *ee_new) -{ - Eventlog_entry *insert_point; - - insert_point=r_u->entry; - - if (NULL == insert_point) - { - r_u->entry = ee_new; - ee_new->next = NULL; - } - else - { - while ((NULL != insert_point->next)) - { - insert_point=insert_point->next; - } - ee_new->next = NULL; - insert_point->next = ee_new; - } - r_u->num_records++; - r_u->num_bytes_in_resp += ee_new->record.length; - - return True; + ee_new = PRS_ALLOC_MEM(ps, Eventlog_entry, 1); + if(ee_new == NULL) { + return NULL; + } + + entry->data_record.sid_padding = ((4 - ((entry->data_record.source_name_len + + entry->data_record.computer_name_len) % 4)) %4); + entry->data_record.data_padding = (4 - ((entry->data_record.strings_len + + entry->data_record.user_data_len) % 4)) % 4; + entry->record.length = sizeof(Eventlog_record); + entry->record.length += entry->data_record.source_name_len; + entry->record.length += entry->data_record.computer_name_len; + if(entry->record.user_sid_length == 0) { + /* Should not pad to a DWORD boundary for writing out the sid if there is + no SID, so just propagate the padding to pad the data */ + entry->data_record.data_padding += entry->data_record.sid_padding; + entry->data_record.sid_padding = 0; + } + DEBUG(10, ("sid_padding is [%d].\n", entry->data_record.sid_padding)); + DEBUG(10, ("data_padding is [%d].\n", entry->data_record.data_padding)); + + entry->record.length += entry->data_record.sid_padding; + entry->record.length += entry->record.user_sid_length; + entry->record.length += entry->data_record.strings_len; + entry->record.length += entry->data_record.user_data_len; + entry->record.length += entry->data_record.data_padding; + /* need another copy of length at the end of the data */ + entry->record.length += sizeof(entry->record.length); + DEBUG(10, ("entry->record.length is [%d].\n", entry->record.length)); + entry->data = PRS_ALLOC_MEM(ps, uint8, entry->record.length - sizeof(Eventlog_record) - sizeof(entry->record.length)); + if(entry->data == NULL) { + return NULL; + } + offset = entry->data; + memcpy(offset, &(entry->data_record.source_name), entry->data_record.source_name_len); + offset += entry->data_record.source_name_len; + memcpy(offset, &(entry->data_record.computer_name), entry->data_record.computer_name_len); + offset += entry->data_record.computer_name_len; + /* SID needs to be DWORD-aligned */ + offset += entry->data_record.sid_padding; + entry->record.user_sid_offset = sizeof(Eventlog_record) + (offset - entry->data); + memcpy(offset, &(entry->data_record.sid), entry->record.user_sid_length); + offset += entry->record.user_sid_length; + /* Now do the strings */ + entry->record.string_offset = sizeof(Eventlog_record) + (offset - entry->data); + memcpy(offset, &(entry->data_record.strings), entry->data_record.strings_len); + offset += entry->data_record.strings_len; + /* Now do the data */ + entry->record.data_length = entry->data_record.user_data_len; + entry->record.data_offset = sizeof(Eventlog_record) + (offset - entry->data); + memcpy(offset, &(entry->data_record.user_data), entry->data_record.user_data_len); + offset += entry->data_record.user_data_len; + + memcpy(&(ee_new->record), &entry->record, sizeof(Eventlog_record)); + memcpy(&(ee_new->data_record), &entry->data_record, sizeof(Eventlog_data_record)); + ee_new->data = entry->data; + + return ee_new; } - -WERROR _eventlog_read_eventlog(pipes_struct *p, - EVENTLOG_Q_READ_EVENTLOG *q_u, - EVENTLOG_R_READ_EVENTLOG *r_u) + +/******************************************************************** +********************************************************************/ + +static BOOL add_record_to_resp(EVENTLOG_R_READ_EVENTLOG *r_u, Eventlog_entry *ee_new) { - Eventlog_info *info = NULL; - POLICY_HND *handle; - Eventlog_entry entry, *ee_new; - BOOL eof = False, eor = False; - const char *direction = ""; - uint32 num_records_read = 0; - prs_struct *ps; - int numlines, i; - char **buffer; - - if(!q_u || !r_u) - return WERR_NOMEM; - - handle = &(q_u->handle); - info = find_eventlog_info_by_hnd(p, handle); - info->flags = q_u->flags; - ps = &p->out_data.rdata; - /* if this is the first time we're reading on this handle */ - if(info->active_entry == 0) - { - /* Rather than checking the EVENTLOG_SEQUENTIAL_READ/EVENTLOG_SEEK_READ flags, - we'll just go to the offset specified in the request, or the oldest entry - if no offset is specified */ - if(q_u->offset > 0) - info->active_entry = q_u->offset; - else - info->active_entry = info->oldest_entry; - - } - - if(q_u->flags & EVENTLOG_FORWARDS_READ) - direction = "forward"; - else if(q_u->flags & EVENTLOG_BACKWARDS_READ) - direction = "backward"; - - if(!(_eventlog_read_eventlog_hook(info, &entry, direction, info->active_entry, q_u->max_read_size, &eof, &buffer, &numlines))) - { - if(eof == False) - return WERR_NOMEM; - } - if(numlines > 0) - { - ZERO_STRUCT(entry); - for(i = 0; i < numlines; i++) - { - num_records_read = r_u->num_records; - DEBUGADD(10, ("Line[%d] = [%s]\n", i, buffer[i])); - _eventlog_read_parse_line(buffer[i], &entry, &eor); - if(eor == True) - { - /* package ee_new entry */ - if((ee_new = _eventlog_read_package_entry(ps, q_u, r_u, &entry)) == NULL) - { - free(buffer); - return WERR_NOMEM; - } - /* Now see if there is enough room to add */ - if(r_u->num_bytes_in_resp + ee_new->record.length > q_u->max_read_size) - { - r_u->bytes_in_next_record = ee_new->record.length; - /* response would be too big to fit in client-size buffer */ - break; + Eventlog_entry *insert_point; + + insert_point=r_u->entry; + + if (NULL == insert_point) { + r_u->entry = ee_new; + ee_new->next = NULL; + } else { + while ((NULL != insert_point->next)) { + insert_point=insert_point->next; } - _eventlog_add_record_to_resp(r_u, ee_new); - ZERO_STRUCT(entry); - eor=False; - num_records_read = r_u->num_records - num_records_read; - DEBUG(10, ("_eventlog_read_eventlog: read [%d] records for a total of [%d] records using [%d] bytes out of a max of [%d].\n", - num_records_read, - r_u->num_records, - r_u->num_bytes_in_resp, - q_u->max_read_size)); - /* update the active record */ - if(info->flags & EVENTLOG_FORWARDS_READ) - info->active_entry += num_records_read; - else if(info->flags & EVENTLOG_BACKWARDS_READ) - info->active_entry -= num_records_read; - } - } - free(buffer); - } - - return WERR_OK; + ee_new->next = NULL; + insert_point->next = ee_new; + } + r_u->num_records++; + r_u->num_bytes_in_resp += ee_new->record.length; + + return True; } + +/******************************************************************** +********************************************************************/ + /** * Callout to clear (and optionally backup) a specified event log * @@ -902,96 +741,224 @@ WERROR _eventlog_read_eventlog(pipes_struct *p, * The given log is copied to that location on the server. See comments for * eventlog_io_q_clear_eventlog for info about odd file name behavior */ -static BOOL _eventlog_clear_eventlog_hook(Eventlog_info *info, - pstring backup_file_name) + +static BOOL clear_eventlog_hook(EventlogInfo *info, pstring backup_file_name) { - char *cmd = lp_eventlog_clear_cmd(); - char **qlines; - pstring command; - int numlines = 0; - int ret; - int fd = -1; - - if(cmd == NULL || strlen(cmd) == 0) - { - DEBUG(0, ("Must define an \"eventlog clear command\" entry in the config.\n")); - return False; - } - - memset(command, 0, sizeof(command)); - if(strlen(backup_file_name) > 0) - slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\" \"%s\"", - cmd, - info->source_log_file_name, - backup_file_name, - info->handle_string); - else - slprintf(command, sizeof(command)-1, "%s \"%s\" \"%s\"", - cmd, - info->source_log_file_name, - info->handle_string); - - DEBUG(10, ("Running [%s]\n", command)); - ret = smbrun(command, &fd); - DEBUGADD(10, ("returned [%d]\n", ret)); - - if(ret != 0) - { - if(fd != -1) - close(fd); - return False; - } + char *cmd = lp_eventlog_clear_cmd(); + char **qlines; + pstring command; + int numlines = 0; + int ret; + int fd = -1; + + if ( !cmd || !*cmd ) { + DEBUG(0, ("Must define an \"eventlog clear command\" entry in the config.\n")); + return False; + } + + if ( strlen(backup_file_name) ) + pstr_sprintf( command, "%s \"%s\" \"%s\"", cmd, info->logname, backup_file_name ); + else + pstr_sprintf( command, "%s \"%s\"", cmd, info->logname ); + + DEBUG(10, ("Running [%s]\n", command)); + ret = smbrun(command, &fd); + DEBUGADD(10, ("returned [%d]\n", ret)); - qlines = fd_lines_load(fd, &numlines); - DEBUGADD(10, ("Lines returned = [%d]\n", numlines)); - close(fd); + if(ret != 0) { + if(fd != -1) { + close(fd); + } + return False; + } - if(numlines) - { - DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0])); - if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS"))) - { - DEBUGADD(10, ("Able to clear [%s].\n", info->source_log_file_name)); - file_lines_free(qlines); - return True; + qlines = fd_lines_load(fd, &numlines); + DEBUGADD(10, ("Lines returned = [%d]\n", numlines)); + close(fd); + + if(numlines) { + DEBUGADD(10, ("Line[0] = [%s]\n", qlines[0])); + if(0 == strncmp(qlines[0], "SUCCESS", strlen("SUCCESS"))) { + DEBUGADD(10, ("Able to clear [%s].\n", info->logname)); + file_lines_free(qlines); + return True; + } } - } - file_lines_free(qlines); - return False; + file_lines_free(qlines); + return False; +} + +/******************************************************************* +*******************************************************************/ + +WERROR _eventlog_open_eventlog(pipes_struct *p, EVENTLOG_Q_OPEN_EVENTLOG *q_u, EVENTLOG_R_OPEN_EVENTLOG *r_u) +{ + EventlogInfo *info = NULL; + fstring str; + + if ( !(info = TALLOC_ZERO_P(NULL, EventlogInfo)) ) + return WERR_NOMEM; + + fstrcpy( str, global_myname() ); + if ( q_u->servername.string ) { + rpcstr_pull( str, q_u->servername.string->buffer, + sizeof(str), q_u->servername.string->uni_str_len*2, 0 ); + } + info->servername = talloc_strdup( info, str ); + + fstrcpy( str, "Application" ); + if ( q_u->logname.string ) { + rpcstr_pull( str, q_u->logname.string->buffer, + sizeof(str), q_u->logname.string->uni_str_len*2, 0 ); + } + info->logname = talloc_strdup( info, str ); + + DEBUG(10, ("_eventlog_open_eventlog: Using [%s] as the server name.\n", info->servername)); + DEBUG(10, ("_eventlog_open_eventlog: Using [%s] as the source log file.\n", info->logname)); + + if ( !create_policy_hnd(p, &r_u->handle, free_eventlog_info, (void *)info) ) { + free_eventlog_info(info); + return WERR_NOMEM; + } + + if ( !(open_eventlog_hook(info)) ) { + close_policy_hnd(p, &r_u->handle); + return WERR_BADFILE; + } + + return WERR_OK; } -WERROR _eventlog_clear_eventlog(pipes_struct *p, - EVENTLOG_Q_CLEAR_EVENTLOG *q_u, - EVENTLOG_R_CLEAR_EVENTLOG *r_u) +/******************************************************************** +********************************************************************/ + +WERROR _eventlog_clear_eventlog(pipes_struct *p, EVENTLOG_Q_CLEAR_EVENTLOG *q_u, EVENTLOG_R_CLEAR_EVENTLOG *r_u) { - Eventlog_info *info = NULL; - pstring backup_file_name; - POLICY_HND *handle = NULL; + EventlogInfo *info = find_eventlog_info_by_hnd(p, &q_u->handle); + pstring backup_file_name; - if(!q_u || !r_u) - return WERR_NOMEM; + pstrcpy( backup_file_name, "" ); - handle = &(q_u->handle); - info = find_eventlog_info_by_hnd(p, handle); - memset(backup_file_name, 0, sizeof(backup_file_name)); + if ( q_u->backupfile.string ) + unistr2_to_ascii(backup_file_name, q_u->backupfile.string, sizeof(backup_file_name)); - if(q_u->backup_file_ptr != 0) - { - unistr2_to_ascii(backup_file_name, &(q_u->backup_file), sizeof(backup_file_name)); DEBUG(10, ("_eventlog_clear_eventlog: Using [%s] as the backup file name for log [%s].", - backup_file_name, - info->source_log_file_name)); - } - else - { - /* if backup_file == NULL, do not back up the log before clearing it */ - DEBUG(10, ("_eventlog_clear_eventlog: clearing [%s] log without making a backup.", - info->source_log_file_name)); - } - - if(!(_eventlog_clear_eventlog_hook(info, backup_file_name))) - return WERR_BADFILE; - - return WERR_OK; + backup_file_name, info->logname)); + + if ( !(clear_eventlog_hook(info, backup_file_name)) ) + return WERR_BADFILE; + + return WERR_OK; +} + +/******************************************************************** +********************************************************************/ + +WERROR _eventlog_close_eventlog(pipes_struct *p, EVENTLOG_Q_CLOSE_EVENTLOG *q_u, EVENTLOG_R_CLOSE_EVENTLOG *r_u) +{ + EventlogInfo *info = find_eventlog_info_by_hnd(p,&q_u->handle); + + if ( !(close_eventlog_hook(info)) ) + return WERR_BADFILE; + + if ( !(close_policy_hnd(p, &q_u->handle)) ) { + return WERR_BADFID; + } + + return WERR_OK; } + +/******************************************************************** +********************************************************************/ + +WERROR _eventlog_read_eventlog(pipes_struct *p, EVENTLOG_Q_READ_EVENTLOG *q_u, EVENTLOG_R_READ_EVENTLOG *r_u) +{ + EventlogInfo *info = find_eventlog_info_by_hnd(p, &q_u->handle); + Eventlog_entry entry, *ee_new; + BOOL eof = False, eor = False; + const char *direction = ""; + uint32 num_records_read = 0; + prs_struct *ps; + int numlines, i; + char **buffer; + + info->flags = q_u->flags; + ps = &p->out_data.rdata; + + if ( info->flags & EVENTLOG_FORWARDS_READ ) + direction = "forward"; + else if ( info->flags & EVENTLOG_BACKWARDS_READ ) + direction = "backward"; + + if ( !(read_eventlog_hook(info, &entry, direction, q_u->offset, q_u->max_read_size, &eof, &buffer, &numlines)) ) { + if(eof == False) { + return WERR_NOMEM; + } + } + + if(numlines > 0) { + ZERO_STRUCT(entry); + for(i = 0; i < numlines; i++) { + num_records_read = r_u->num_records; + DEBUGADD(10, ("Line[%d] = [%s]\n", i, buffer[i])); + parse_logentry(buffer[i], &entry, &eor); + if(eor == True) { + /* package ee_new entry */ + if((ee_new = read_package_entry(ps, q_u, r_u, &entry)) == NULL) { + SAFE_FREE(buffer); + return WERR_NOMEM; + } + /* Now see if there is enough room to add */ + if(r_u->num_bytes_in_resp + ee_new->record.length > q_u->max_read_size) { + r_u->bytes_in_next_record = ee_new->record.length; + /* response would be too big to fit in client-size buffer */ + break; + } + add_record_to_resp(r_u, ee_new); + ZERO_STRUCT(entry); + eor=False; + num_records_read = r_u->num_records - num_records_read; + DEBUG(10, ("_eventlog_read_eventlog: read [%d] records for a total of [%d] records using [%d] bytes out of a max of [%d].\n", + num_records_read, + r_u->num_records, + r_u->num_bytes_in_resp, + q_u->max_read_size)); + } + } + SAFE_FREE(buffer); + } + + return WERR_OK; +} + +/******************************************************************** +********************************************************************/ + +WERROR _eventlog_get_oldest_entry(pipes_struct *p, EVENTLOG_Q_GET_OLDEST_ENTRY *q_u, EVENTLOG_R_GET_OLDEST_ENTRY *r_u) +{ + EventlogInfo *info = find_eventlog_info_by_hnd(p, &q_u->handle); + + if ( !(get_oldest_entry_hook(info)) ) + return WERR_BADFILE; + + r_u->oldest_entry = info->oldest_entry; + + return WERR_OK; +} + +/******************************************************************** +********************************************************************/ + +WERROR _eventlog_get_num_records(pipes_struct *p, EVENTLOG_Q_GET_NUM_RECORDS *q_u, EVENTLOG_R_GET_NUM_RECORDS *r_u) +{ + EventlogInfo *info = find_eventlog_info_by_hnd(p, &q_u->handle); + + if ( !(get_num_records_hook(info)) ) + return WERR_BADFILE; + + r_u->num_records = info->num_records; + + return WERR_OK; +} + diff --git a/source3/rpc_server/srv_lsa_hnd.c b/source3/rpc_server/srv_lsa_hnd.c index 68072b528aa..7da87d5b93d 100644 --- a/source3/rpc_server/srv_lsa_hnd.c +++ b/source3/rpc_server/srv_lsa_hnd.c @@ -253,16 +253,18 @@ BOOL pipe_access_check(pipes_struct *p) user_struct *user = get_valid_user_struct(p->vuid); /* schannel, so we must be ok */ - if (p->netsec_auth_validated) + if (p->pipe_bound && (p->auth.auth_type == PIPE_AUTH_TYPE_SCHANNEL)) { return True; + } if (!user) { DEBUG(3, ("invalid vuid %d\n", p->vuid)); return False; } - if (user->guest) + if (user->guest) { return False; + } } return True; diff --git a/source3/rpc_server/srv_lsa_nt.c b/source3/rpc_server/srv_lsa_nt.c index 021f1dc8e0f..15d420538ef 100644 --- a/source3/rpc_server/srv_lsa_nt.c +++ b/source3/rpc_server/srv_lsa_nt.c @@ -805,17 +805,12 @@ NTSTATUS _lsa_enum_privs(pipes_struct *p, LSA_Q_ENUM_PRIVS *q_u, LSA_R_ENUM_PRIV struct lsa_info *handle; uint32 i; uint32 enum_context = q_u->enum_context; - int num_privs = 0; + int num_privs = count_all_privileges(); LSA_PRIV_ENTRY *entries = NULL; LUID_ATTR luid; /* remember that the enum_context starts at 0 and not 1 */ - if ( lp_enable_privileges() ) - num_privs = count_all_privileges(); - else - DEBUG(2,("_lsa_enum_privs: client trying to enumerate privileges by not enabled in smb.conf!\n")); - if ( enum_context >= num_privs ) return NT_STATUS_NO_MORE_ENTRIES; diff --git a/source3/rpc_server/srv_netlog_nt.c b/source3/rpc_server/srv_netlog_nt.c index 15827a8b55e..5aefe3ca3c9 100644 --- a/source3/rpc_server/srv_netlog_nt.c +++ b/source3/rpc_server/srv_netlog_nt.c @@ -74,6 +74,7 @@ NTSTATUS _net_logon_ctrl(pipes_struct *p, NET_Q_LOGON_CTRL *q_u, /**************************************************************************** Send a message to smbd to do a sam synchronisation **************************************************************************/ + static void send_sync_message(void) { TDB_CONTEXT *tdb; @@ -268,26 +269,33 @@ static BOOL get_md4pw(char *md4pw, char *mach_acct) NTSTATUS _net_req_chal(pipes_struct *p, NET_Q_REQ_CHAL *q_u, NET_R_REQ_CHAL *r_u) { - NTSTATUS status = NT_STATUS_OK; - - rpcstr_pull(p->dc.remote_machine,q_u->uni_logon_clnt.buffer,sizeof(fstring),q_u->uni_logon_clnt.uni_str_len*2,0); - - /* create a server challenge for the client */ - /* Set these to random values. */ - generate_random_buffer(p->dc.srv_chal.data, 8); - - memcpy(p->dc.srv_cred.challenge.data, p->dc.srv_chal.data, 8); + if (!p->dc) { + p->dc = TALLOC_ZERO_P(p->pipe_state_mem_ctx, struct dcinfo); + if (!p->dc) { + return NT_STATUS_NO_MEMORY; + } + } else { + DEBUG(10,("_net_req_chal: new challenge requested. Clearing old state.\n")); + ZERO_STRUCTP(p->dc); + } - memcpy(p->dc.clnt_chal.data , q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data)); - memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data)); + rpcstr_pull(p->dc->remote_machine, + q_u->uni_logon_clnt.buffer, + sizeof(fstring),q_u->uni_logon_clnt.uni_str_len*2,0); - memset((char *)p->dc.sess_key, '\0', sizeof(p->dc.sess_key)); + /* Save the client challenge to the server. */ + memcpy(p->dc->clnt_chal.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data)); - p->dc.challenge_sent = True; + /* Create a server challenge for the client */ + /* Set this to a random value. */ + generate_random_buffer(p->dc->srv_chal.data, 8); + /* set up the LSA REQUEST CHALLENGE response */ - init_net_r_req_chal(r_u, &p->dc.srv_chal, status); + init_net_r_req_chal(r_u, &p->dc->srv_chal, NT_STATUS_OK); - return status; + p->dc->challenge_sent = True; + + return NT_STATUS_OK; } /************************************************************************* @@ -301,50 +309,54 @@ static void init_net_r_auth(NET_R_AUTH *r_a, DOM_CHAL *resp_cred, NTSTATUS statu } /************************************************************************* - _net_auth + _net_auth. Create the initial credentials. *************************************************************************/ NTSTATUS _net_auth(pipes_struct *p, NET_Q_AUTH *q_u, NET_R_AUTH *r_u) { - NTSTATUS status = NT_STATUS_OK; - DOM_CHAL srv_cred; - UTIME srv_time; fstring mach_acct; + fstring remote_machine; + DOM_CHAL srv_chal_out; - srv_time.time = 0; - - rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring),q_u->clnt_id.uni_acct_name.uni_str_len*2,0); + if (!p->dc || !p->dc->challenge_sent) { + return NT_STATUS_ACCESS_DENIED; + } - if (p->dc.challenge_sent && get_md4pw((char *)p->dc.md4pw, mach_acct)) { + rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring), + q_u->clnt_id.uni_acct_name.uni_str_len*2,0); + rpcstr_pull(remote_machine, q_u->clnt_id.uni_comp_name.buffer,sizeof(fstring), + q_u->clnt_id.uni_comp_name.uni_str_len*2,0); - /* from client / server challenges and md4 password, generate sess key */ - cred_session_key(&p->dc.clnt_chal, &p->dc.srv_chal, - p->dc.md4pw, p->dc.sess_key); - - /* check that the client credentials are valid */ - if (cred_assert(&q_u->clnt_chal, p->dc.sess_key, &p->dc.clnt_cred.challenge, srv_time)) { - - /* create server challenge for inclusion in the reply */ - cred_create(p->dc.sess_key, &p->dc.srv_cred.challenge, srv_time, &srv_cred); - - /* copy the received client credentials for use next time */ - memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data)); - memcpy(p->dc.srv_cred .challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data)); - - /* Save the machine account name. */ - fstrcpy(p->dc.mach_acct, mach_acct); - - p->dc.authenticated = True; + if (!get_md4pw((char *)p->dc->mach_pw, mach_acct)) { + DEBUG(0,("_net_auth: creds_server_check failed. Failed to " + "get pasword for machine account %s " + "from client %s\n", + mach_acct, remote_machine )); + return NT_STATUS_ACCESS_DENIED; + } - } else { - status = NT_STATUS_ACCESS_DENIED; - } - } else { - status = NT_STATUS_ACCESS_DENIED; + /* From the client / server challenges and md4 password, generate sess key */ + creds_server_init(p->dc, + &p->dc->clnt_chal, /* Stored client chal. */ + &p->dc->srv_chal, /* Stored server chal. */ + p->dc->mach_pw, + &srv_chal_out); + + /* Check client credentials are valid. */ + if (!creds_server_check(p->dc, &q_u->clnt_chal)) { + DEBUG(0,("_net_auth: creds_server_check failed. Rejecting auth " + "request from client %s machine account %s\n", + remote_machine, mach_acct )); + return NT_STATUS_ACCESS_DENIED; } - + + fstrcpy(p->dc->mach_acct, mach_acct); + fstrcpy(p->dc->remote_machine, remote_machine); + p->dc->authenticated = True; + /* set up the LSA AUTH response */ - init_net_r_auth(r_u, &srv_cred, status); + /* Return the server credentials. */ + init_net_r_auth(r_u, &srv_chal_out, NT_STATUS_OK); return r_u->status; } @@ -367,51 +379,54 @@ static void init_net_r_auth_2(NET_R_AUTH_2 *r_a, NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u) { - NTSTATUS status = NT_STATUS_OK; - DOM_CHAL srv_cred; - UTIME srv_time; NEG_FLAGS srv_flgs; fstring mach_acct; + fstring remote_machine; + DOM_CHAL srv_chal_out; - srv_time.time = 0; + rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring), + q_u->clnt_id.uni_acct_name.uni_str_len*2,0); + rpcstr_pull(remote_machine, q_u->clnt_id.uni_comp_name.buffer,sizeof(fstring), + q_u->clnt_id.uni_comp_name.uni_str_len*2,0); + + if (!p->dc || !p->dc->challenge_sent) { + DEBUG(0,("_net_auth2: no challenge sent to client %s\n", + remote_machine )); + return NT_STATUS_ACCESS_DENIED; + } if ( (lp_server_schannel() == True) && ((q_u->clnt_flgs.neg_flags & NETLOGON_NEG_SCHANNEL) == 0) ) { /* schannel must be used, but client did not offer it. */ - status = NT_STATUS_ACCESS_DENIED; + DEBUG(0,("_net_auth2: schannel required but client failed " + "to offer it. Client was %s\n", + mach_acct )); + return NT_STATUS_ACCESS_DENIED; } - rpcstr_pull(mach_acct, q_u->clnt_id.uni_acct_name.buffer,sizeof(fstring),q_u->clnt_id.uni_acct_name.uni_str_len*2,0); - - if (p->dc.challenge_sent && get_md4pw((char *)p->dc.md4pw, mach_acct)) { - - /* from client / server challenges and md4 password, generate sess key */ - cred_session_key(&p->dc.clnt_chal, &p->dc.srv_chal, - p->dc.md4pw, p->dc.sess_key); - - /* check that the client credentials are valid */ - if (cred_assert(&q_u->clnt_chal, p->dc.sess_key, &p->dc.clnt_cred.challenge, srv_time)) { - - /* create server challenge for inclusion in the reply */ - cred_create(p->dc.sess_key, &p->dc.srv_cred.challenge, srv_time, &srv_cred); - - /* copy the received client credentials for use next time */ - memcpy(p->dc.clnt_cred.challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data)); - memcpy(p->dc.srv_cred .challenge.data, q_u->clnt_chal.data, sizeof(q_u->clnt_chal.data)); - - /* Save the machine account name. */ - fstrcpy(p->dc.mach_acct, mach_acct); - - p->dc.authenticated = True; + if (!get_md4pw((char *)p->dc->mach_pw, mach_acct)) { + DEBUG(0,("_net_auth2: failed to get machine password for " + "account %s\n", + mach_acct )); + return NT_STATUS_ACCESS_DENIED; + } - } else { - status = NT_STATUS_ACCESS_DENIED; - } - } else { - status = NT_STATUS_ACCESS_DENIED; + /* From the client / server challenges and md4 password, generate sess key */ + creds_server_init(p->dc, + &p->dc->clnt_chal, /* Stored client chal. */ + &p->dc->srv_chal, /* Stored server chal. */ + p->dc->mach_pw, + &srv_chal_out); + + /* Check client credentials are valid. */ + if (!creds_server_check(p->dc, &q_u->clnt_chal)) { + DEBUG(0,("_net_auth2: creds_server_check failed. Rejecting auth " + "request from client %s machine account %s\n", + remote_machine, mach_acct )); + return NT_STATUS_ACCESS_DENIED; } - + srv_flgs.neg_flags = 0x000001ff; if (lp_server_schannel() != False) { @@ -419,12 +434,11 @@ NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u) } /* set up the LSA AUTH 2 response */ - init_net_r_auth_2(r_u, &srv_cred, &srv_flgs, status); + init_net_r_auth_2(r_u, &srv_chal_out, &srv_flgs, NT_STATUS_OK); - if (NT_STATUS_IS_OK(status)) { - server_auth2_negotiated = True; - last_dcinfo = p->dc; - } + server_auth2_negotiated = True; + p->dc->authenticated = True; + last_dcinfo = *p->dc; return r_u->status; } @@ -436,32 +450,39 @@ NTSTATUS _net_auth_2(pipes_struct *p, NET_Q_AUTH_2 *q_u, NET_R_AUTH_2 *r_u) NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET *r_u) { NTSTATUS status = NT_STATUS_ACCESS_DENIED; - DOM_CRED srv_cred; - pstring workstation; + fstring workstation; SAM_ACCOUNT *sampass=NULL; BOOL ret = False; unsigned char pwd[16]; int i; uint32 acct_ctrl; + DOM_CRED cred_out; const uchar *old_pw; - /* checks and updates credentials. creates reply credentials */ - if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->clnt_id.cred, &srv_cred))) + if (!p->dc || !p->dc->authenticated) { return NT_STATUS_INVALID_HANDLE; + } - memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred)); + /* Step the creds chain forward. */ + if (!creds_server_step(p->dc, &q_u->clnt_id.cred, &cred_out)) { + DEBUG(0,("_net_srv_pwset: creds_server_step failed. Rejecting auth " + "request from client %s machine account %s\n", + p->dc->remote_machine, p->dc->mach_acct )); + return NT_STATUS_ACCESS_DENIED; + } DEBUG(5,("_net_srv_pwset: %d\n", __LINE__)); rpcstr_pull(workstation,q_u->clnt_id.login.uni_comp_name.buffer, sizeof(workstation),q_u->clnt_id.login.uni_comp_name.uni_str_len*2,0); - DEBUG(3,("Server Password Set by Wksta:[%s] on account [%s]\n", workstation, p->dc.mach_acct)); + DEBUG(3,("_net_srv_pwset: Server Password Set by Wksta:[%s] on account [%s]\n", + workstation, p->dc->mach_acct)); pdb_init_sam(&sampass); become_root(); - ret=pdb_getsampwnam(sampass, p->dc.mach_acct); + ret=pdb_getsampwnam(sampass, p->dc->mach_acct); unbecome_root(); /* Ensure the account exists and is a machine account. */ @@ -481,7 +502,8 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET * return NT_STATUS_ACCOUNT_DISABLED; } - cred_hash3( pwd, q_u->pwd, p->dc.sess_key, 0); + /* Woah - what does this to to the credential chain ? JRA */ + cred_hash3( pwd, q_u->pwd, p->dc->sess_key, 0); DEBUG(100,("Server password set : new given value was :\n")); for(i = 0; i < sizeof(pwd); i++) @@ -498,17 +520,17 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET * } else { /* LM password should be NULL for machines */ - if (!pdb_set_lanman_passwd (sampass, NULL, PDB_CHANGED)) { + if (!pdb_set_lanman_passwd(sampass, NULL, PDB_CHANGED)) { pdb_free_sam(&sampass); return NT_STATUS_NO_MEMORY; } - if (!pdb_set_nt_passwd (sampass, pwd, PDB_CHANGED)) { + if (!pdb_set_nt_passwd(sampass, pwd, PDB_CHANGED)) { pdb_free_sam(&sampass); return NT_STATUS_NO_MEMORY; } - if (!pdb_set_pass_changed_now (sampass)) { + if (!pdb_set_pass_changed_now(sampass)) { pdb_free_sam(&sampass); /* Not quite sure what this one qualifies as, but this will do */ return NT_STATUS_UNSUCCESSFUL; @@ -518,42 +540,41 @@ NTSTATUS _net_srv_pwset(pipes_struct *p, NET_Q_SRV_PWSET *q_u, NET_R_SRV_PWSET * ret = pdb_update_sam_account (sampass); unbecome_root(); } - if (ret) + if (ret) { status = NT_STATUS_OK; + } /* set up the LSA Server Password Set response */ - init_net_r_srv_pwset(r_u, &srv_cred, status); + init_net_r_srv_pwset(r_u, &cred_out, status); pdb_free_sam(&sampass); return r_u->status; } - /************************************************************************* _net_sam_logoff: *************************************************************************/ NTSTATUS _net_sam_logoff(pipes_struct *p, NET_Q_SAM_LOGOFF *q_u, NET_R_SAM_LOGOFF *r_u) { - DOM_CRED srv_cred; - if (!get_valid_user_struct(p->vuid)) return NT_STATUS_NO_SUCH_USER; - /* checks and updates credentials. creates reply credentials */ - if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, - &q_u->sam_id.client.cred, &srv_cred))) + if (!p->dc || !p->dc->authenticated) { return NT_STATUS_INVALID_HANDLE; + } - /* what happens if we get a logoff for an unknown user? */ - memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred)); - - /* XXXX maybe we want to say 'no', reject the client's credentials */ r_u->buffer_creds = 1; /* yes, we have valid server credentials */ - memcpy(&r_u->srv_creds, &srv_cred, sizeof(r_u->srv_creds)); - r_u->status = NT_STATUS_OK; + /* checks and updates credentials. creates reply credentials */ + if (!creds_server_step(p->dc, &q_u->sam_id.client.cred, &r_u->srv_creds)) { + DEBUG(0,("_net_sam_logoff: creds_server_step failed. Rejecting auth " + "request from client %s machine account %s\n", + p->dc->remote_machine, p->dc->mach_acct )); + return NT_STATUS_ACCESS_DENIED; + } + r_u->status = NT_STATUS_OK; return r_u->status; } @@ -567,7 +588,6 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * NTSTATUS status = NT_STATUS_OK; NET_USER_INFO_3 *usr_info = NULL; NET_ID_INFO_CTR *ctr = q_u->sam_id.ctr; - DOM_CRED srv_cred; UNISTR2 *uni_samlogon_user = NULL; UNISTR2 *uni_samlogon_domain = NULL; UNISTR2 *uni_samlogon_workstation = NULL; @@ -588,26 +608,31 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * r_u->switch_value = 0; /* indicates no info */ r_u->auth_resp = 1; /* authoritative response */ r_u->switch_value = 3; /* indicates type of validation user info */ + r_u->buffer_creds = 1; /* Ensure we always return server creds. */ if (!get_valid_user_struct(p->vuid)) return NT_STATUS_NO_SUCH_USER; + if (!p->dc || !p->dc->authenticated) { + return NT_STATUS_INVALID_HANDLE; + } - if ( (lp_server_schannel() == True) && (!p->netsec_auth_validated) ) { + if ( (lp_server_schannel() == True) && (p->auth.auth_type != PIPE_AUTH_TYPE_SCHANNEL) ) { /* 'server schannel = yes' should enforce use of schannel, the client did offer it in auth2, but obviously did not use it. */ + DEBUG(0,("_net_sam_logoff: client %s not using schannel for netlogon\n", + p->dc->remote_machine )); return NT_STATUS_ACCESS_DENIED; } /* checks and updates credentials. creates reply credentials */ - if (!(p->dc.authenticated && deal_with_creds(p->dc.sess_key, &p->dc.clnt_cred, &q_u->sam_id.client.cred, &srv_cred))) - return NT_STATUS_INVALID_HANDLE; - - memcpy(&p->dc.srv_cred, &p->dc.clnt_cred, sizeof(p->dc.clnt_cred)); - - r_u->buffer_creds = 1; /* yes, we have valid server credentials */ - memcpy(&r_u->srv_creds, &srv_cred, sizeof(r_u->srv_creds)); + if (!creds_server_step(p->dc, &q_u->sam_id.client.cred, &r_u->srv_creds)) { + DEBUG(0,("_net_sam_logoff: creds_server_step failed. Rejecting auth " + "request from client %s machine account %s\n", + p->dc->remote_machine, p->dc->mach_acct )); + return NT_STATUS_ACCESS_DENIED; + } /* find the username */ @@ -692,7 +717,7 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * nt_workstation, chal, ctr->auth.id1.lm_owf.data, ctr->auth.id1.nt_owf.data, - p->dc.sess_key)) { + p->dc->sess_key)) { status = NT_STATUS_NO_MEMORY; } break; @@ -791,7 +816,7 @@ NTSTATUS _net_sam_logon(pipes_struct *p, NET_Q_SAM_LOGON *q_u, NET_R_SAM_LOGON * } ZERO_STRUCT(netlogon_sess_key); - memcpy(netlogon_sess_key, p->dc.sess_key, 8); + memcpy(netlogon_sess_key, p->dc->sess_key, 8); if (server_info->user_session_key.length) { memcpy(user_session_key, server_info->user_session_key.data, MIN(sizeof(user_session_key), server_info->user_session_key.length)); diff --git a/source3/rpc_server/srv_ntsvcs.c b/source3/rpc_server/srv_ntsvcs.c new file mode 100644 index 00000000000..48910dbee2e --- /dev/null +++ b/source3/rpc_server/srv_ntsvcs.c @@ -0,0 +1,220 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * Copyright (C) Gerald Carter 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" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_SRV + +/******************************************************************* + ********************************************************************/ + +static BOOL api_ntsvcs_get_version(pipes_struct *p) +{ + NTSVCS_Q_GET_VERSION q_u; + NTSVCS_R_GET_VERSION r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!ntsvcs_io_q_get_version("", &q_u, data, 0)) + return False; + + r_u.status = _ntsvcs_get_version(p, &q_u, &r_u); + + if(!ntsvcs_io_r_get_version("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + ********************************************************************/ + +static BOOL api_ntsvcs_get_device_list_size(pipes_struct *p) +{ + NTSVCS_Q_GET_DEVICE_LIST_SIZE q_u; + NTSVCS_R_GET_DEVICE_LIST_SIZE r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!ntsvcs_io_q_get_device_list_size("", &q_u, data, 0)) + return False; + + r_u.status = _ntsvcs_get_device_list_size(p, &q_u, &r_u); + + if(!ntsvcs_io_r_get_device_list_size("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + ********************************************************************/ + +static BOOL api_ntsvcs_get_device_list(pipes_struct *p) +{ + NTSVCS_Q_GET_DEVICE_LIST q_u; + NTSVCS_R_GET_DEVICE_LIST r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!ntsvcs_io_q_get_device_list("", &q_u, data, 0)) + return False; + + r_u.status = _ntsvcs_get_device_list(p, &q_u, &r_u); + + if(!ntsvcs_io_r_get_device_list("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + ********************************************************************/ + +static BOOL api_ntsvcs_validate_device_instance(pipes_struct *p) +{ + NTSVCS_Q_VALIDATE_DEVICE_INSTANCE q_u; + NTSVCS_R_VALIDATE_DEVICE_INSTANCE r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!ntsvcs_io_q_validate_device_instance("", &q_u, data, 0)) + return False; + + r_u.status = _ntsvcs_validate_device_instance(p, &q_u, &r_u); + + if(!ntsvcs_io_r_validate_device_instance("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + ********************************************************************/ + +static BOOL api_ntsvcs_get_device_reg_property(pipes_struct *p) +{ + NTSVCS_Q_GET_DEVICE_REG_PROPERTY q_u; + NTSVCS_R_GET_DEVICE_REG_PROPERTY r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!ntsvcs_io_q_get_device_reg_property("", &q_u, data, 0)) + return False; + + r_u.status = _ntsvcs_get_device_reg_property(p, &q_u, &r_u); + + if(!ntsvcs_io_r_get_device_reg_property("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + ********************************************************************/ + +static BOOL api_ntsvcs_get_hw_profile_info(pipes_struct *p) +{ + NTSVCS_Q_GET_HW_PROFILE_INFO q_u; + NTSVCS_R_GET_HW_PROFILE_INFO r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!ntsvcs_io_q_get_hw_profile_info("", &q_u, data, 0)) + return False; + + r_u.status = _ntsvcs_get_hw_profile_info(p, &q_u, &r_u); + + if(!ntsvcs_io_r_get_hw_profile_info("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + ********************************************************************/ + +static BOOL api_ntsvcs_hw_profile_flags(pipes_struct *p) +{ + NTSVCS_Q_HW_PROFILE_FLAGS q_u; + NTSVCS_R_HW_PROFILE_FLAGS r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!ntsvcs_io_q_hw_profile_flags("", &q_u, data, 0)) + return False; + + r_u.status = _ntsvcs_hw_profile_flags(p, &q_u, &r_u); + + if(!ntsvcs_io_r_hw_profile_flags("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + \PIPE\svcctl commands + ********************************************************************/ + +static struct api_struct api_ntsvcs_cmds[] = +{ + { "NTSVCS_GET_VERSION" , NTSVCS_GET_VERSION , api_ntsvcs_get_version }, + { "NTSVCS_GET_DEVICE_LIST_SIZE" , NTSVCS_GET_DEVICE_LIST_SIZE , api_ntsvcs_get_device_list_size }, + { "NTSVCS_GET_DEVICE_LIST" , NTSVCS_GET_DEVICE_LIST , api_ntsvcs_get_device_list }, + { "NTSVCS_VALIDATE_DEVICE_INSTANCE" , NTSVCS_VALIDATE_DEVICE_INSTANCE , api_ntsvcs_validate_device_instance }, + { "NTSVCS_GET_DEVICE_REG_PROPERTY" , NTSVCS_GET_DEVICE_REG_PROPERTY , api_ntsvcs_get_device_reg_property }, + { "NTSVCS_GET_HW_PROFILE_INFO" , NTSVCS_GET_HW_PROFILE_INFO , api_ntsvcs_get_hw_profile_info }, + { "NTSVCS_HW_PROFILE_FLAGS" , NTSVCS_HW_PROFILE_FLAGS , api_ntsvcs_hw_profile_flags } +}; + + +void ntsvcs_get_pipe_fns( struct api_struct **fns, int *n_fns ) +{ + *fns = api_ntsvcs_cmds; + *n_fns = sizeof(api_ntsvcs_cmds) / sizeof(struct api_struct); +} + +NTSTATUS rpc_ntsvcs_init(void) +{ + return rpc_pipe_register_commands(SMB_RPC_INTERFACE_VERSION, "ntsvcs", "ntsvcs", api_ntsvcs_cmds, + sizeof(api_ntsvcs_cmds) / sizeof(struct api_struct)); +} diff --git a/source3/rpc_server/srv_ntsvcs_nt.c b/source3/rpc_server/srv_ntsvcs_nt.c new file mode 100644 index 00000000000..0bb9154aaf0 --- /dev/null +++ b/source3/rpc_server/srv_ntsvcs_nt.c @@ -0,0 +1,174 @@ +/* + * Unix SMB/CIFS implementation. + * RPC Pipe client / server routines + * + * Copyright (C) Gerald (Jerry) Carter 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" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_RPC_SRV + +/******************************************************************** +********************************************************************/ + +static char* get_device_path( const char *device ) +{ + static pstring path; + + pstr_sprintf( path, "ROOT\\Legacy_%s\\0000", device ); + + return path; +} + +/******************************************************************** +********************************************************************/ + +WERROR _ntsvcs_get_version( pipes_struct *p, NTSVCS_Q_GET_VERSION *q_u, NTSVCS_R_GET_VERSION *r_u ) +{ + r_u->version = 0x00000400; /* no idea what this means */ + + return WERR_OK; +} + +/******************************************************************** +********************************************************************/ + +WERROR _ntsvcs_get_device_list_size( pipes_struct *p, NTSVCS_Q_GET_DEVICE_LIST_SIZE *q_u, NTSVCS_R_GET_DEVICE_LIST_SIZE *r_u ) +{ + fstring device; + const char *devicepath; + + if ( !q_u->devicename ) + return WERR_ACCESS_DENIED; + + rpcstr_pull(device, q_u->devicename->buffer, sizeof(device), q_u->devicename->uni_str_len*2, 0); + devicepath = get_device_path( device ); + + r_u->size = strlen(devicepath) + 2; + + return WERR_OK; +} + + +/******************************************************************** +********************************************************************/ + +WERROR _ntsvcs_get_device_list( pipes_struct *p, NTSVCS_Q_GET_DEVICE_LIST *q_u, NTSVCS_R_GET_DEVICE_LIST *r_u ) +{ + fstring device; + const char *devicepath; + + if ( !q_u->devicename ) + return WERR_ACCESS_DENIED; + + rpcstr_pull(device, q_u->devicename->buffer, sizeof(device), q_u->devicename->uni_str_len*2, 0); + devicepath = get_device_path( device ); + + /* From the packet traces I've see, I think this really should be an array + of UNISTR2's. But I've never seen more than one string in spite of the + fact that the string in double NULL terminated. -- jerry */ + + init_unistr2( &r_u->devicepath, devicepath, UNI_STR_TERMINATE ); + r_u->needed = r_u->devicepath.uni_str_len; + + return WERR_OK; +} + +/******************************************************************** +********************************************************************/ + +WERROR _ntsvcs_get_device_reg_property( pipes_struct *p, NTSVCS_Q_GET_DEVICE_REG_PROPERTY *q_u, NTSVCS_R_GET_DEVICE_REG_PROPERTY *r_u ) +{ + fstring devicepath; + char *ptr; + REGVAL_CTR *values; + REGISTRY_VALUE *val; + + rpcstr_pull(devicepath, q_u->devicepath.buffer, sizeof(devicepath), q_u->devicepath.uni_str_len*2, 0); + + switch( q_u->property ) { + case DEV_REGPROP_DESC: + /* just parse the service name from the device path and then + lookup the display name */ + if ( !(ptr = strrchr_m( devicepath, '\\' )) ) + return WERR_GENERAL_FAILURE; + *ptr = '\0'; + + if ( !(ptr = strrchr_m( devicepath, '_' )) ) + return WERR_GENERAL_FAILURE; + ptr++; + + if ( !(values = svcctl_fetch_regvalues( ptr, p->pipe_user.nt_user_token )) ) + return WERR_GENERAL_FAILURE; + + if ( !(val = regval_ctr_getvalue( values, "DisplayName" )) ) { + TALLOC_FREE( values ); + return WERR_GENERAL_FAILURE; + } + + r_u->unknown1 = 0x1; /* always 1...tested using a remove device manager connection */ + r_u->size = reg_init_regval_buffer( &r_u->value, val ); + r_u->needed = r_u->size; + + TALLOC_FREE(values); + + break; + + default: + r_u->unknown1 = 0x00437c98; + return WERR_CM_NO_SUCH_VALUE; + } + + return WERR_OK; +} + +/******************************************************************** +********************************************************************/ + +WERROR _ntsvcs_validate_device_instance( pipes_struct *p, NTSVCS_Q_VALIDATE_DEVICE_INSTANCE *q_u, NTSVCS_R_VALIDATE_DEVICE_INSTANCE *r_u ) +{ + /* whatever dude */ + return WERR_OK; +} + +/******************************************************************** +********************************************************************/ + +WERROR _ntsvcs_get_hw_profile_info( pipes_struct *p, NTSVCS_Q_GET_HW_PROFILE_INFO *q_u, NTSVCS_R_GET_HW_PROFILE_INFO *r_u ) +{ + /* steal the incoming buffer */ + + r_u->buffer_size = q_u->buffer_size; + r_u->buffer = q_u->buffer; + + /* Take the 5th Ammentment */ + + return WERR_CM_NO_MORE_HW_PROFILES; +} + +/******************************************************************** +********************************************************************/ + +WERROR _ntsvcs_hw_profile_flags( pipes_struct *p, NTSVCS_Q_HW_PROFILE_FLAGS *q_u, NTSVCS_R_HW_PROFILE_FLAGS *r_u ) +{ + /* just nod your head */ + + return WERR_OK; +} + diff --git a/source3/rpc_server/srv_pipe.c b/source3/rpc_server/srv_pipe.c index 63e8d2f5cda..ba6d9704e80 100644 --- a/source3/rpc_server/srv_pipe.c +++ b/source3/rpc_server/srv_pipe.c @@ -1,11 +1,7 @@ /* * Unix SMB/CIFS implementation. * RPC Pipe client / server routines - * Copyright (C) Andrew Tridgell 1992-1998 - * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, - * Copyright (C) Paul Ashton 1997-1998, - * Copyright (C) Jeremy Allison 1999, - * Copyright (C) Jim McDonough 2003. + * Almost completely rewritten by (C) Jeremy Allison 2005. * * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,12 +26,6 @@ * and DCE/RPC, while minimising the amount of mallocs, unnecessary * data copies, and network traffic. * - * in this version, which takes a "let's learn what's going on and - * get something running" approach, there is additional network - * traffic generated, but the code should be easier to understand... - * - * ... if you read the docs. or stare at packets for weeks on end. - * */ #include "includes.h" @@ -51,52 +41,38 @@ extern struct current_user current_user; We need to transfer the session key from one rpc bind to the next. This is the way the netlogon schannel works. **************************************************************/ + struct dcinfo last_dcinfo; BOOL server_auth2_negotiated = False; -static void NTLMSSPcalc_p( pipes_struct *p, unsigned char *data, int len) +static void free_pipe_ntlmssp_auth_data(struct pipe_auth_data *auth) { - unsigned char *hash = p->ntlmssp_hash; - unsigned char index_i = hash[256]; - unsigned char index_j = hash[257]; - int ind; - - for( ind = 0; ind < len; ind++) { - unsigned char tc; - unsigned char t; + AUTH_NTLMSSP_STATE *a = auth->a_u.auth_ntlmssp_state; - index_i++; - index_j += hash[index_i]; - - tc = hash[index_i]; - hash[index_i] = hash[index_j]; - hash[index_j] = tc; - - t = hash[index_i] + hash[index_j]; - data[ind] = data[ind] ^ hash[t]; + if (a) { + auth_ntlmssp_end(&a); } - - hash[256] = index_i; - hash[257] = index_j; + auth->a_u.auth_ntlmssp_state = NULL; } /******************************************************************* Generate the next PDU to be returned from the data in p->rdata. - We cheat here as this function doesn't handle the special auth - footers of the authenticated bind response reply. + Handle NTLMSSP. ********************************************************************/ -BOOL create_next_pdu(pipes_struct *p) +static BOOL create_next_pdu_ntlmssp(pipes_struct *p) { RPC_HDR_RESP hdr_resp; - BOOL auth_verify = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) != 0); - BOOL auth_seal = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SEAL) != 0); uint32 ss_padding_len = 0; - uint32 data_len; uint32 data_space_available; uint32 data_len_left; + uint32 data_len; prs_struct outgoing_pdu; - uint32 data_pos; + NTSTATUS status; + DATA_BLOB auth_blob; + RPC_HDR_AUTH auth_info; + uint8 auth_type, auth_level; + AUTH_NTLMSSP_STATE *a = p->auth.a_u.auth_ntlmssp_state; /* * If we're in the fault state, keep returning fault PDU's until @@ -124,18 +100,6 @@ BOOL create_next_pdu(pipes_struct *p) * Work out how much we can fit in a single PDU. */ - data_space_available = sizeof(p->out_data.current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN; - if(p->ntlmssp_auth_validated) { - data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN); - } else if(p->netsec_auth_validated) { - data_space_available -= (RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN); - } - - /* - * The amount we send is the minimum of the available - * space and the amount left to send. - */ - data_len_left = prs_offset(&p->out_data.rdata) - p->out_data.data_sent_length; /* @@ -143,10 +107,18 @@ BOOL create_next_pdu(pipes_struct *p) */ if(!data_len_left) { - DEBUG(0,("create_next_pdu: no data left to send !\n")); + DEBUG(0,("create_next_pdu_ntlmssp: no data left to send !\n")); return False; } + data_space_available = sizeof(p->out_data.current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - + RPC_HDR_AUTH_LEN - NTLMSSP_SIG_SIZE; + + /* + * The amount we send is the minimum of the available + * space and the amount left to send. + */ + data_len = MIN(data_len_left, data_space_available); /* @@ -162,9 +134,9 @@ BOOL create_next_pdu(pipes_struct *p) if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata)) { p->hdr.flags |= RPC_FLG_LAST; - if ((auth_seal || auth_verify || p->netsec_auth_validated) && (data_len_left % 8)) { + if (data_len_left % 8) { ss_padding_len = 8 - (data_len_left % 8); - DEBUG(10,("create_next_pdu: adding sign/seal padding of %u\n", + DEBUG(10,("create_next_pdu_ntlmssp: adding sign/seal padding of %u\n", ss_padding_len )); } } @@ -173,20 +145,11 @@ BOOL create_next_pdu(pipes_struct *p) * Set up the header lengths. */ - if (p->ntlmssp_auth_validated) { - p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + + p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len + ss_padding_len + - RPC_HDR_AUTH_LEN + RPC_AUTH_NTLMSSP_CHK_LEN; - p->hdr.auth_len = RPC_AUTH_NTLMSSP_CHK_LEN; - } else if (p->netsec_auth_validated) { - p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + - data_len + ss_padding_len + - RPC_HDR_AUTH_LEN + RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN; - p->hdr.auth_len = RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN; - } else { - p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len; - p->hdr.auth_len = 0; - } + RPC_HDR_AUTH_LEN + NTLMSSP_SIG_SIZE; + p->hdr.auth_len = NTLMSSP_SIG_SIZE; + /* * Init the parse struct to point at the outgoing @@ -198,127 +161,105 @@ BOOL create_next_pdu(pipes_struct *p) /* Store the header in the data stream. */ if(!smb_io_rpc_hdr("hdr", &p->hdr, &outgoing_pdu, 0)) { - DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR.\n")); + DEBUG(0,("create_next_pdu_ntlmssp: failed to marshall RPC_HDR.\n")); prs_mem_free(&outgoing_pdu); return False; } if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &outgoing_pdu, 0)) { - DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_RESP.\n")); + DEBUG(0,("create_next_pdu_ntlmssp: failed to marshall RPC_HDR_RESP.\n")); prs_mem_free(&outgoing_pdu); return False; } - /* Store the current offset. */ - data_pos = prs_offset(&outgoing_pdu); - /* Copy the data into the PDU. */ if(!prs_append_some_prs_data(&outgoing_pdu, &p->out_data.rdata, p->out_data.data_sent_length, data_len)) { - DEBUG(0,("create_next_pdu: failed to copy %u bytes of data.\n", (unsigned int)data_len)); + DEBUG(0,("create_next_pdu_ntlmssp: failed to copy %u bytes of data.\n", (unsigned int)data_len)); prs_mem_free(&outgoing_pdu); return False; } /* Copy the sign/seal padding data. */ if (ss_padding_len) { - char pad[8]; + unsigned char pad[8]; + memset(pad, '\0', 8); if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding_len)) { - DEBUG(0,("create_next_pdu: failed to add %u bytes of pad data.\n", (unsigned int)ss_padding_len)); + DEBUG(0,("create_next_pdu_ntlmssp: failed to add %u bytes of pad data.\n", + (unsigned int)ss_padding_len)); prs_mem_free(&outgoing_pdu); return False; } } - if (p->ntlmssp_auth_validated) { - /* - * NTLMSSP processing. Mutually exclusive with Schannel. - */ - uint32 crc32 = 0; - char *data; - - DEBUG(5,("create_next_pdu: sign: %s seal: %s data %d auth %d\n", - BOOLSTR(auth_verify), BOOLSTR(auth_seal), data_len + ss_padding_len, p->hdr.auth_len)); - - /* - * Set data to point to where we copied the data into. - */ - data = prs_data_p(&outgoing_pdu) + data_pos; + /* Now write out the auth header and null blob. */ + if (p->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP) { + auth_type = RPC_NTLMSSP_AUTH_TYPE; + } else { + auth_type = RPC_SPNEGO_AUTH_TYPE; + } + if (p->auth.auth_level == PIPE_AUTH_LEVEL_PRIVACY) { + auth_level = RPC_AUTH_LEVEL_PRIVACY; + } else { + auth_level = RPC_AUTH_LEVEL_INTEGRITY; + } - if (auth_seal) { - crc32 = crc32_calc_buffer(data, data_len + ss_padding_len); - NTLMSSPcalc_p(p, (uchar*)data, data_len + ss_padding_len); - } + init_rpc_hdr_auth(&auth_info, auth_type, auth_level, ss_padding_len, 1 /* context id. */); + if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) { + DEBUG(0,("create_next_pdu_ntlmssp: failed to marshall RPC_HDR_AUTH.\n")); + prs_mem_free(&outgoing_pdu); + return False; + } - if (auth_seal || auth_verify) { - RPC_HDR_AUTH auth_info; + /* Generate the sign blob. */ - init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE, - auth_seal ? RPC_PIPE_AUTH_SEAL_LEVEL : RPC_PIPE_AUTH_SIGN_LEVEL, - (auth_verify ? ss_padding_len : 0), (auth_verify ? 1 : 0)); - if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) { - DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n")); + switch (p->auth.auth_level) { + case PIPE_AUTH_LEVEL_PRIVACY: + /* Data portion is encrypted. */ + status = ntlmssp_seal_packet(a->ntlmssp_state, + prs_data_p(&outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN, + data_len + ss_padding_len, + prs_data_p(&outgoing_pdu), + (size_t)prs_offset(&outgoing_pdu), + &auth_blob); + if (!NT_STATUS_IS_OK(status)) { + data_blob_free(&auth_blob); prs_mem_free(&outgoing_pdu); return False; } - } - - if (auth_verify) { - RPC_AUTH_NTLMSSP_CHK ntlmssp_chk; - char *auth_data = prs_data_p(&outgoing_pdu); - - p->ntlmssp_seq_num++; - init_rpc_auth_ntlmssp_chk(&ntlmssp_chk, NTLMSSP_SIGN_VERSION, - crc32, p->ntlmssp_seq_num++); - auth_data = prs_data_p(&outgoing_pdu) + prs_offset(&outgoing_pdu) + 4; - if(!smb_io_rpc_auth_ntlmssp_chk("auth_sign", &ntlmssp_chk, &outgoing_pdu, 0)) { - DEBUG(0,("create_next_pdu: failed to marshall RPC_AUTH_NTLMSSP_CHK.\n")); + break; + case PIPE_AUTH_LEVEL_INTEGRITY: + /* Data is signed. */ + status = ntlmssp_sign_packet(a->ntlmssp_state, + prs_data_p(&outgoing_pdu) + RPC_HEADER_LEN + RPC_HDR_RESP_LEN, + data_len + ss_padding_len, + prs_data_p(&outgoing_pdu), + (size_t)prs_offset(&outgoing_pdu), + &auth_blob); + if (!NT_STATUS_IS_OK(status)) { + data_blob_free(&auth_blob); prs_mem_free(&outgoing_pdu); return False; } - NTLMSSPcalc_p(p, (uchar*)auth_data, RPC_AUTH_NTLMSSP_CHK_LEN - 4); - } - } else if (p->netsec_auth_validated) { - /* - * Schannel processing. Mutually exclusive with NTLMSSP. - */ - int auth_type, auth_level; - char *data; - RPC_HDR_AUTH auth_info; - - RPC_AUTH_NETSEC_CHK verf; - prs_struct rverf; - prs_struct rauth; - - data = prs_data_p(&outgoing_pdu) + data_pos; - /* Check it's the type of reply we were expecting to decode */ - - get_auth_type_level(p->netsec_auth.auth_flags, &auth_type, &auth_level); - init_rpc_hdr_auth(&auth_info, auth_type, auth_level, - ss_padding_len, 1); - - if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) { - DEBUG(0,("create_next_pdu: failed to marshall RPC_HDR_AUTH.\n")); + break; + default: prs_mem_free(&outgoing_pdu); return False; - } - - prs_init(&rverf, 0, p->mem_ctx, MARSHALL); - prs_init(&rauth, 0, p->mem_ctx, MARSHALL); - - netsec_encode(&p->netsec_auth, - p->netsec_auth.auth_flags, - SENDER_IS_ACCEPTOR, - &verf, data, data_len + ss_padding_len); - - smb_io_rpc_auth_netsec_chk("", RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN, - &verf, &outgoing_pdu, 0); + } - p->netsec_auth.seq_num++; + /* Append the auth blob. */ + if (!prs_copy_data_in(&outgoing_pdu, auth_blob.data, NTLMSSP_SIG_SIZE)) { + DEBUG(0,("create_next_pdu_ntlmssp: failed to add %u bytes auth blob.\n", + (unsigned int)NTLMSSP_SIG_SIZE)); + data_blob_free(&auth_blob); + prs_mem_free(&outgoing_pdu); + return False; } + data_blob_free(&auth_blob); + /* * Setup the counts for this PDU. */ @@ -332,292 +273,501 @@ BOOL create_next_pdu(pipes_struct *p) } /******************************************************************* - Process an NTLMSSP authentication response. - If this function succeeds, the user has been authenticated - and their domain, name and calling workstation stored in - the pipe struct. - The initial challenge is stored in p->challenge. - *******************************************************************/ + Generate the next PDU to be returned from the data in p->rdata. + Return an schannel authenticated fragment. + ********************************************************************/ -static BOOL api_pipe_ntlmssp_verify(pipes_struct *p, RPC_AUTH_NTLMSSP_RESP *ntlmssp_resp) +static BOOL create_next_pdu_schannel(pipes_struct *p) { - uchar lm_owf[24]; - uchar nt_owf[128]; - int nt_pw_len; - int lm_pw_len; - fstring user_name; - fstring domain; - fstring wks; + RPC_HDR_RESP hdr_resp; + uint32 ss_padding_len = 0; + uint32 data_len; + uint32 data_space_available; + uint32 data_len_left; + prs_struct outgoing_pdu; + uint32 data_pos; - NTSTATUS nt_status; + /* + * If we're in the fault state, keep returning fault PDU's until + * the pipe gets closed. JRA. + */ - struct auth_context *auth_context = NULL; - auth_usersupplied_info *user_info = NULL; - auth_serversupplied_info *server_info = NULL; + if(p->fault_state) { + setup_fault_pdu(p, NT_STATUS(0x1c010002)); + return True; + } - DEBUG(5,("api_pipe_ntlmssp_verify: checking user details\n")); + memset((char *)&hdr_resp, '\0', sizeof(hdr_resp)); - memset(p->user_name, '\0', sizeof(p->user_name)); - memset(p->pipe_user_name, '\0', sizeof(p->pipe_user_name)); - memset(p->domain, '\0', sizeof(p->domain)); - memset(p->wks, '\0', sizeof(p->wks)); + /* Change the incoming request header to a response. */ + p->hdr.pkt_type = RPC_RESPONSE; - /* Set up for non-authenticated user. */ - delete_nt_token(&p->pipe_user.nt_user_token); - p->pipe_user.ngroups = 0; - SAFE_FREE( p->pipe_user.groups); + /* Set up rpc header flags. */ + if (p->out_data.data_sent_length == 0) { + p->hdr.flags = RPC_FLG_FIRST; + } else { + p->hdr.flags = 0; + } - /* - * Setup an empty password for a guest user. + /* + * Work out how much we can fit in a single PDU. */ + data_len_left = prs_offset(&p->out_data.rdata) - p->out_data.data_sent_length; + /* - * We always negotiate UNICODE. + * Ensure there really is data left to send. */ - if (p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_UNICODE) { - rpcstr_pull(user_name, ntlmssp_resp->user, sizeof(fstring), ntlmssp_resp->hdr_usr.str_str_len*2, 0 ); - rpcstr_pull(domain, ntlmssp_resp->domain, sizeof(fstring), ntlmssp_resp->hdr_domain.str_str_len*2, 0); - rpcstr_pull(wks, ntlmssp_resp->wks, sizeof(fstring), ntlmssp_resp->hdr_wks.str_str_len*2, 0); - } else { - pull_ascii_fstring(user_name, ntlmssp_resp->user); - pull_ascii_fstring(domain, ntlmssp_resp->domain); - pull_ascii_fstring(wks, ntlmssp_resp->wks); + if(!data_len_left) { + DEBUG(0,("create_next_pdu_schannel: no data left to send !\n")); + return False; } - DEBUG(5,("user: %s domain: %s wks: %s\n", user_name, domain, wks)); + data_space_available = sizeof(p->out_data.current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN - + RPC_HDR_AUTH_LEN - RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN; - nt_pw_len = MIN(sizeof(nt_owf), ntlmssp_resp->hdr_nt_resp.str_str_len); - lm_pw_len = MIN(sizeof(lm_owf), ntlmssp_resp->hdr_lm_resp.str_str_len); - - memcpy(lm_owf, ntlmssp_resp->lm_resp, sizeof(lm_owf)); - memcpy(nt_owf, ntlmssp_resp->nt_resp, nt_pw_len); + /* + * The amount we send is the minimum of the available + * space and the amount left to send. + */ -#ifdef DEBUG_PASSWORD - DEBUG(100,("lm, nt owfs, chal\n")); - dump_data(100, (char *)lm_owf, sizeof(lm_owf)); - dump_data(100, (char *)nt_owf, nt_pw_len); - dump_data(100, (char *)p->challenge, 8); -#endif + data_len = MIN(data_len_left, data_space_available); /* - * Allow guest access. Patch from Shirish Kalele . + * Set up the alloc hint. This should be the data left to + * send. */ - if (*user_name) { - - /* - * Do the length checking only if user is not NULL. - */ + hdr_resp.alloc_hint = data_len_left; - if (ntlmssp_resp->hdr_lm_resp.str_str_len == 0) - return False; - if (ntlmssp_resp->hdr_nt_resp.str_str_len == 0) - return False; - if (ntlmssp_resp->hdr_usr.str_str_len == 0) - return False; - if (ntlmssp_resp->hdr_domain.str_str_len == 0) - return False; - if (ntlmssp_resp->hdr_wks.str_str_len == 0) - return False; + /* + * Work out if this PDU will be the last. + */ + if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata)) { + p->hdr.flags |= RPC_FLG_LAST; + if (data_len_left % 8) { + ss_padding_len = 8 - (data_len_left % 8); + DEBUG(10,("create_next_pdu_schannel: adding sign/seal padding of %u\n", + ss_padding_len )); + } } - - make_auth_context_fixed(&auth_context, (uchar*)p->challenge); - if (!make_user_info_netlogon_network(&user_info, - user_name, domain, wks, - lm_owf, lm_pw_len, - nt_owf, nt_pw_len)) { - DEBUG(0,("make_user_info_netlogon_network failed! Failing authenticaion.\n")); - return False; - } - - nt_status = auth_context->check_ntlm_password(auth_context, user_info, &server_info); - - (auth_context->free)(&auth_context); - free_user_info(&user_info); - - p->ntlmssp_auth_validated = NT_STATUS_IS_OK(nt_status); - - if (!p->ntlmssp_auth_validated) { - DEBUG(1,("api_pipe_ntlmssp_verify: User [%s]\\[%s] from machine %s \ -failed authentication on named pipe %s.\n", domain, user_name, wks, p->name )); - free_server_info(&server_info); - return False; - } + p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len + ss_padding_len + + RPC_HDR_AUTH_LEN + RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN; + p->hdr.auth_len = RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN; /* - * Set up the sign/seal data. + * Init the parse struct to point at the outgoing + * data. */ - if (server_info->lm_session_key.length != 16) { - DEBUG(1,("api_pipe_ntlmssp_verify: User [%s]\\[%s] from machine %s \ -succeeded authentication on named pipe %s, but session key was of incorrect length [%u].\n", - domain, user_name, wks, p->name, server_info->lm_session_key.length)); - free_server_info(&server_info); - return False; - } else { - uchar p24[24]; - NTLMSSPOWFencrypt(server_info->lm_session_key.data, lm_owf, p24); - { - unsigned char j = 0; - int ind; - - unsigned char k2[8]; + prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL); + prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False); - memcpy(k2, p24, 5); - k2[5] = 0xe5; - k2[6] = 0x38; - k2[7] = 0xb0; + /* Store the header in the data stream. */ + if(!smb_io_rpc_hdr("hdr", &p->hdr, &outgoing_pdu, 0)) { + DEBUG(0,("create_next_pdu_schannel: failed to marshall RPC_HDR.\n")); + prs_mem_free(&outgoing_pdu); + return False; + } - for (ind = 0; ind < 256; ind++) - p->ntlmssp_hash[ind] = (unsigned char)ind; + if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &outgoing_pdu, 0)) { + DEBUG(0,("create_next_pdu_schannel: failed to marshall RPC_HDR_RESP.\n")); + prs_mem_free(&outgoing_pdu); + return False; + } - for( ind = 0; ind < 256; ind++) { - unsigned char tc; + /* Store the current offset. */ + data_pos = prs_offset(&outgoing_pdu); - j += (p->ntlmssp_hash[ind] + k2[ind%8]); + /* Copy the data into the PDU. */ - tc = p->ntlmssp_hash[ind]; - p->ntlmssp_hash[ind] = p->ntlmssp_hash[j]; - p->ntlmssp_hash[j] = tc; - } + if(!prs_append_some_prs_data(&outgoing_pdu, &p->out_data.rdata, p->out_data.data_sent_length, data_len)) { + DEBUG(0,("create_next_pdu_schannel: failed to copy %u bytes of data.\n", (unsigned int)data_len)); + prs_mem_free(&outgoing_pdu); + return False; + } - p->ntlmssp_hash[256] = 0; - p->ntlmssp_hash[257] = 0; + /* Copy the sign/seal padding data. */ + if (ss_padding_len) { + char pad[8]; + memset(pad, '\0', 8); + if (!prs_copy_data_in(&outgoing_pdu, pad, ss_padding_len)) { + DEBUG(0,("create_next_pdu_schannel: failed to add %u bytes of pad data.\n", (unsigned int)ss_padding_len)); + prs_mem_free(&outgoing_pdu); + return False; } + } - dump_data_pw("NTLMSSP hash (v1)\n", p->ntlmssp_hash, - sizeof(p->ntlmssp_hash)); - -/* NTLMSSPhash(p->ntlmssp_hash, p24); */ - p->ntlmssp_seq_num = 0; + { + /* + * Schannel processing. + */ + char *data; + RPC_HDR_AUTH auth_info; + RPC_AUTH_SCHANNEL_CHK verf; - } + data = prs_data_p(&outgoing_pdu) + data_pos; + /* Check it's the type of reply we were expecting to decode */ - fstrcpy(p->user_name, user_name); - fstrcpy(p->pipe_user_name, server_info->unix_name); - fstrcpy(p->domain, domain); - fstrcpy(p->wks, wks); + init_rpc_hdr_auth(&auth_info, + RPC_SCHANNEL_AUTH_TYPE, + p->auth.auth_level == PIPE_AUTH_LEVEL_PRIVACY ? + RPC_AUTH_LEVEL_PRIVACY : RPC_AUTH_LEVEL_INTEGRITY, + ss_padding_len, 1); - /* - * Store the UNIX credential data (uid/gid pair) in the pipe structure. - */ + if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, &outgoing_pdu, 0)) { + DEBUG(0,("create_next_pdu_schannel: failed to marshall RPC_HDR_AUTH.\n")); + prs_mem_free(&outgoing_pdu); + return False; + } - if (p->session_key.data) { - data_blob_free(&p->session_key); - } - p->session_key = data_blob(server_info->lm_session_key.data, server_info->lm_session_key.length); + schannel_encode(p->auth.a_u.schannel_auth, + p->auth.auth_level, + SENDER_IS_ACCEPTOR, + &verf, data, data_len + ss_padding_len); - p->pipe_user.uid = server_info->uid; - p->pipe_user.gid = server_info->gid; - - p->pipe_user.ngroups = server_info->n_groups; - if (p->pipe_user.ngroups) { - if (!(p->pipe_user.groups = memdup(server_info->groups, sizeof(gid_t) * p->pipe_user.ngroups))) { - DEBUG(0,("failed to memdup group list to p->pipe_user.groups\n")); - free_server_info(&server_info); + if (!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN, + &verf, &outgoing_pdu, 0)) { + prs_mem_free(&outgoing_pdu); return False; } - } - if (server_info->ptok) - p->pipe_user.nt_user_token = dup_nt_token(server_info->ptok); - else { - DEBUG(1,("Error: Authmodule failed to provide nt_user_token\n")); - p->pipe_user.nt_user_token = NULL; - free_server_info(&server_info); - return False; + p->auth.a_u.schannel_auth->seq_num++; } - p->ntlmssp_auth_validated = True; + /* + * Setup the counts for this PDU. + */ + + p->out_data.data_sent_length += data_len; + p->out_data.current_pdu_len = p->hdr.frag_len; + p->out_data.current_pdu_sent = 0; - free_server_info(&server_info); + prs_mem_free(&outgoing_pdu); return True; } /******************************************************************* - The switch table for the pipe names and the functions to handle them. - *******************************************************************/ + Generate the next PDU to be returned from the data in p->rdata. + No authentication done. +********************************************************************/ -struct rpc_table +static BOOL create_next_pdu_noauth(pipes_struct *p) { - struct - { - const char *clnt; - const char *srv; - } pipe; - struct api_struct *cmds; - int n_cmds; -}; + RPC_HDR_RESP hdr_resp; + uint32 data_len; + uint32 data_space_available; + uint32 data_len_left; + prs_struct outgoing_pdu; -static struct rpc_table *rpc_lookup; -static int rpc_lookup_size; + /* + * If we're in the fault state, keep returning fault PDU's until + * the pipe gets closed. JRA. + */ -/******************************************************************* - This is the client reply to our challenge for an authenticated - bind request. The challenge we sent is in p->challenge. -*******************************************************************/ + if(p->fault_state) { + setup_fault_pdu(p, NT_STATUS(0x1c010002)); + return True; + } -BOOL api_pipe_bind_auth_resp(pipes_struct *p, prs_struct *rpc_in_p) -{ - RPC_HDR_AUTHA autha_info; - RPC_AUTH_VERIFIER auth_verifier; - RPC_AUTH_NTLMSSP_RESP ntlmssp_resp; + memset((char *)&hdr_resp, '\0', sizeof(hdr_resp)); - DEBUG(5,("api_pipe_bind_auth_resp: decode request. %d\n", __LINE__)); + /* Change the incoming request header to a response. */ + p->hdr.pkt_type = RPC_RESPONSE; - if (p->hdr.auth_len == 0) { - DEBUG(0,("api_pipe_bind_auth_resp: No auth field sent !\n")); - return False; + /* Set up rpc header flags. */ + if (p->out_data.data_sent_length == 0) { + p->hdr.flags = RPC_FLG_FIRST; + } else { + p->hdr.flags = 0; } /* - * Decode the authentication verifier response. + * Work out how much we can fit in a single PDU. + */ + + data_len_left = prs_offset(&p->out_data.rdata) - p->out_data.data_sent_length; + + /* + * Ensure there really is data left to send. + */ + + if(!data_len_left) { + DEBUG(0,("create_next_pdu_noath: no data left to send !\n")); + return False; + } + + data_space_available = sizeof(p->out_data.current_pdu) - RPC_HEADER_LEN - RPC_HDR_RESP_LEN; + + /* + * The amount we send is the minimum of the available + * space and the amount left to send. + */ + + data_len = MIN(data_len_left, data_space_available); + + /* + * Set up the alloc hint. This should be the data left to + * send. + */ + + hdr_resp.alloc_hint = data_len_left; + + /* + * Work out if this PDU will be the last. */ - if(!smb_io_rpc_hdr_autha("", &autha_info, rpc_in_p, 0)) { - DEBUG(0,("api_pipe_bind_auth_resp: unmarshall of RPC_HDR_AUTHA failed.\n")); + if(p->out_data.data_sent_length + data_len >= prs_offset(&p->out_data.rdata)) { + p->hdr.flags |= RPC_FLG_LAST; + } + + /* + * Set up the header lengths. + */ + + p->hdr.frag_len = RPC_HEADER_LEN + RPC_HDR_RESP_LEN + data_len; + p->hdr.auth_len = 0; + + /* + * Init the parse struct to point at the outgoing + * data. + */ + + prs_init( &outgoing_pdu, 0, p->mem_ctx, MARSHALL); + prs_give_memory( &outgoing_pdu, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False); + + /* Store the header in the data stream. */ + if(!smb_io_rpc_hdr("hdr", &p->hdr, &outgoing_pdu, 0)) { + DEBUG(0,("create_next_pdu_noath: failed to marshall RPC_HDR.\n")); + prs_mem_free(&outgoing_pdu); return False; } - if (autha_info.auth.auth_type != NTLMSSP_AUTH_TYPE || autha_info.auth.auth_level != RPC_PIPE_AUTH_SEAL_LEVEL) { - DEBUG(0,("api_pipe_bind_auth_resp: incorrect auth type (%d) or level (%d).\n", - (int)autha_info.auth.auth_type, (int)autha_info.auth.auth_level )); + if(!smb_io_rpc_hdr_resp("resp", &hdr_resp, &outgoing_pdu, 0)) { + DEBUG(0,("create_next_pdu_noath: failed to marshall RPC_HDR_RESP.\n")); + prs_mem_free(&outgoing_pdu); return False; } - if(!smb_io_rpc_auth_verifier("", &auth_verifier, rpc_in_p, 0)) { - DEBUG(0,("api_pipe_bind_auth_resp: unmarshall of RPC_AUTH_VERIFIER failed.\n")); + /* Copy the data into the PDU. */ + + if(!prs_append_some_prs_data(&outgoing_pdu, &p->out_data.rdata, p->out_data.data_sent_length, data_len)) { + DEBUG(0,("create_next_pdu_noauth: failed to copy %u bytes of data.\n", (unsigned int)data_len)); + prs_mem_free(&outgoing_pdu); return False; } /* - * Ensure this is a NTLMSSP_AUTH packet type. + * Setup the counts for this PDU. */ - if (!rpc_auth_verifier_chk(&auth_verifier, "NTLMSSP", NTLMSSP_AUTH)) { - DEBUG(0,("api_pipe_bind_auth_resp: rpc_auth_verifier_chk failed.\n")); + p->out_data.data_sent_length += data_len; + p->out_data.current_pdu_len = p->hdr.frag_len; + p->out_data.current_pdu_sent = 0; + + prs_mem_free(&outgoing_pdu); + return True; +} + +/******************************************************************* + Generate the next PDU to be returned from the data in p->rdata. +********************************************************************/ + +BOOL create_next_pdu(pipes_struct *p) +{ + switch(p->auth.auth_level) { + case PIPE_AUTH_LEVEL_NONE: + case PIPE_AUTH_LEVEL_CONNECT: + /* This is incorrect for auth level connect. Fixme. JRA */ + return create_next_pdu_noauth(p); + + default: + switch(p->auth.auth_type) { + case PIPE_AUTH_TYPE_NTLMSSP: + case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: + return create_next_pdu_ntlmssp(p); + case PIPE_AUTH_TYPE_SCHANNEL: + return create_next_pdu_schannel(p); + default: + break; + } + } + + DEBUG(0,("create_next_pdu: invalid internal auth level %u / type %u", + (unsigned int)p->auth.auth_level, + (unsigned int)p->auth.auth_type)); + return False; +} + +/******************************************************************* + Process an NTLMSSP authentication response. + If this function succeeds, the user has been authenticated + and their domain, name and calling workstation stored in + the pipe struct. +*******************************************************************/ + +static BOOL pipe_ntlmssp_verify_final(pipes_struct *p, DATA_BLOB *p_resp_blob) +{ + DATA_BLOB reply; + NTSTATUS status; + AUTH_NTLMSSP_STATE *a = p->auth.a_u.auth_ntlmssp_state; + + DEBUG(5,("pipe_ntlmssp_verify_final: checking user details\n")); + + ZERO_STRUCT(reply); + + memset(p->user_name, '\0', sizeof(p->user_name)); + memset(p->pipe_user_name, '\0', sizeof(p->pipe_user_name)); + memset(p->domain, '\0', sizeof(p->domain)); + memset(p->wks, '\0', sizeof(p->wks)); + + /* Set up for non-authenticated user. */ + delete_nt_token(&p->pipe_user.nt_user_token); + p->pipe_user.ngroups = 0; + SAFE_FREE( p->pipe_user.groups); + + status = auth_ntlmssp_update(a, *p_resp_blob, &reply); + + /* Don't generate a reply. */ + data_blob_free(&reply); + + if (!NT_STATUS_IS_OK(status)) { return False; } - if(!smb_io_rpc_auth_ntlmssp_resp("", &ntlmssp_resp, rpc_in_p, 0)) { - DEBUG(0,("api_pipe_bind_auth_resp: Failed to unmarshall RPC_AUTH_NTLMSSP_RESP.\n")); + fstrcpy(p->user_name, a->ntlmssp_state->user); + fstrcpy(p->pipe_user_name, a->server_info->unix_name); + fstrcpy(p->domain, a->ntlmssp_state->domain); + fstrcpy(p->wks, a->ntlmssp_state->workstation); + + DEBUG(5,("pipe_ntlmssp_verify_final: OK: user: %s domain: %s workstation: %s\n", + p->user_name, p->domain, p->wks)); + + /* + * Store the UNIX credential data (uid/gid pair) in the pipe structure. + */ + + p->pipe_user.uid = a->server_info->uid; + p->pipe_user.gid = a->server_info->gid; + + /* + * Copy the session key from the ntlmssp state. + */ + + data_blob_free(&p->session_key); + p->session_key = data_blob(a->ntlmssp_state->session_key.data, a->ntlmssp_state->session_key.length); + if (!p->session_key.data) { return False; } + p->pipe_user.ngroups = a->server_info->n_groups; + if (p->pipe_user.ngroups) { + if (!(p->pipe_user.groups = memdup(a->server_info->groups, sizeof(gid_t) * p->pipe_user.ngroups))) { + DEBUG(0,("failed to memdup group list to p->pipe_user.groups\n")); + return False; + } + } + + if (a->server_info->ptok) { + p->pipe_user.nt_user_token = dup_nt_token(a->server_info->ptok); + } else { + DEBUG(1,("Error: Authmodule failed to provide nt_user_token\n")); + p->pipe_user.nt_user_token = NULL; + return False; + } + + return True; +} + +/******************************************************************* + The switch table for the pipe names and the functions to handle them. +*******************************************************************/ + +struct rpc_table { + struct { + const char *clnt; + const char *srv; + } pipe; + struct api_struct *cmds; + int n_cmds; +}; + +static struct rpc_table *rpc_lookup; +static int rpc_lookup_size; + +/******************************************************************* + This is the "stage3" NTLMSSP response after a bind request and reply. +*******************************************************************/ + +BOOL api_pipe_bind_auth3(pipes_struct *p, prs_struct *rpc_in_p) +{ + RPC_HDR_AUTH auth_info; + uint32 pad; + DATA_BLOB blob; + + ZERO_STRUCT(blob); + + DEBUG(5,("api_pipe_bind_auth3: decode request. %d\n", __LINE__)); + + if (p->hdr.auth_len == 0) { + DEBUG(0,("api_pipe_bind_auth3: No auth field sent !\n")); + goto err; + } + + /* 4 bytes padding. */ + if (!prs_uint32("pad", rpc_in_p, 0, &pad)) { + DEBUG(0,("api_pipe_bind_auth3: unmarshall of 4 byte pad failed.\n")); + goto err; + } + + /* + * Decode the authentication verifier response. + */ + + if(!smb_io_rpc_hdr_auth("", &auth_info, rpc_in_p, 0)) { + DEBUG(0,("api_pipe_bind_auth3: unmarshall of RPC_HDR_AUTH failed.\n")); + goto err; + } + + if (auth_info.auth_type != RPC_NTLMSSP_AUTH_TYPE) { + DEBUG(0,("api_pipe_bind_auth3: incorrect auth type (%u).\n", + (unsigned int)auth_info.auth_type )); + return False; + } + + blob = data_blob(NULL,p->hdr.auth_len); + + if (!prs_copy_data_out(blob.data, rpc_in_p, p->hdr.auth_len)) { + DEBUG(0,("api_pipe_bind_auth3: Failed to pull %u bytes - the response blob.\n", + (unsigned int)p->hdr.auth_len )); + goto err; + } + /* * The following call actually checks the challenge/response data. * for correctness against the given DOMAIN\user name. */ - if (!api_pipe_ntlmssp_verify(p, &ntlmssp_resp)) - return False; + if (!pipe_ntlmssp_verify_final(p, &blob)) { + goto err; + } + + data_blob_free(&blob); + + p->pipe_bound = True; - p->pipe_bound = True -; return True; + + err: + + data_blob_free(&blob); + free_pipe_ntlmssp_auth_data(&p->auth); + p->auth.a_u.auth_ntlmssp_state = NULL; + + return False; } /******************************************************************* @@ -642,13 +792,12 @@ static BOOL setup_bind_nak(pipes_struct *p) prs_init( &outgoing_rpc, 0, p->mem_ctx, MARSHALL); prs_give_memory( &outgoing_rpc, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False); - /* * Initialize a bind_nak header. */ init_rpc_hdr(&nak_hdr, RPC_BINDNACK, RPC_FLG_FIRST | RPC_FLG_LAST, - p->hdr.call_id, RPC_HEADER_LEN + sizeof(uint16), 0); + p->hdr.call_id, RPC_HEADER_LEN + sizeof(uint16), 0); /* * Marshall the header into the outgoing PDU. @@ -673,6 +822,11 @@ static BOOL setup_bind_nak(pipes_struct *p) p->out_data.current_pdu_len = prs_offset(&outgoing_rpc); p->out_data.current_pdu_sent = 0; + if (p->auth.auth_data_free_func) { + (*p->auth.auth_data_free_func)(&p->auth); + } + p->auth.auth_level = PIPE_AUTH_LEVEL_NONE; + p->auth.auth_type = PIPE_AUTH_TYPE_NONE; p->pipe_bound = False; return True; @@ -766,15 +920,13 @@ BOOL check_bind_req(struct pipes_struct *p, RPC_IFACE* abstract, /* we have to check all now since win2k introduced a new UUID on the lsaprpc pipe */ - for ( i=0; pipe_names[i].client_pipe; i++ ) - { + for ( i=0; pipe_names[i].client_pipe; i++ ) { DEBUG(10,("checking %s\n", pipe_names[i].client_pipe)); if ( strequal(pipe_names[i].client_pipe, pname) && (abstract->version == pipe_names[i].abstr_syntax.version) && (memcmp(&abstract->uuid, &pipe_names[i].abstr_syntax.uuid, sizeof(struct uuid)) == 0) && (transfer->version == pipe_names[i].trans_syntax.version) - && (memcmp(&transfer->uuid, &pipe_names[i].trans_syntax.uuid, sizeof(struct uuid)) == 0) ) - { + && (memcmp(&transfer->uuid, &pipe_names[i].trans_syntax.uuid, sizeof(struct uuid)) == 0) ) { struct api_struct *fns = NULL; int n_fns = 0; PIPE_RPC_FNS *context_fns; @@ -800,8 +952,9 @@ BOOL check_bind_req(struct pipes_struct *p, RPC_IFACE* abstract, } } - if(pipe_names[i].client_pipe == NULL) + if(pipe_names[i].client_pipe == NULL) { return False; + } return True; } @@ -809,6 +962,7 @@ BOOL check_bind_req(struct pipes_struct *p, RPC_IFACE* abstract, /******************************************************************* Register commands to an RPC pipe *******************************************************************/ + NTSTATUS rpc_pipe_register_commands(int version, const char *clnt, const char *srv, const struct api_struct *cmds, int size) { struct rpc_table *rpc_entry; @@ -856,6 +1010,365 @@ NTSTATUS rpc_pipe_register_commands(int version, const char *clnt, const char *s return NT_STATUS_OK; } +/******************************************************************* + Handle a SPNEGO krb5 bind auth. +*******************************************************************/ + +static BOOL pipe_spnego_auth_bind_kerberos(pipes_struct *p, prs_struct *rpc_in_p, RPC_HDR_AUTH *pauth_info, + DATA_BLOB *psecblob, prs_struct *pout_auth) +{ + return False; +} + +/******************************************************************* + Handle the first part of a SPNEGO bind auth. +*******************************************************************/ + +static BOOL pipe_spnego_auth_bind_negotiate(pipes_struct *p, prs_struct *rpc_in_p, + RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth) +{ + DATA_BLOB blob; + DATA_BLOB secblob; + DATA_BLOB response; + DATA_BLOB chal; + char *OIDs[ASN1_MAX_OIDS]; + int i; + NTSTATUS status; + BOOL got_kerberos_mechanism = False; + AUTH_NTLMSSP_STATE *a = NULL; + RPC_HDR_AUTH auth_info; + + ZERO_STRUCT(secblob); + ZERO_STRUCT(chal); + ZERO_STRUCT(response); + + /* Grab the SPNEGO blob. */ + blob = data_blob(NULL,p->hdr.auth_len); + + if (!prs_copy_data_out(blob.data, rpc_in_p, p->hdr.auth_len)) { + DEBUG(0,("pipe_spnego_auth_bind_negotiate: Failed to pull %u bytes - the SPNEGO auth header.\n", + (unsigned int)p->hdr.auth_len )); + goto err; + } + + if (blob.data[0] != ASN1_APPLICATION(0)) { + goto err; + } + + /* parse out the OIDs and the first sec blob */ + if (!parse_negTokenTarg(blob, OIDs, &secblob)) { + DEBUG(0,("pipe_spnego_auth_bind_negotiate: Failed to parse the security blob.\n")); + goto err; + } + + if (strcmp(OID_KERBEROS5, OIDs[0]) == 0 || strcmp(OID_KERBEROS5_OLD, OIDs[0]) == 0) { + got_kerberos_mechanism = True; + } + + for (i=0;OIDs[i];i++) { + DEBUG(3,("pipe_spnego_auth_bind_negotiate: Got OID %s\n", OIDs[i])); + SAFE_FREE(OIDs[i]); + } + DEBUG(3,("pipe_spnego_auth_bind_negotiate: Got secblob of size %lu\n", (unsigned long)secblob.length)); + + if ( got_kerberos_mechanism && ((lp_security()==SEC_ADS) || lp_use_kerberos_keytab()) ) { + BOOL ret = pipe_spnego_auth_bind_kerberos(p, rpc_in_p, pauth_info, &secblob, pout_auth); + data_blob_free(&secblob); + data_blob_free(&blob); + return ret; + } + + if (p->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP && p->auth.a_u.auth_ntlmssp_state) { + /* Free any previous auth type. */ + free_pipe_ntlmssp_auth_data(&p->auth); + } + + /* Initialize the NTLM engine. */ + status = auth_ntlmssp_start(&a); + if (!NT_STATUS_IS_OK(status)) { + goto err; + } + + /* + * Pass the first security blob of data to it. + * This can return an error or NT_STATUS_MORE_PROCESSING_REQUIRED + * which means we need another packet to complete the bind. + */ + + status = auth_ntlmssp_update(a, secblob, &chal); + + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + DEBUG(3,("pipe_spnego_auth_bind_negotiate: auth_ntlmssp_update failed.\n")); + goto err; + } + + /* Generate the response blob we need for step 2 of the bind. */ + response = spnego_gen_auth_response(&chal, status, OID_NTLMSSP); + + /* Copy the blob into the pout_auth parse struct */ + init_rpc_hdr_auth(&auth_info, RPC_SPNEGO_AUTH_TYPE, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1); + if(!smb_io_rpc_hdr_auth("", &auth_info, pout_auth, 0)) { + DEBUG(0,("pipe_spnego_auth_bind_negotiate: marshalling of RPC_HDR_AUTH failed.\n")); + goto err; + } + + if (!prs_copy_data_in(pout_auth, response.data, response.length)) { + DEBUG(0,("pipe_spnego_auth_bind_negotiate: marshalling of data blob failed.\n")); + goto err; + } + + p->auth.a_u.auth_ntlmssp_state = a; + p->auth.auth_data_free_func = &free_pipe_ntlmssp_auth_data; + p->auth.auth_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP; + + data_blob_free(&blob); + data_blob_free(&secblob); + data_blob_free(&chal); + data_blob_free(&response); + + /* We can't set pipe_bound True yet - we need an RPC_ALTER_CONTEXT response packet... */ + return True; + + err: + + data_blob_free(&blob); + data_blob_free(&secblob); + data_blob_free(&chal); + data_blob_free(&response); + + p->auth.a_u.auth_ntlmssp_state = NULL; + + return False; +} + +/******************************************************************* + Handle the second part of a SPNEGO bind auth. +*******************************************************************/ + +static BOOL pipe_spnego_auth_bind_continue(pipes_struct *p, prs_struct *rpc_in_p, + RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth) +{ + DATA_BLOB spnego_blob, auth_blob, auth_reply; + AUTH_NTLMSSP_STATE *a = p->auth.a_u.auth_ntlmssp_state; + + ZERO_STRUCT(spnego_blob); + ZERO_STRUCT(auth_blob); + ZERO_STRUCT(auth_reply); + + if (p->auth.auth_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP || !a) { + DEBUG(0,("pipe_spnego_auth_bind_continue: not in NTLMSSP auth state.\n")); + goto err; + } + + /* Grab the SPNEGO blob. */ + spnego_blob = data_blob(NULL,p->hdr.auth_len); + + if (!prs_copy_data_out(spnego_blob.data, rpc_in_p, p->hdr.auth_len)) { + DEBUG(0,("pipe_spnego_auth_bind_continue: Failed to pull %u bytes - the SPNEGO auth header.\n", + (unsigned int)p->hdr.auth_len )); + goto err; + } + + if (spnego_blob.data[0] != ASN1_CONTEXT(1)) { + DEBUG(0,("pipe_spnego_auth_bind_continue: invalid SPNEGO blob type.\n")); + goto err; + } + + if (!spnego_parse_auth(spnego_blob, &auth_blob)) { + DEBUG(0,("pipe_spnego_auth_bind_continue: invalid SPNEGO blob.\n")); + goto err; + } + + /* + * The following call actually checks the challenge/response data. + * for correctness against the given DOMAIN\user name. + */ + + if (!pipe_ntlmssp_verify_final(p, &auth_blob)) { + goto err; + } + + data_blob_free(&spnego_blob); + data_blob_free(&auth_blob); + data_blob_free(&auth_reply); + + p->pipe_bound = True; + + return True; + + err: + + data_blob_free(&spnego_blob); + data_blob_free(&auth_blob); + data_blob_free(&auth_reply); + + free_pipe_ntlmssp_auth_data(&p->auth); + p->auth.a_u.auth_ntlmssp_state = NULL; + + return False; +} + +/******************************************************************* + Handle an schannel bind auth. +*******************************************************************/ + +static BOOL pipe_schannel_auth_bind(pipes_struct *p, prs_struct *rpc_in_p, + RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth) +{ + RPC_HDR_AUTH auth_info; + RPC_AUTH_SCHANNEL_NEG neg; + RPC_AUTH_VERIFIER auth_verifier; + uint32 flags; + + if (!server_auth2_negotiated) { + DEBUG(0, ("pipe_schannel_auth_bind: Attempt to bind using schannel without successful serverauth2\n")); + return False; + } + + if (!smb_io_rpc_auth_schannel_neg("", &neg, rpc_in_p, 0)) { + DEBUG(0,("pipe_schannel_auth_bind: Could not unmarshal SCHANNEL auth neg\n")); + return False; + } + + p->auth.a_u.schannel_auth = TALLOC_P(p->pipe_state_mem_ctx, struct schannel_auth_struct); + if (!p->auth.a_u.schannel_auth) { + return False; + } + + memset(p->auth.a_u.schannel_auth->sess_key, 0, sizeof(p->auth.a_u.schannel_auth->sess_key)); + memcpy(p->auth.a_u.schannel_auth->sess_key, last_dcinfo.sess_key, sizeof(last_dcinfo.sess_key)); + + p->auth.a_u.schannel_auth->seq_num = 0; + + /* + * JRA. Should we also copy the schannel session key into the pipe session key p->session_key + * here ? We do that for NTLMSPP, but the session key is already set up from the vuser + * struct of the person who opened the pipe. I need to test this further. JRA. + */ + + /* The client opens a second RPC NETLOGON pipe without + doing a auth2. The credentials for the schannel are + re-used from the auth2 the client did before. */ + p->dc = TALLOC_ZERO_P(p->pipe_state_mem_ctx, struct dcinfo); + if (!p->dc) { + return False; + } + *p->dc = last_dcinfo; + + init_rpc_hdr_auth(&auth_info, RPC_SCHANNEL_AUTH_TYPE, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1); + if(!smb_io_rpc_hdr_auth("", &auth_info, pout_auth, 0)) { + DEBUG(0,("pipe_schannel_auth_bind: marshalling of RPC_HDR_AUTH failed.\n")); + return False; + } + + /*** SCHANNEL verifier ***/ + + init_rpc_auth_verifier(&auth_verifier, "\001", 0x0); + if(!smb_io_rpc_schannel_verifier("", &auth_verifier, pout_auth, 0)) { + DEBUG(0,("pipe_schannel_auth_bind: marshalling of RPC_AUTH_VERIFIER failed.\n")); + return False; + } + + prs_align(pout_auth); + + flags = 5; + if(!prs_uint32("flags ", pout_auth, 0, &flags)) { + return False; + } + + DEBUG(10,("pipe_schannel_auth_bind: schannel auth: domain [%s] myname [%s]\n", + neg.domain, neg.myname)); + + /* We're finished with this bind - no more packets. */ + p->auth.auth_data_free_func = NULL; + p->auth.auth_type = PIPE_AUTH_TYPE_SCHANNEL; + + p->pipe_bound = True; + + return True; +} + +/******************************************************************* + Handle an NTLMSSP bind auth. +*******************************************************************/ + +static BOOL pipe_ntlmssp_auth_bind(pipes_struct *p, prs_struct *rpc_in_p, + RPC_HDR_AUTH *pauth_info, prs_struct *pout_auth) +{ + RPC_HDR_AUTH auth_info; + DATA_BLOB blob; + DATA_BLOB response; + NTSTATUS status; + AUTH_NTLMSSP_STATE *a = NULL; + + ZERO_STRUCT(blob); + ZERO_STRUCT(response); + + /* Grab the NTLMSSP blob. */ + blob = data_blob(NULL,p->hdr.auth_len); + + if (!prs_copy_data_out(blob.data, rpc_in_p, p->hdr.auth_len)) { + DEBUG(0,("pipe_ntlmssp_auth_bind: Failed to pull %u bytes - the NTLM auth header.\n", + (unsigned int)p->hdr.auth_len )); + goto err; + } + + if (strncmp(blob.data, "NTLMSSP", 7) != 0) { + DEBUG(0,("pipe_ntlmssp_auth_bind: Failed to read NTLMSSP in blob\n")); + goto err; + } + + /* We have an NTLMSSP blob. */ + status = auth_ntlmssp_start(&a); + if (!NT_STATUS_IS_OK(status)) { + DEBUG(0,("pipe_ntlmssp_auth_bind: auth_ntlmssp_start failed: %s\n", + nt_errstr(status) )); + goto err; + } + + status = auth_ntlmssp_update(a, blob, &response); + if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + DEBUG(0,("pipe_ntlmssp_auth_bind: auth_ntlmssp_update failed: %s\n", + nt_errstr(status) )); + goto err; + } + + data_blob_free(&blob); + + /* Copy the blob into the pout_auth parse struct */ + init_rpc_hdr_auth(&auth_info, RPC_NTLMSSP_AUTH_TYPE, pauth_info->auth_level, RPC_HDR_AUTH_LEN, 1); + if(!smb_io_rpc_hdr_auth("", &auth_info, pout_auth, 0)) { + DEBUG(0,("pipe_ntlmssp_auth_bind: marshalling of RPC_HDR_AUTH failed.\n")); + goto err; + } + + if (!prs_copy_data_in(pout_auth, response.data, response.length)) { + DEBUG(0,("pipe_ntlmssp_auth_bind: marshalling of data blob failed.\n")); + goto err; + } + + p->auth.a_u.auth_ntlmssp_state = a; + p->auth.auth_data_free_func = &free_pipe_ntlmssp_auth_data; + p->auth.auth_type = PIPE_AUTH_TYPE_NTLMSSP; + + data_blob_free(&blob); + data_blob_free(&response); + + DEBUG(10,("pipe_ntlmssp_auth_bind: NTLMSSP auth started\n")); + + /* We can't set pipe_bound True yet - we need an RPC_AUTH3 response packet... */ + return True; + + err: + + data_blob_free(&blob); + data_blob_free(&response); + + free_pipe_ntlmssp_auth_data(&p->auth); + p->auth.a_u.auth_ntlmssp_state = NULL; + return False; +} + /******************************************************************* Respond to a pipe bind request. *******************************************************************/ @@ -872,162 +1385,280 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) prs_struct outgoing_rpc; int i = 0; int auth_len = 0; - enum RPC_PKT_TYPE reply_pkt_type; + unsigned int auth_type = RPC_ANONYMOUS_AUTH_TYPE; + + /* No rebinds on a bound pipe - use alter context. */ + if (p->pipe_bound) { + DEBUG(2,("api_pipe_bind_req: rejecting bind request on bound pipe %s.\n", p->pipe_srv_name)); + return setup_bind_nak(p); + } - p->ntlmssp_auth_requested = False; - p->netsec_auth_validated = False; + prs_init( &outgoing_rpc, 0, p->mem_ctx, MARSHALL); + + /* + * Marshall directly into the outgoing PDU space. We + * must do this as we need to set to the bind response + * header and are never sending more than one PDU here. + */ + + prs_give_memory( &outgoing_rpc, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False); + + /* + * Setup the memory to marshall the ba header, and the + * auth footers. + */ + + if(!prs_init(&out_hdr_ba, 1024, p->mem_ctx, MARSHALL)) { + DEBUG(0,("api_pipe_bind_req: malloc out_hdr_ba failed.\n")); + prs_mem_free(&outgoing_rpc); + return False; + } + + if(!prs_init(&out_auth, 1024, p->mem_ctx, MARSHALL)) { + DEBUG(0,("api_pipe_bind_req: malloc out_auth failed.\n")); + prs_mem_free(&outgoing_rpc); + prs_mem_free(&out_hdr_ba); + return False; + } DEBUG(5,("api_pipe_bind_req: decode request. %d\n", __LINE__)); /* - * Try and find the correct pipe name to ensure - * that this is a pipe name we support. + * Try and find the correct pipe name to ensure + * that this is a pipe name we support. + */ + + + for (i = 0; i < rpc_lookup_size; i++) { + if (strequal(rpc_lookup[i].pipe.clnt, p->name)) { + DEBUG(3, ("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n", + rpc_lookup[i].pipe.clnt, rpc_lookup[i].pipe.srv)); + fstrcpy(p->pipe_srv_name, rpc_lookup[i].pipe.srv); + break; + } + } + + if (i == rpc_lookup_size) { + if (NT_STATUS_IS_ERR(smb_probe_module("rpc", p->name))) { + DEBUG(3,("api_pipe_bind_req: Unknown pipe name %s in bind request.\n", + p->name )); + prs_mem_free(&outgoing_rpc); + prs_mem_free(&out_hdr_ba); + prs_mem_free(&out_auth); + + return setup_bind_nak(p); + } + + for (i = 0; i < rpc_lookup_size; i++) { + if (strequal(rpc_lookup[i].pipe.clnt, p->name)) { + DEBUG(3, ("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n", + rpc_lookup[i].pipe.clnt, rpc_lookup[i].pipe.srv)); + fstrcpy(p->pipe_srv_name, rpc_lookup[i].pipe.srv); + break; + } + } + + if (i == rpc_lookup_size) { + DEBUG(0, ("module %s doesn't provide functions for pipe %s!\n", p->name, p->name)); + goto err_exit; + } + } + + /* decode the bind request */ + if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_in_p, 0)) { + DEBUG(0,("api_pipe_bind_req: unable to unmarshall RPC_HDR_RB struct.\n")); + goto err_exit; + } + + /* name has to be \PIPE\xxxxx */ + fstrcpy(ack_pipe_name, "\\PIPE\\"); + fstrcat(ack_pipe_name, p->pipe_srv_name); + + DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__)); + + /* + * Check if this is an authenticated bind request. + */ + + if (p->hdr.auth_len) { + /* + * Decode the authentication verifier. + */ + + if(!smb_io_rpc_hdr_auth("", &auth_info, rpc_in_p, 0)) { + DEBUG(0,("api_pipe_bind_req: unable to unmarshall RPC_HDR_AUTH struct.\n")); + goto err_exit; + } + + auth_type = auth_info.auth_type; + + /* Work out if we have to sign or seal etc. */ + switch (auth_info.auth_level) { + case RPC_AUTH_LEVEL_INTEGRITY: + p->auth.auth_level = PIPE_AUTH_LEVEL_INTEGRITY; + break; + case RPC_AUTH_LEVEL_PRIVACY: + p->auth.auth_level = PIPE_AUTH_LEVEL_PRIVACY; + break; + default: + DEBUG(0,("api_pipe_bind_req: unexpected auth level (%u).\n", + (unsigned int)auth_info.auth_level )); + goto err_exit; + } + } else { + ZERO_STRUCT(auth_info); + } + + assoc_gid = hdr_rb.bba.assoc_gid ? hdr_rb.bba.assoc_gid : 0x53f0; + + switch(auth_type) { + case RPC_NTLMSSP_AUTH_TYPE: + if (!pipe_ntlmssp_auth_bind(p, rpc_in_p, &auth_info, &out_auth)) { + goto err_exit; + } + assoc_gid = 0x7a77; + break; + + case RPC_SCHANNEL_AUTH_TYPE: + if (!pipe_schannel_auth_bind(p, rpc_in_p, &auth_info, &out_auth)) { + goto err_exit; + } + break; + + case RPC_SPNEGO_AUTH_TYPE: + if (!pipe_spnego_auth_bind_negotiate(p, rpc_in_p, &auth_info, &out_auth)) { + goto err_exit; + } + break; + + case RPC_ANONYMOUS_AUTH_TYPE: + /* Unauthenticated bind request. */ + /* We're finished - no more packets. */ + p->auth.auth_type = PIPE_AUTH_TYPE_NONE; + /* We must set the pipe auth_level here also. */ + p->auth.auth_level = PIPE_AUTH_LEVEL_NONE; + p->pipe_bound = True; + break; + + default: + DEBUG(0,("api_pipe_bind_req: unknown auth type %x requested.\n", auth_type )); + goto err_exit; + } + + /* + * Create the bind response struct. + */ + + /* If the requested abstract synt uuid doesn't match our client pipe, + reject the bind_ack & set the transfer interface synt to all 0's, + ver 0 (observed when NT5 attempts to bind to abstract interfaces + unknown to NT4) + Needed when adding entries to a DACL from NT5 - SK */ + + if(check_bind_req(p, &hdr_rb.rpc_context[0].abstract, &hdr_rb.rpc_context[0].transfer[0], + hdr_rb.rpc_context[0].context_id )) { + init_rpc_hdr_ba(&hdr_ba, + RPC_MAX_PDU_FRAG_LEN, + RPC_MAX_PDU_FRAG_LEN, + assoc_gid, + ack_pipe_name, + 0x1, 0x0, 0x0, + &hdr_rb.rpc_context[0].transfer[0]); + } else { + RPC_IFACE null_interface; + ZERO_STRUCT(null_interface); + /* Rejection reason: abstract syntax not supported */ + init_rpc_hdr_ba(&hdr_ba, RPC_MAX_PDU_FRAG_LEN, + RPC_MAX_PDU_FRAG_LEN, assoc_gid, + ack_pipe_name, 0x1, 0x2, 0x1, + &null_interface); + p->pipe_bound = False; + } + + /* + * and marshall it. */ - - for (i = 0; i < rpc_lookup_size; i++) { - if (strequal(rpc_lookup[i].pipe.clnt, p->name)) { - DEBUG(3, ("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n", - rpc_lookup[i].pipe.clnt, rpc_lookup[i].pipe.srv)); - fstrcpy(p->pipe_srv_name, rpc_lookup[i].pipe.srv); - break; - } + if(!smb_io_rpc_hdr_ba("", &hdr_ba, &out_hdr_ba, 0)) { + DEBUG(0,("api_pipe_bind_req: marshalling of RPC_HDR_BA failed.\n")); + goto err_exit; } - if (i == rpc_lookup_size) { - if (NT_STATUS_IS_ERR(smb_probe_module("rpc", p->name))) { - DEBUG(3,("api_pipe_bind_req: Unknown pipe name %s in bind request.\n", - p->name )); - return setup_bind_nak(p); - } - - for (i = 0; i < rpc_lookup_size; i++) { - if (strequal(rpc_lookup[i].pipe.clnt, p->name)) { - DEBUG(3, ("api_pipe_bind_req: \\PIPE\\%s -> \\PIPE\\%s\n", - rpc_lookup[i].pipe.clnt, rpc_lookup[i].pipe.srv)); - fstrcpy(p->pipe_srv_name, rpc_lookup[i].pipe.srv); - break; - } - } + /* + * Create the header, now we know the length. + */ - if (i == rpc_lookup_size) { - DEBUG(0, ("module %s doesn't provide functions for pipe %s!\n", p->name, p->name)); - return False; - } + if (prs_offset(&out_auth)) { + auth_len = prs_offset(&out_auth) - RPC_HDR_AUTH_LEN; } - /* decode the bind request */ - if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_in_p, 0)) { - DEBUG(0,("api_pipe_bind_req: unable to unmarshall RPC_HDR_RB struct.\n")); - return setup_bind_nak(p); - } + init_rpc_hdr(&p->hdr, RPC_BINDACK, RPC_FLG_FIRST | RPC_FLG_LAST, + p->hdr.call_id, + RPC_HEADER_LEN + prs_offset(&out_hdr_ba) + prs_offset(&out_auth), + auth_len); /* - * Check if this is an authenticated request. + * Marshall the header into the outgoing PDU. */ - if (p->hdr.auth_len != 0) { - RPC_AUTH_VERIFIER auth_verifier; - RPC_AUTH_NTLMSSP_NEG ntlmssp_neg; - - /* - * Decode the authentication verifier. - */ - - if(!smb_io_rpc_hdr_auth("", &auth_info, rpc_in_p, 0)) { - DEBUG(0,("api_pipe_bind_req: unable to unmarshall RPC_HDR_AUTH struct.\n")); - return setup_bind_nak(p); - } - - switch(auth_info.auth_type) { - case NTLMSSP_AUTH_TYPE: - - if(!smb_io_rpc_auth_verifier("", &auth_verifier, rpc_in_p, 0)) { - DEBUG(0,("api_pipe_bind_req: unable to " - "unmarshall RPC_HDR_AUTH struct.\n")); - return setup_bind_nak(p); - } - - if(!strequal(auth_verifier.signature, "NTLMSSP")) { - DEBUG(0,("api_pipe_bind_req: " - "auth_verifier.signature != NTLMSSP\n")); - return setup_bind_nak(p); - } - - if(auth_verifier.msg_type != NTLMSSP_NEGOTIATE) { - DEBUG(0,("api_pipe_bind_req: " - "auth_verifier.msg_type (%d) != NTLMSSP_NEGOTIATE\n", - auth_verifier.msg_type)); - return setup_bind_nak(p); - } + if(!smb_io_rpc_hdr("", &p->hdr, &outgoing_rpc, 0)) { + DEBUG(0,("api_pipe_bind_req: marshalling of RPC_HDR failed.\n")); + goto err_exit; + } - if(!smb_io_rpc_auth_ntlmssp_neg("", &ntlmssp_neg, rpc_in_p, 0)) { - DEBUG(0,("api_pipe_bind_req: " - "Failed to unmarshall RPC_AUTH_NTLMSSP_NEG.\n")); - return setup_bind_nak(p); - } + /* + * Now add the RPC_HDR_BA and any auth needed. + */ - p->ntlmssp_chal_flags = SMBD_NTLMSSP_NEG_FLAGS; - p->ntlmssp_auth_requested = True; - break; + if(!prs_append_prs_data( &outgoing_rpc, &out_hdr_ba)) { + DEBUG(0,("api_pipe_bind_req: append of RPC_HDR_BA failed.\n")); + goto err_exit; + } - case NETSEC_AUTH_TYPE: - { - RPC_AUTH_NETSEC_NEG neg; - struct netsec_auth_struct *a = &(p->netsec_auth); + if (auth_len && !prs_append_prs_data( &outgoing_rpc, &out_auth)) { + DEBUG(0,("api_pipe_bind_req: append of auth info failed.\n")); + goto err_exit; + } - if (!server_auth2_negotiated) { - DEBUG(0, ("Attempt to bind using schannel " - "without successful serverauth2\n")); - return setup_bind_nak(p); - } + /* + * Setup the lengths for the initial reply. + */ - if (!smb_io_rpc_auth_netsec_neg("", &neg, rpc_in_p, 0)) { - DEBUG(0,("api_pipe_bind_req: " - "Could not unmarshal SCHANNEL auth neg\n")); - return setup_bind_nak(p); - } + p->out_data.data_sent_length = 0; + p->out_data.current_pdu_len = prs_offset(&outgoing_rpc); + p->out_data.current_pdu_sent = 0; - p->netsec_auth_validated = True; + prs_mem_free(&out_hdr_ba); + prs_mem_free(&out_auth); - memset(a->sess_key, 0, sizeof(a->sess_key)); - memcpy(a->sess_key, last_dcinfo.sess_key, sizeof(last_dcinfo.sess_key)); + return True; - a->seq_num = 0; + err_exit: - DEBUG(10,("schannel auth: domain [%s] myname [%s]\n", - neg.domain, neg.myname)); - break; - } + prs_mem_free(&outgoing_rpc); + prs_mem_free(&out_hdr_ba); + prs_mem_free(&out_auth); + return setup_bind_nak(p); +} - case SPNEGO_AUTH_TYPE: - default: - DEBUG(0,("api_pipe_bind_req: unknown auth type %x requested.\n", - auth_info.auth_type )); - return setup_bind_nak(p); - } - } +/**************************************************************************** + Deal with an alter context call. Can be third part of 3 leg auth request for + SPNEGO calls. +****************************************************************************/ - switch(p->hdr.pkt_type) { - case RPC_BIND: - /* name has to be \PIPE\xxxxx */ - fstrcpy(ack_pipe_name, "\\PIPE\\"); - fstrcat(ack_pipe_name, p->pipe_srv_name); - reply_pkt_type = RPC_BINDACK; - break; - case RPC_ALTCONT: - /* secondary address CAN be NULL - * as the specs say it's ignored. - * It MUST NULL to have the spoolss working. - */ - fstrcpy(ack_pipe_name,""); - reply_pkt_type = RPC_ALTCONTRESP; - break; - default: - return False; - } +BOOL api_pipe_alter_context(pipes_struct *p, prs_struct *rpc_in_p) +{ + RPC_HDR_BA hdr_ba; + RPC_HDR_RB hdr_rb; + RPC_HDR_AUTH auth_info; + uint16 assoc_gid; + fstring ack_pipe_name; + prs_struct out_hdr_ba; + prs_struct out_auth; + prs_struct outgoing_rpc; + int auth_len = 0; - DEBUG(5,("api_pipe_bind_req: make response. %d\n", __LINE__)); + prs_init( &outgoing_rpc, 0, p->mem_ctx, MARSHALL); /* * Marshall directly into the outgoing PDU space. We @@ -1035,7 +1666,6 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) * header and are never sending more than one PDU here. */ - prs_init( &outgoing_rpc, 0, p->mem_ctx, MARSHALL); prs_give_memory( &outgoing_rpc, (char *)p->out_data.current_pdu, sizeof(p->out_data.current_pdu), False); /* @@ -1044,22 +1674,68 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) */ if(!prs_init(&out_hdr_ba, 1024, p->mem_ctx, MARSHALL)) { - DEBUG(0,("api_pipe_bind_req: malloc out_hdr_ba failed.\n")); + DEBUG(0,("api_pipe_alter_context: malloc out_hdr_ba failed.\n")); prs_mem_free(&outgoing_rpc); return False; } if(!prs_init(&out_auth, 1024, p->mem_ctx, MARSHALL)) { - DEBUG(0,("pi_pipe_bind_req: malloc out_auth failed.\n")); + DEBUG(0,("api_pipe_alter_context: malloc out_auth failed.\n")); prs_mem_free(&outgoing_rpc); prs_mem_free(&out_hdr_ba); return False; } - if (p->ntlmssp_auth_requested) - assoc_gid = 0x7a77; - else - assoc_gid = hdr_rb.bba.assoc_gid ? hdr_rb.bba.assoc_gid : 0x53f0; + DEBUG(5,("api_pipe_alter_context: decode request. %d\n", __LINE__)); + + /* decode the alter context request */ + if(!smb_io_rpc_hdr_rb("", &hdr_rb, rpc_in_p, 0)) { + DEBUG(0,("api_pipe_alter_context: unable to unmarshall RPC_HDR_RB struct.\n")); + goto err_exit; + } + + /* secondary address CAN be NULL + * as the specs say it's ignored. + * It MUST be NULL to have the spoolss working. + */ + fstrcpy(ack_pipe_name,""); + + DEBUG(5,("api_pipe_alter_context: make response. %d\n", __LINE__)); + + /* + * Check if this is an authenticated alter context request. + */ + + if (p->hdr.auth_len != 0) { + /* + * Decode the authentication verifier. + */ + + if(!smb_io_rpc_hdr_auth("", &auth_info, rpc_in_p, 0)) { + DEBUG(0,("api_pipe_alter_context: unable to unmarshall RPC_HDR_AUTH struct.\n")); + goto err_exit; + } + + /* + * Currently only the SPNEGO auth type uses the alter ctx + * response in place of the NTLMSSP auth3 type. + */ + + if (auth_info.auth_type == RPC_SPNEGO_AUTH_TYPE) { + /* We can only finish if the pipe is unbound. */ + if (!p->pipe_bound) { + if (!pipe_spnego_auth_bind_continue(p, rpc_in_p, &auth_info, &out_auth)) { + goto err_exit; + } + } else { + goto err_exit; + } + } + } else { + ZERO_STRUCT(auth_info); + } + + assoc_gid = hdr_rb.bba.assoc_gid ? hdr_rb.bba.assoc_gid : 0x53f0; /* * Create the bind response struct. @@ -1074,8 +1750,8 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) if(check_bind_req(p, &hdr_rb.rpc_context[0].abstract, &hdr_rb.rpc_context[0].transfer[0], hdr_rb.rpc_context[0].context_id )) { init_rpc_hdr_ba(&hdr_ba, - MAX_PDU_FRAG_LEN, - MAX_PDU_FRAG_LEN, + RPC_MAX_PDU_FRAG_LEN, + RPC_MAX_PDU_FRAG_LEN, assoc_gid, ack_pipe_name, 0x1, 0x0, 0x0, @@ -1084,10 +1760,11 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) RPC_IFACE null_interface; ZERO_STRUCT(null_interface); /* Rejection reason: abstract syntax not supported */ - init_rpc_hdr_ba(&hdr_ba, MAX_PDU_FRAG_LEN, - MAX_PDU_FRAG_LEN, assoc_gid, + init_rpc_hdr_ba(&hdr_ba, RPC_MAX_PDU_FRAG_LEN, + RPC_MAX_PDU_FRAG_LEN, assoc_gid, ack_pipe_name, 0x1, 0x2, 0x1, &null_interface); + p->pipe_bound = False; } /* @@ -1095,85 +1772,19 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) */ if(!smb_io_rpc_hdr_ba("", &hdr_ba, &out_hdr_ba, 0)) { - DEBUG(0,("api_pipe_bind_req: marshalling of RPC_HDR_BA failed.\n")); + DEBUG(0,("api_pipe_alter_context: marshalling of RPC_HDR_BA failed.\n")); goto err_exit; } /* - * Now the authentication. + * Create the header, now we know the length. */ - if (p->ntlmssp_auth_requested) { - RPC_AUTH_VERIFIER auth_verifier; - RPC_AUTH_NTLMSSP_CHAL ntlmssp_chal; - - generate_random_buffer(p->challenge, 8); - - /*** Authentication info ***/ - - init_rpc_hdr_auth(&auth_info, NTLMSSP_AUTH_TYPE, RPC_PIPE_AUTH_SEAL_LEVEL, RPC_HDR_AUTH_LEN, 1); - if(!smb_io_rpc_hdr_auth("", &auth_info, &out_auth, 0)) { - DEBUG(0,("api_pipe_bind_req: marshalling of RPC_HDR_AUTH failed.\n")); - goto err_exit; - } - - /*** NTLMSSP verifier ***/ - - init_rpc_auth_verifier(&auth_verifier, "NTLMSSP", NTLMSSP_CHALLENGE); - if(!smb_io_rpc_auth_verifier("", &auth_verifier, &out_auth, 0)) { - DEBUG(0,("api_pipe_bind_req: marshalling of RPC_AUTH_VERIFIER failed.\n")); - goto err_exit; - } - - /* NTLMSSP challenge ***/ - - init_rpc_auth_ntlmssp_chal(&ntlmssp_chal, p->ntlmssp_chal_flags, p->challenge); - if(!smb_io_rpc_auth_ntlmssp_chal("", &ntlmssp_chal, &out_auth, 0)) { - DEBUG(0,("api_pipe_bind_req: marshalling of RPC_AUTH_NTLMSSP_CHAL failed.\n")); - goto err_exit; - } - - /* Auth len in the rpc header doesn't include auth_header. */ - auth_len = prs_offset(&out_auth) - RPC_HDR_AUTH_LEN; - } - - if (p->netsec_auth_validated) { - RPC_AUTH_VERIFIER auth_verifier; - uint32 flags; - - /* The client opens a second RPC NETLOGON pipe without - doing a auth2. The credentials for the schannel are - re-used from the auth2 the client did before. */ - p->dc = last_dcinfo; - - init_rpc_hdr_auth(&auth_info, NETSEC_AUTH_TYPE, auth_info.auth_level, RPC_HDR_AUTH_LEN, 1); - if(!smb_io_rpc_hdr_auth("", &auth_info, &out_auth, 0)) { - DEBUG(0,("api_pipe_bind_req: marshalling of RPC_HDR_AUTH failed.\n")); - goto err_exit; - } - - /*** NETSEC verifier ***/ - - init_rpc_auth_verifier(&auth_verifier, "\001", 0x0); - if(!smb_io_rpc_netsec_verifier("", &auth_verifier, &out_auth, 0)) { - DEBUG(0,("api_pipe_bind_req: marshalling of RPC_AUTH_VERIFIER failed.\n")); - goto err_exit; - } - - prs_align(&out_auth); - - flags = 5; - if(!prs_uint32("flags ", &out_auth, 0, &flags)) - goto err_exit; - + if (prs_offset(&out_auth)) { auth_len = prs_offset(&out_auth) - RPC_HDR_AUTH_LEN; } - /* - * Create the header, now we know the length. - */ - - init_rpc_hdr(&p->hdr, reply_pkt_type, RPC_FLG_FIRST | RPC_FLG_LAST, + init_rpc_hdr(&p->hdr, RPC_ALTCONTRESP, RPC_FLG_FIRST | RPC_FLG_LAST, p->hdr.call_id, RPC_HEADER_LEN + prs_offset(&out_hdr_ba) + prs_offset(&out_auth), auth_len); @@ -1183,7 +1794,7 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) */ if(!smb_io_rpc_hdr("", &p->hdr, &outgoing_rpc, 0)) { - DEBUG(0,("pi_pipe_bind_req: marshalling of RPC_HDR failed.\n")); + DEBUG(0,("api_pipe_alter_context: marshalling of RPC_HDR failed.\n")); goto err_exit; } @@ -1192,19 +1803,15 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) */ if(!prs_append_prs_data( &outgoing_rpc, &out_hdr_ba)) { - DEBUG(0,("api_pipe_bind_req: append of RPC_HDR_BA failed.\n")); + DEBUG(0,("api_pipe_alter_context: append of RPC_HDR_BA failed.\n")); goto err_exit; } - if((p->ntlmssp_auth_requested|p->netsec_auth_validated) && - !prs_append_prs_data( &outgoing_rpc, &out_auth)) { - DEBUG(0,("api_pipe_bind_req: append of auth info failed.\n")); + if (auth_len && !prs_append_prs_data( &outgoing_rpc, &out_auth)) { + DEBUG(0,("api_pipe_alter_context: append of auth info failed.\n")); goto err_exit; } - if(!p->ntlmssp_auth_requested) - p->pipe_bound = True; - /* * Setup the lengths for the initial reply. */ @@ -1223,138 +1830,141 @@ BOOL api_pipe_bind_req(pipes_struct *p, prs_struct *rpc_in_p) prs_mem_free(&outgoing_rpc); prs_mem_free(&out_hdr_ba); prs_mem_free(&out_auth); - return False; + return setup_bind_nak(p); } /**************************************************************************** - Deal with sign & seal processing on an RPC request. + Deal with NTLMSSP sign & seal processing on an RPC request. ****************************************************************************/ -BOOL api_pipe_auth_process(pipes_struct *p, prs_struct *rpc_in) +BOOL api_pipe_ntlmssp_auth_process(pipes_struct *p, prs_struct *rpc_in, + uint32 *p_ss_padding_len, NTSTATUS *pstatus) { - /* - * We always negotiate the following two bits.... - */ - BOOL auth_verify = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) != 0); - BOOL auth_seal = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SEAL) != 0); - int data_len; - int auth_len; - uint32 old_offset; - uint32 crc32 = 0; + RPC_HDR_AUTH auth_info; + uint32 auth_len = p->hdr.auth_len; + uint32 save_offset = prs_offset(rpc_in); + AUTH_NTLMSSP_STATE *a = p->auth.a_u.auth_ntlmssp_state; + unsigned char *data = NULL; + size_t data_len; + unsigned char *full_packet_data = NULL; + size_t full_packet_data_len; + DATA_BLOB auth_blob; + + *pstatus = NT_STATUS_OK; - auth_len = p->hdr.auth_len; + if (p->auth.auth_level == PIPE_AUTH_LEVEL_NONE || p->auth.auth_level == PIPE_AUTH_LEVEL_CONNECT) { + return True; + } + + if (!a) { + *pstatus = NT_STATUS_INVALID_PARAMETER; + return False; + } - if ((auth_len != RPC_AUTH_NTLMSSP_CHK_LEN) && auth_verify) { - DEBUG(0,("api_pipe_auth_process: Incorrect auth_len %d.\n", auth_len )); + /* Ensure there's enough data for an authenticated request. */ + if ((auth_len > RPC_MAX_SIGN_SIZE) || + (RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_HDR_AUTH_LEN + auth_len > p->hdr.frag_len)) { + DEBUG(0,("api_pipe_ntlmssp_auth_process: auth_len %u is too large.\n", + (unsigned int)auth_len )); + *pstatus = NT_STATUS_INVALID_PARAMETER; return False; } /* - * The following is that length of the data we must verify or unseal. - * This doesn't include the RPC headers or the auth_len or the RPC_HDR_AUTH_LEN - * preceeding the auth_data. + * We need the full packet data + length (minus auth stuff) as well as the packet data + length + * after the RPC header. + * We need to pass in the full packet (minus auth len) to the NTLMSSP sign and check seal + * functions as NTLMv2 checks the rpc headers also. */ - data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN - - (auth_verify ? RPC_HDR_AUTH_LEN : 0) - auth_len; - - DEBUG(5,("api_pipe_auth_process: sign: %s seal: %s data %d auth %d\n", - BOOLSTR(auth_verify), BOOLSTR(auth_seal), data_len, auth_len)); + data = (unsigned char *)(prs_data_p(rpc_in) + RPC_HDR_REQ_LEN); + data_len = (size_t)(p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN - RPC_HDR_AUTH_LEN - auth_len); - if (auth_seal) { - /* - * The data in rpc_in doesn't contain the RPC_HEADER as this - * has already been consumed. - */ - char *data = prs_data_p(rpc_in) + RPC_HDR_REQ_LEN; - dump_data_pw("NTLMSSP hash (v1)\n", p->ntlmssp_hash, - sizeof(p->ntlmssp_hash)); + full_packet_data = p->in_data.current_in_pdu; + full_packet_data_len = p->hdr.frag_len - auth_len; - dump_data_pw("Incoming RPC PDU (NTLMSSP sealed)\n", - (const unsigned char *)data, data_len); - NTLMSSPcalc_p(p, (uchar*)data, data_len); - dump_data_pw("Incoming RPC PDU (NTLMSSP unsealed)\n", - (const unsigned char *)data, data_len); - crc32 = crc32_calc_buffer(data, data_len); + /* Pull the auth header and the following data into a blob. */ + if(!prs_set_offset(rpc_in, RPC_HDR_REQ_LEN + data_len)) { + DEBUG(0,("api_pipe_ntlmssp_auth_process: cannot move offset to %u.\n", + (unsigned int)RPC_HDR_REQ_LEN + (unsigned int)data_len )); + *pstatus = NT_STATUS_INVALID_PARAMETER; + return False; } - old_offset = prs_offset(rpc_in); - - if (auth_seal || auth_verify) { - RPC_HDR_AUTH auth_info; - - if(!prs_set_offset(rpc_in, old_offset + data_len)) { - DEBUG(0,("api_pipe_auth_process: cannot move offset to %u.\n", - (unsigned int)old_offset + data_len )); - return False; - } - - if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, rpc_in, 0)) { - DEBUG(0,("api_pipe_auth_process: failed to unmarshall RPC_HDR_AUTH.\n")); - return False; - } + if(!smb_io_rpc_hdr_auth("hdr_auth", &auth_info, rpc_in, 0)) { + DEBUG(0,("api_pipe_ntlmssp_auth_process: failed to unmarshall RPC_HDR_AUTH.\n")); + *pstatus = NT_STATUS_INVALID_PARAMETER; + return False; } - if (auth_verify) { - RPC_AUTH_NTLMSSP_CHK ntlmssp_chk; - char *req_data = prs_data_p(rpc_in) + prs_offset(rpc_in) + 4; - - DEBUG(5,("api_pipe_auth_process: auth %d\n", prs_offset(rpc_in) + 4)); - - /* - * Ensure we have RPC_AUTH_NTLMSSP_CHK_LEN - 4 more bytes in the - * incoming buffer. - */ - if(prs_mem_get(rpc_in, RPC_AUTH_NTLMSSP_CHK_LEN - 4) == NULL) { - DEBUG(0,("api_pipe_auth_process: missing %d bytes in buffer.\n", - RPC_AUTH_NTLMSSP_CHK_LEN - 4 )); - return False; - } - - NTLMSSPcalc_p(p, (uchar*)req_data, RPC_AUTH_NTLMSSP_CHK_LEN - 4); - if(!smb_io_rpc_auth_ntlmssp_chk("auth_sign", &ntlmssp_chk, rpc_in, 0)) { - DEBUG(0,("api_pipe_auth_process: failed to unmarshall RPC_AUTH_NTLMSSP_CHK.\n")); - return False; - } - - if (!rpc_auth_ntlmssp_chk(&ntlmssp_chk, crc32, p->ntlmssp_seq_num)) { - DEBUG(0,("api_pipe_auth_process: NTLMSSP check failed.\n")); + auth_blob.data = prs_data_p(rpc_in) + prs_offset(rpc_in); + auth_blob.length = auth_len; + + switch (p->auth.auth_level) { + case PIPE_AUTH_LEVEL_PRIVACY: + /* Data is encrypted. */ + *pstatus = ntlmssp_unseal_packet(a->ntlmssp_state, + data, data_len, + full_packet_data, + full_packet_data_len, + &auth_blob); + if (!NT_STATUS_IS_OK(*pstatus)) { + return False; + } + break; + case PIPE_AUTH_LEVEL_INTEGRITY: + /* Data is signed. */ + *pstatus = ntlmssp_check_packet(a->ntlmssp_state, + data, data_len, + full_packet_data, + full_packet_data_len, + &auth_blob); + if (!NT_STATUS_IS_OK(*pstatus)) { + return False; + } + break; + default: + *pstatus = NT_STATUS_INVALID_PARAMETER; return False; - } } /* * Return the current pointer to the data offset. */ - if(!prs_set_offset(rpc_in, old_offset)) { + if(!prs_set_offset(rpc_in, save_offset)) { DEBUG(0,("api_pipe_auth_process: failed to set offset back to %u\n", - (unsigned int)old_offset )); + (unsigned int)save_offset )); + *pstatus = NT_STATUS_INVALID_PARAMETER; return False; } + /* + * Remember the padding length. We must remove it from the real data + * stream once the sign/seal is done. + */ + + *p_ss_padding_len = auth_info.auth_pad_len; + return True; } /**************************************************************************** Deal with schannel processing on an RPC request. ****************************************************************************/ -BOOL api_pipe_netsec_process(pipes_struct *p, prs_struct *rpc_in) + +BOOL api_pipe_schannel_process(pipes_struct *p, prs_struct *rpc_in, uint32 *p_ss_padding_len) { - /* - * We always negotiate the following two bits.... - */ - int data_len; - int auth_len; - uint32 old_offset; + uint32 data_len; + uint32 auth_len; + uint32 save_offset = prs_offset(rpc_in); RPC_HDR_AUTH auth_info; - RPC_AUTH_NETSEC_CHK netsec_chk; - + RPC_AUTH_SCHANNEL_CHK schannel_chk; auth_len = p->hdr.auth_len; - if (auth_len != RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN) { - DEBUG(0,("Incorrect auth_len %d.\n", auth_len )); + if (auth_len != RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN) { + DEBUG(0,("Incorrect auth_len %u.\n", (unsigned int)auth_len )); return False; } @@ -1364,16 +1974,21 @@ BOOL api_pipe_netsec_process(pipes_struct *p, prs_struct *rpc_in) * preceeding the auth_data. */ + if (p->hdr.frag_len < RPC_HEADER_LEN + RPC_HDR_REQ_LEN + RPC_HDR_AUTH_LEN + auth_len) { + DEBUG(0,("Incorrect frag %u, auth %u.\n", + (unsigned int)p->hdr.frag_len, + (unsigned int)auth_len )); + return False; + } + data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN - RPC_HDR_AUTH_LEN - auth_len; DEBUG(5,("data %d auth %d\n", data_len, auth_len)); - old_offset = prs_offset(rpc_in); - - if(!prs_set_offset(rpc_in, old_offset + data_len)) { + if(!prs_set_offset(rpc_in, RPC_HDR_REQ_LEN + data_len)) { DEBUG(0,("cannot move offset to %u.\n", - (unsigned int)old_offset + data_len )); + (unsigned int)RPC_HDR_REQ_LEN + data_len )); return False; } @@ -1382,34 +1997,22 @@ BOOL api_pipe_netsec_process(pipes_struct *p, prs_struct *rpc_in) return False; } - if (auth_info.auth_type != NETSEC_AUTH_TYPE) { + if (auth_info.auth_type != RPC_SCHANNEL_AUTH_TYPE) { DEBUG(0,("Invalid auth info %d on schannel\n", auth_info.auth_type)); return False; } - if (auth_info.auth_level == RPC_PIPE_AUTH_SEAL_LEVEL) { - p->netsec_auth.auth_flags = AUTH_PIPE_NETSEC|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL; - } else if (auth_info.auth_level == RPC_PIPE_AUTH_SIGN_LEVEL) { - p->netsec_auth.auth_flags = AUTH_PIPE_NETSEC|AUTH_PIPE_SIGN; - } else { - DEBUG(0,("Invalid auth level %d on schannel\n", - auth_info.auth_level)); - return False; - } - - if(!smb_io_rpc_auth_netsec_chk("", RPC_AUTH_NETSEC_SIGN_OR_SEAL_CHK_LEN, - &netsec_chk, rpc_in, 0)) - { - DEBUG(0,("failed to unmarshal RPC_AUTH_NETSEC_CHK.\n")); + if(!smb_io_rpc_auth_schannel_chk("", RPC_AUTH_SCHANNEL_SIGN_OR_SEAL_CHK_LEN, &schannel_chk, rpc_in, 0)) { + DEBUG(0,("failed to unmarshal RPC_AUTH_SCHANNEL_CHK.\n")); return False; } - if (!netsec_decode(&p->netsec_auth, - p->netsec_auth.auth_flags, + if (!schannel_decode(p->auth.a_u.schannel_auth, + p->auth.auth_level, SENDER_IS_INITIATOR, - &netsec_chk, - prs_data_p(rpc_in)+old_offset, data_len)) { + &schannel_chk, + prs_data_p(rpc_in)+RPC_HDR_REQ_LEN, data_len)) { DEBUG(3,("failed to decode PDU\n")); return False; } @@ -1418,14 +2021,21 @@ BOOL api_pipe_netsec_process(pipes_struct *p, prs_struct *rpc_in) * Return the current pointer to the data offset. */ - if(!prs_set_offset(rpc_in, old_offset)) { + if(!prs_set_offset(rpc_in, save_offset)) { DEBUG(0,("failed to set offset back to %u\n", - (unsigned int)old_offset )); + (unsigned int)save_offset )); return False; } /* The sequence number gets incremented on both send and receive. */ - p->netsec_auth.seq_num++; + p->auth.a_u.schannel_auth->seq_num++; + + /* + * Remember the padding length. We must remove it from the real data + * stream once the sign/seal is done. + */ + + *p_ss_padding_len = auth_info.auth_pad_len; return True; } @@ -1436,7 +2046,9 @@ BOOL api_pipe_netsec_process(pipes_struct *p, prs_struct *rpc_in) struct current_user *get_current_user(struct current_user *user, pipes_struct *p) { - if (p->ntlmssp_auth_validated) { + if (p->pipe_bound && + (p->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP || + (p->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP))) { memcpy(user, &p->pipe_user, sizeof(struct current_user)); } else { memcpy(user, ¤t_user, sizeof(struct current_user)); @@ -1470,7 +2082,7 @@ static PIPE_RPC_FNS* find_pipe_fns_by_context( PIPE_RPC_FNS *list, uint32 contex } /**************************************************************************** - memory cleanup + Memory cleanup. ****************************************************************************/ void free_pipe_rpc_context( PIPE_RPC_FNS *list ) @@ -1496,14 +2108,17 @@ void free_pipe_rpc_context( PIPE_RPC_FNS *list ) BOOL api_pipe_request(pipes_struct *p) { BOOL ret = False; + BOOL changed_user = False; PIPE_RPC_FNS *pipe_fns; - if (p->ntlmssp_auth_validated) { - + if (p->pipe_bound && + ((p->auth.auth_type == PIPE_AUTH_TYPE_NTLMSSP) || + (p->auth.auth_type == PIPE_AUTH_TYPE_SPNEGO_NTLMSSP))) { if(!become_authenticated_pipe_user(p)) { prs_mem_free(&p->out_data.rdata); return False; } + changed_user = True; } DEBUG(5, ("Requested \\PIPE\\%s\n", p->name)); @@ -1522,8 +2137,9 @@ BOOL api_pipe_request(pipes_struct *p) p->hdr_req.context_id, p->name)); } - if(p->ntlmssp_auth_validated) + if (changed_user) { unbecome_authenticated_pipe_user(); + } return ret; } @@ -1649,6 +2265,9 @@ void get_pipe_fns( int idx, struct api_struct **fns, int *n_fns ) case PI_EVENTLOG: eventlog_get_pipe_fns( &cmds, &n_cmds ); break; + case PI_NTSVCS: + ntsvcs_get_pipe_fns( &cmds, &n_cmds ); + break; #ifdef DEVELOPER case PI_ECHO: echo_get_pipe_fns( &cmds, &n_cmds ); @@ -1663,5 +2282,3 @@ void get_pipe_fns( int idx, struct api_struct **fns, int *n_fns ) return; } - - diff --git a/source3/rpc_server/srv_pipe_hnd.c b/source3/rpc_server/srv_pipe_hnd.c index 83b78f8d2f6..205223190b4 100644 --- a/source3/rpc_server/srv_pipe_hnd.c +++ b/source3/rpc_server/srv_pipe_hnd.c @@ -2,8 +2,8 @@ * Unix SMB/CIFS implementation. * RPC Pipe client / server routines * Copyright (C) Andrew Tridgell 1992-1998, - * Copyright (C) Luke Kenneth Casson Leighton 1996-1998, - * Copyright (C) Jeremy Allison 1999. + * Largely re-written : 2005 + * Copyright (C) Jeremy Allison 1998 - 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 @@ -106,10 +106,11 @@ static int pipe_handle_offset; void set_pipe_handle_offset(int max_open_files) { - if(max_open_files < 0x7000) - pipe_handle_offset = 0x7000; - else - pipe_handle_offset = max_open_files + 10; /* For safety. :-) */ + if(max_open_files < 0x7000) { + pipe_handle_offset = 0x7000; + } else { + pipe_handle_offset = max_open_files + 10; /* For safety. :-) */ + } } /**************************************************************************** @@ -128,8 +129,9 @@ void reset_chain_p(void) void init_rpc_pipe_hnd(void) { bmap = bitmap_allocate(MAX_OPEN_PIPES); - if (!bmap) + if (!bmap) { exit_server("out of memory in init_rpc_pipe_hnd"); + } } /**************************************************************************** @@ -154,7 +156,7 @@ static BOOL pipe_init_outgoing_data(pipes_struct *p) * Initialize the outgoing RPC data buffer. * we will use this as the raw data area for replying to rpc requests. */ - if(!prs_init(&o_data->rdata, MAX_PDU_FRAG_LEN, p->mem_ctx, MARSHALL)) { + if(!prs_init(&o_data->rdata, RPC_MAX_PDU_FRAG_LEN, p->mem_ctx, MARSHALL)) { DEBUG(0,("pipe_init_outgoing_data: malloc fail.\n")); return False; } @@ -177,8 +179,9 @@ smb_np_struct *open_rpc_pipe_p(char *pipe_name, DEBUG(4,("Open pipe requested %s (pipes_open=%d)\n", pipe_name, pipes_open)); - if (strstr(pipe_name, "spoolss")) + if (strstr(pipe_name, "spoolss")) { is_spoolss_pipe = True; + } if (is_spoolss_pipe && current_spoolss_pipes_open >= MAX_OPEN_SPOOLSS_PIPES) { DEBUG(10,("open_rpc_pipe_p: spooler bug workaround. Denying open on pipe %s\n", @@ -189,8 +192,10 @@ smb_np_struct *open_rpc_pipe_p(char *pipe_name, /* not repeating pipe numbers makes it easier to track things in log files and prevents client bugs where pipe numbers are reused over connection restarts */ - if (next_pipe == 0) + + if (next_pipe == 0) { next_pipe = (sys_getpid() ^ time(NULL)) % MAX_OPEN_PIPES; + } i = bitmap_find(bmap, next_pipe); @@ -201,8 +206,9 @@ smb_np_struct *open_rpc_pipe_p(char *pipe_name, next_pipe = (i+1) % MAX_OPEN_PIPES; - for (p = Pipes; p; p = p->next) + for (p = Pipes; p; p = p->next) { DEBUG(5,("open_rpc_pipe_p: name %s pnum=%x\n", p->name, p->pnum)); + } p = SMB_MALLOC_P(smb_np_struct); if (!p) { @@ -259,8 +265,9 @@ smb_np_struct *open_rpc_pipe_p(char *pipe_name, chain_p = p; /* Iterate over p_it as a temp variable, to display all open pipes */ - for (p_it = Pipes; p_it; p_it = p_it->next) + for (p_it = Pipes; p_it; p_it = p_it->next) { DEBUG(5,("open pipes: name %s pnum=%x\n", p_it->name, p_it->pnum)); + } return chain_p; } @@ -297,9 +304,17 @@ static void *make_internal_rpc_pipe_p(char *pipe_name, return NULL; } + if ((p->pipe_state_mem_ctx = talloc_init("pipe_state %s %p", pipe_name, p)) == NULL) { + DEBUG(0,("open_rpc_pipe_p: talloc_init failed.\n")); + talloc_destroy(p->mem_ctx); + SAFE_FREE(p); + return NULL; + } + if (!init_pipe_handle_list(p, pipe_name)) { DEBUG(0,("open_rpc_pipe_p: init_pipe_handles failed.\n")); talloc_destroy(p->mem_ctx); + talloc_destroy(p->pipe_state_mem_ctx); SAFE_FREE(p); return NULL; } @@ -311,8 +326,10 @@ static void *make_internal_rpc_pipe_p(char *pipe_name, * change the type to UNMARSALLING before processing the stream. */ - if(!prs_init(&p->in_data.data, MAX_PDU_FRAG_LEN, p->mem_ctx, MARSHALL)) { + if(!prs_init(&p->in_data.data, RPC_MAX_PDU_FRAG_LEN, p->mem_ctx, MARSHALL)) { DEBUG(0,("open_rpc_pipe_p: malloc fail for in_data struct.\n")); + talloc_destroy(p->mem_ctx); + talloc_destroy(p->pipe_state_mem_ctx); return NULL; } @@ -325,12 +342,6 @@ static void *make_internal_rpc_pipe_p(char *pipe_name, p->vuid = vuid; - p->ntlmssp_chal_flags = 0; - p->ntlmssp_auth_validated = False; - p->ntlmssp_auth_requested = False; - - p->pipe_bound = False; - p->fault_state = False; p->endian = RPC_LITTLE_ENDIAN; ZERO_STRUCT(p->pipe_user); @@ -344,21 +355,6 @@ static void *make_internal_rpc_pipe_p(char *pipe_name, p->pipe_user.nt_user_token = dup_nt_token(vuser->nt_user_token); } - /* - * Initialize the incoming RPC struct. - */ - - p->in_data.pdu_needed_len = 0; - p->in_data.pdu_received_len = 0; - - /* - * Initialize the outgoing RPC struct. - */ - - p->out_data.current_pdu_len = 0; - p->out_data.current_pdu_sent = 0; - p->out_data.data_sent_length = 0; - /* * Initialize the outgoing RPC data buffer with no memory. */ @@ -504,7 +500,7 @@ static ssize_t unmarshall_rpc_header(pipes_struct *p) * Ensure that the pdu length is sane. */ - if((p->hdr.frag_len < RPC_HEADER_LEN) || (p->hdr.frag_len > MAX_PDU_FRAG_LEN)) { + if((p->hdr.frag_len < RPC_HEADER_LEN) || (p->hdr.frag_len > RPC_MAX_PDU_FRAG_LEN)) { DEBUG(0,("unmarshall_rpc_header: assert on frag length failed.\n")); set_incoming_fault(p); prs_mem_free(&rpc_in); @@ -514,18 +510,8 @@ static ssize_t unmarshall_rpc_header(pipes_struct *p) DEBUG(10,("unmarshall_rpc_header: type = %u, flags = %u\n", (unsigned int)p->hdr.pkt_type, (unsigned int)p->hdr.flags )); - /* - * Adjust for the header we just ate. - */ - p->in_data.pdu_received_len = 0; p->in_data.pdu_needed_len = (uint32)p->hdr.frag_len - RPC_HEADER_LEN; - /* - * Null the data we just ate. - */ - - memset((char *)&p->in_data.current_in_pdu[0], '\0', RPC_HEADER_LEN); - prs_mem_free(&rpc_in); return 0; /* No extra data processed. */ @@ -540,12 +526,13 @@ static void free_pipe_context(pipes_struct *p) { if (p->mem_ctx) { DEBUG(3,("free_pipe_context: destroying talloc pool of size " - "%llu\n", talloc_total_size(p->mem_ctx) )); + "%lu\n", (unsigned long)talloc_total_size(p->mem_ctx) )); talloc_free_children(p->mem_ctx); } else { p->mem_ctx = talloc_init("pipe %s %p", p->name, p); - if (p->mem_ctx == NULL) + if (p->mem_ctx == NULL) { p->fault_state = True; + } } } @@ -556,9 +543,9 @@ static void free_pipe_context(pipes_struct *p) static BOOL process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p) { - BOOL auth_verify = ((p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) != 0); + uint32 ss_padding_len = 0; size_t data_len = p->hdr.frag_len - RPC_HEADER_LEN - RPC_HDR_REQ_LEN - - (auth_verify ? RPC_HDR_AUTH_LEN : 0) - p->hdr.auth_len; + (p->hdr.auth_len ? RPC_HDR_AUTH_LEN : 0) - p->hdr.auth_len; if(!p->pipe_bound) { DEBUG(0,("process_request_pdu: rpc request with no bind.\n")); @@ -581,29 +568,40 @@ static BOOL process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p) return False; } - if(p->ntlmssp_auth_validated && !api_pipe_auth_process(p, rpc_in_p)) { - DEBUG(0,("process_request_pdu: failed to do auth processing.\n")); - set_incoming_fault(p); - return False; - } + switch(p->auth.auth_type) { + case PIPE_AUTH_TYPE_NONE: + break; - if (p->ntlmssp_auth_requested && !p->ntlmssp_auth_validated) { + case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: + case PIPE_AUTH_TYPE_NTLMSSP: + { + NTSTATUS status; + if(!api_pipe_ntlmssp_auth_process(p, rpc_in_p, &ss_padding_len, &status)) { + DEBUG(0,("process_request_pdu: failed to do auth processing.\n")); + DEBUG(0,("process_request_pdu: error was %s.\n", nt_errstr(status) )); + set_incoming_fault(p); + return False; + } + break; + } - /* - * Authentication _was_ requested and it already failed. - */ + case PIPE_AUTH_TYPE_SCHANNEL: + if (!api_pipe_schannel_process(p, rpc_in_p, &ss_padding_len)) { + DEBUG(3,("process_request_pdu: failed to do schannel processing.\n")); + set_incoming_fault(p); + return False; + } + break; - DEBUG(0,("process_request_pdu: RPC request received on pipe %s " - "where authentication failed. Denying the request.\n", - p->name)); - set_incoming_fault(p); - return False; + default: + DEBUG(0,("process_request_pdu: unknown auth type %u set.\n", (unsigned int)p->auth.auth_type )); + set_incoming_fault(p); + return False; } - if (p->netsec_auth_validated && !api_pipe_netsec_process(p, rpc_in_p)) { - DEBUG(3,("process_request_pdu: failed to do schannel processing.\n")); - set_incoming_fault(p); - return False; + /* Now we've done the sign/seal we can remove any padding data. */ + if (data_len > ss_padding_len) { + data_len -= ss_padding_len; } /* @@ -643,8 +641,7 @@ static BOOL process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p) * size as the current offset. */ - if(!prs_set_buffer_size(&p->in_data.data, prs_offset(&p->in_data.data))) - { + if(!prs_set_buffer_size(&p->in_data.data, prs_offset(&p->in_data.data))) { DEBUG(0,("process_request_pdu: Call to prs_set_buffer_size failed!\n")); set_incoming_fault(p); return False; @@ -664,8 +661,9 @@ static BOOL process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p) free_pipe_context(p); - if(pipe_init_outgoing_data(p)) + if(pipe_init_outgoing_data(p)) { ret = api_pipe_request(p); + } free_pipe_context(p); @@ -690,11 +688,11 @@ static BOOL process_request_pdu(pipes_struct *p, prs_struct *rpc_in_p) already been parsed and stored in p->hdr. ****************************************************************************/ -static ssize_t process_complete_pdu(pipes_struct *p) +static void process_complete_pdu(pipes_struct *p) { prs_struct rpc_in; - size_t data_len = p->in_data.pdu_received_len; - char *data_p = (char *)&p->in_data.current_in_pdu[0]; + size_t data_len = p->in_data.pdu_received_len - RPC_HEADER_LEN; + char *data_p = (char *)&p->in_data.current_in_pdu[RPC_HEADER_LEN]; BOOL reply = False; if(p->fault_state) { @@ -702,7 +700,7 @@ static ssize_t process_complete_pdu(pipes_struct *p) p->name )); set_incoming_fault(p); setup_fault_pdu(p, NT_STATUS(0x1c010002)); - return (ssize_t)data_len; + return; } prs_init( &rpc_in, 0, p->mem_ctx, UNMARSHALL); @@ -722,19 +720,28 @@ static ssize_t process_complete_pdu(pipes_struct *p) switch (p->hdr.pkt_type) { case RPC_BIND: - case RPC_ALTCONT: /* * We assume that a pipe bind is only in one pdu. */ - if(pipe_init_outgoing_data(p)) + if(pipe_init_outgoing_data(p)) { reply = api_pipe_bind_req(p, &rpc_in); + } + break; + case RPC_ALTCONT: + /* + * We assume that a pipe bind is only in one pdu. + */ + if(pipe_init_outgoing_data(p)) { + reply = api_pipe_alter_context(p, &rpc_in); + } break; - case RPC_BINDRESP: + case RPC_AUTH3: /* - * We assume that a pipe bind_resp is only in one pdu. + * The third packet in an NTLMSSP auth exchange. */ - if(pipe_init_outgoing_data(p)) - reply = api_pipe_bind_auth_resp(p, &rpc_in); + if(pipe_init_outgoing_data(p)) { + reply = api_pipe_bind_auth3(p, &rpc_in); + } break; case RPC_REQUEST: reply = process_request_pdu(p, &rpc_in); @@ -761,7 +768,6 @@ static ssize_t process_complete_pdu(pipes_struct *p) } prs_mem_free(&rpc_in); - return (ssize_t)data_len; } /**************************************************************************** @@ -770,8 +776,7 @@ static ssize_t process_complete_pdu(pipes_struct *p) static ssize_t process_incoming_data(pipes_struct *p, char *data, size_t n) { - size_t data_to_copy = MIN(n, MAX_PDU_FRAG_LEN - p->in_data.pdu_received_len); - size_t old_pdu_received_len = p->in_data.pdu_received_len; + size_t data_to_copy = MIN(n, RPC_MAX_PDU_FRAG_LEN - p->in_data.pdu_received_len); DEBUG(10,("process_incoming_data: Start: pdu_received_len = %u, pdu_needed_len = %u, incoming data = %u\n", (unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len, @@ -812,8 +817,9 @@ incoming data size = %u\n", (unsigned int)p->in_data.pdu_received_len, (unsigned * data we need, then loop again. */ - if(p->in_data.pdu_needed_len == 0) + if(p->in_data.pdu_needed_len == 0) { return unmarshall_rpc_header(p); + } /* * Ok - at this point we have a valid RPC_HEADER in p->hdr. @@ -824,24 +830,27 @@ incoming data size = %u\n", (unsigned int)p->in_data.pdu_received_len, (unsigned /* * Copy as much of the data as we need into the current_in_pdu buffer. + * pdu_needed_len becomes zero when we have a complete pdu. */ memcpy( (char *)&p->in_data.current_in_pdu[p->in_data.pdu_received_len], data, data_to_copy); p->in_data.pdu_received_len += data_to_copy; + p->in_data.pdu_needed_len -= data_to_copy; /* * Do we have a complete PDU ? - * (return the nym of bytes handled in the call) + * (return the number of bytes handled in the call) */ - if(p->in_data.pdu_received_len == p->in_data.pdu_needed_len) - return process_complete_pdu(p) - old_pdu_received_len; + if(p->in_data.pdu_needed_len == 0) { + process_complete_pdu(p); + return data_to_copy; + } DEBUG(10,("process_incoming_data: not a complete PDU yet. pdu_received_len = %u, pdu_needed_len = %u\n", (unsigned int)p->in_data.pdu_received_len, (unsigned int)p->in_data.pdu_needed_len )); return (ssize_t)data_to_copy; - } /**************************************************************************** @@ -878,8 +887,9 @@ static ssize_t write_to_internal_pipe(void *np_conn, char *data, size_t n) DEBUG(10,("write_to_pipe: data_used = %d\n", (int)data_used )); - if(data_used < 0) + if(data_used < 0) { return -1; + } data_left -= data_used; data += data_used; @@ -948,9 +958,9 @@ static ssize_t read_from_internal_pipe(void *np_conn, char *data, size_t n, * authentications failing. Just ignore it so things work. */ - if(n > MAX_PDU_FRAG_LEN) { + if(n > RPC_MAX_PDU_FRAG_LEN) { DEBUG(5,("read_from_pipe: too large read (%u) requested on \ -pipe %s. We can only service %d sized reads.\n", (unsigned int)n, p->name, MAX_PDU_FRAG_LEN )); +pipe %s. We can only service %d sized reads.\n", (unsigned int)n, p->name, RPC_MAX_PDU_FRAG_LEN )); } /* @@ -1019,8 +1029,9 @@ returning %d bytes.\n", p->name, (unsigned int)p->out_data.current_pdu_len, BOOL wait_rpc_pipe_hnd_state(smb_np_struct *p, uint16 priority) { - if (p == NULL) + if (p == NULL) { return False; + } if (p->open) { DEBUG(3,("wait_rpc_pipe_hnd_state: Setting pipe wait state priority=%x on pipe (name=%s)\n", @@ -1043,8 +1054,9 @@ BOOL wait_rpc_pipe_hnd_state(smb_np_struct *p, uint16 priority) BOOL set_rpc_pipe_hnd_state(smb_np_struct *p, uint16 device_state) { - if (p == NULL) + if (p == NULL) { return False; + } if (p->open) { DEBUG(3,("set_rpc_pipe_hnd_state: Setting pipe device state=%x on pipe (name=%s)\n", @@ -1121,9 +1133,18 @@ static BOOL close_internal_rpc_pipe_hnd(void *np_conn) prs_mem_free(&p->out_data.rdata); prs_mem_free(&p->in_data.data); - if (p->mem_ctx) + if (p->auth.auth_data_free_func) { + (*p->auth.auth_data_free_func)(&p->auth); + } + + if (p->mem_ctx) { talloc_destroy(p->mem_ctx); - + } + + if (p->pipe_state_mem_ctx) { + talloc_destroy(p->pipe_state_mem_ctx); + } + free_pipe_rpc_context( p->contexts ); /* Free the handles database. */ @@ -1152,8 +1173,9 @@ smb_np_struct *get_rpc_pipe_p(char *buf, int where) { int pnum = SVAL(buf,where); - if (chain_p) + if (chain_p) { return chain_p; + } return get_rpc_pipe(pnum); } @@ -1168,9 +1190,10 @@ smb_np_struct *get_rpc_pipe(int pnum) DEBUG(4,("search for pipe pnum=%x\n", pnum)); - for (p=Pipes;p;p=p->next) + for (p=Pipes;p;p=p->next) { DEBUG(5,("pipe name %s pnum=%x (pipes_open=%d)\n", p->name, p->pnum, pipes_open)); + } for (p=Pipes;p;p=p->next) { if (p->pnum == pnum) { diff --git a/source3/rpc_server/srv_reg.c b/source3/rpc_server/srv_reg.c index 871b1a9f121..17725240387 100644 --- a/source3/rpc_server/srv_reg.c +++ b/source3/rpc_server/srv_reg.c @@ -383,7 +383,7 @@ static BOOL api_reg_restore_key(pipes_struct *p) if(!reg_io_q_restore_key("", &q_u, data, 0)) return False; - + r_u.status = _reg_restore_key(p, &q_u, &r_u); if(!reg_io_r_restore_key("", &r_u, rdata, 0)) @@ -393,7 +393,7 @@ static BOOL api_reg_restore_key(pipes_struct *p) } /******************************************************************* - ******************************************************************/ + ********************************************************************/ static BOOL api_reg_save_key(pipes_struct *p) { @@ -416,6 +416,57 @@ static BOOL api_reg_save_key(pipes_struct *p) return True; } +/******************************************************************* + api_reg_open_hkpd + ********************************************************************/ + +static BOOL api_reg_open_hkpd(pipes_struct *p) +{ + REG_Q_OPEN_HIVE q_u; + REG_R_OPEN_HIVE r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + /* grab the reg open */ + if(!reg_io_q_open_hive("", &q_u, data, 0)) + return False; + + r_u.status = _reg_open_hkpd(p, &q_u, &r_u); + + if(!reg_io_r_open_hive("", &r_u, rdata, 0)) + return False; + + return True; +} + +/******************************************************************* + api_reg_open_hkpd + ********************************************************************/ +static BOOL api_reg_open_hkpt(pipes_struct *p) +{ + REG_Q_OPEN_HIVE q_u; + REG_R_OPEN_HIVE r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + /* grab the reg open */ + if(!reg_io_q_open_hive("", &q_u, data, 0)) + return False; + + r_u.status = _reg_open_hkpt(p, &q_u, &r_u); + + if(!reg_io_r_open_hive("", &r_u, rdata, 0)) + return False; + + return True; +} + /******************************************************************* ******************************************************************/ @@ -573,6 +624,8 @@ static struct api_struct api_reg_cmds[] = { "REG_OPEN_ENTRY" , REG_OPEN_ENTRY , api_reg_open_entry }, { "REG_OPEN_HKCR" , REG_OPEN_HKCR , api_reg_open_hkcr }, { "REG_OPEN_HKLM" , REG_OPEN_HKLM , api_reg_open_hklm }, + { "REG_OPEN_HKPD" , REG_OPEN_HKPD , api_reg_open_hkpd }, + { "REG_OPEN_HKPT" , REG_OPEN_HKPT , api_reg_open_hkpt }, { "REG_OPEN_HKU" , REG_OPEN_HKU , api_reg_open_hku }, { "REG_ENUM_KEY" , REG_ENUM_KEY , api_reg_enum_key }, { "REG_ENUM_VALUE" , REG_ENUM_VALUE , api_reg_enum_value }, diff --git a/source3/rpc_server/srv_reg_nt.c b/source3/rpc_server/srv_reg_nt.c index a405948864b..4db5ed0ed62 100644 --- a/source3/rpc_server/srv_reg_nt.c +++ b/source3/rpc_server/srv_reg_nt.c @@ -33,62 +33,9 @@ #define OUR_HANDLE(hnd) (((hnd)==NULL)?"NULL":(IVAL((hnd)->data5,4)==(uint32)sys_getpid()?"OURS":"OTHER")), \ ((unsigned int)IVAL((hnd)->data5,4)),((unsigned int)sys_getpid()) +static struct generic_mapping reg_generic_map = + { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL }; -static struct generic_mapping reg_generic_map = { REG_KEY_READ, REG_KEY_WRITE, REG_KEY_EXECUTE, REG_KEY_ALL }; - -/******************************************************************** -********************************************************************/ - -NTSTATUS registry_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token, - uint32 access_desired, uint32 *access_granted ) -{ - NTSTATUS result; - - if ( geteuid() == sec_initial_uid() ) { - DEBUG(5,("registry_access_check: access check bypassed for 'root'\n")); - *access_granted = REG_KEY_ALL; - return NT_STATUS_OK; - } - - se_map_generic( &access_desired, ®_generic_map ); - se_access_check( sec_desc, token, access_desired, access_granted, &result ); - - return result; -} - -/******************************************************************** -********************************************************************/ - -SEC_DESC* construct_registry_sd( TALLOC_CTX *ctx ) -{ - SEC_ACE ace[2]; - SEC_ACCESS mask; - size_t i = 0; - SEC_DESC *sd; - SEC_ACL *acl; - uint32 sd_size; - - /* basic access for Everyone */ - - init_sec_access(&mask, REG_KEY_READ ); - init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - - /* Full Access 'BUILTIN\Administrators' */ - - init_sec_access(&mask, REG_KEY_ALL ); - init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - - - /* create the security descriptor */ - - if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) ) - return NULL; - - if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) ) - return NULL; - - return sd; -} /****************************************************************** free() function for REGISTRY_KEY @@ -96,9 +43,7 @@ SEC_DESC* construct_registry_sd( TALLOC_CTX *ctx ) static void free_regkey_info(void *ptr) { - REGISTRY_KEY *info = (REGISTRY_KEY*)ptr; - - SAFE_FREE(info); + TALLOC_FREE( ptr ); } /****************************************************************** @@ -126,89 +71,38 @@ static REGISTRY_KEY *find_regkey_index_by_hnd(pipes_struct *p, POLICY_HND *hnd) HK[LM|U]\\\... *******************************************************************/ -static WERROR open_registry_key(pipes_struct *p, POLICY_HND *hnd, REGISTRY_KEY *parent, - const char *subkeyname, uint32 access_granted ) +static WERROR open_registry_key( pipes_struct *p, POLICY_HND *hnd, + REGISTRY_KEY **keyinfo, REGISTRY_KEY *parent, + const char *subkeyname, uint32 access_desired ) { - REGISTRY_KEY *regkey = NULL; + pstring keypath; + int path_len; WERROR result = WERR_OK; - REGSUBKEY_CTR *subkeys = NULL; - pstring subkeyname2; - int subkey_len; - - DEBUG(7,("open_registry_key: name = [%s][%s]\n", - parent ? parent->name : "NULL", subkeyname)); - - /* strip any trailing '\'s */ - pstrcpy( subkeyname2, subkeyname ); - subkey_len = strlen ( subkeyname2 ); - if ( subkey_len && subkeyname2[subkey_len-1] == '\\' ) - subkeyname2[subkey_len-1] = '\0'; - if ((regkey=SMB_MALLOC_P(REGISTRY_KEY)) == NULL) - return WERR_NOMEM; - - ZERO_STRUCTP( regkey ); - - /* - * very crazy, but regedit.exe on Win2k will attempt to call - * REG_OPEN_ENTRY with a keyname of "". We should return a new - * (second) handle here on the key->name. regedt32.exe does - * not do this stupidity. --jerry - */ - - if ( !subkey_len ) { - pstrcpy( regkey->name, parent->name ); - } - else { - pstrcpy( regkey->name, "" ); - if ( parent ) { - pstrcat( regkey->name, parent->name ); - pstrcat( regkey->name, "\\" ); - } - pstrcat( regkey->name, subkeyname2 ); - } + /* create a full registry path and strip any trailing '\' + characters */ + + pstr_sprintf( keypath, "%s%s%s", + parent ? parent->name : "", + parent ? "\\" : "", + subkeyname ); - /* Look up the table of registry I/O operations */ - - if ( !(regkey->hook = reghook_cache_find( regkey->name )) ) { - DEBUG(0,("open_registry_key: Failed to assigned a REGISTRY_HOOK to [%s]\n", - regkey->name )); - result = WERR_BADFILE; - goto done; - } + path_len = strlen( keypath ); + if ( path_len && keypath[path_len-1] == '\\' ) + keypath[path_len-1] = '\0'; - /* check if the path really exists; failed is indicated by -1 */ - /* if the subkey count failed, bail out */ - - if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) { - result = WERR_NOMEM; - goto done; - } - - if ( fetch_reg_keys( regkey, subkeys ) == -1 ) { - result = WERR_BADFILE; - goto done; - } + /* now do the internal open */ - if ( !create_policy_hnd( p, hnd, free_regkey_info, regkey ) ) { + result = regkey_open_internal( keyinfo, keypath, p->pipe_user.nt_user_token, access_desired ); + if ( !W_ERROR_IS_OK(result) ) + return result; + + if ( !create_policy_hnd( p, hnd, free_regkey_info, *keyinfo ) ) { result = WERR_BADFILE; - goto done; + TALLOC_FREE( *keyinfo ); } - /* save the access mask */ - - regkey->access_granted = access_granted; - -done: - /* clean up */ - - TALLOC_FREE( subkeys ); - - if ( ! NT_STATUS_IS_OK(result) ) - SAFE_FREE( regkey ); - DEBUG(7,("open_registry_key: exit\n")); - return result; } @@ -332,43 +226,39 @@ WERROR _reg_close(pipes_struct *p, REG_Q_CLOSE *q_u, REG_R_CLOSE *r_u) WERROR _reg_open_hklm(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u) { - SEC_DESC *sec_desc; - uint32 access_granted = 0; - NTSTATUS status; + REGISTRY_KEY *keyinfo; - /* perform access checks */ - /* top level keys are done here without passing through the REGISTRY_HOOK api */ + return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKLM, q_u->access ); +} + +/******************************************************************* + ********************************************************************/ + +WERROR _reg_open_hkpd(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u) +{ + REGISTRY_KEY *keyinfo; - if ( !(sec_desc = construct_registry_sd( p->mem_ctx )) ) - return WERR_NOMEM; - - status = registry_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted ); - if ( !NT_STATUS_IS_OK(status) ) - return ntstatus_to_werror( status ); - - return open_registry_key( p, &r_u->pol, NULL, KEY_HKLM, access_granted ); + return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKPD, q_u->access ); } /******************************************************************* ********************************************************************/ -WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u) +WERROR _reg_open_hkpt(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u) { - SEC_DESC *sec_desc; - uint32 access_granted = 0; - NTSTATUS status; + REGISTRY_KEY *keyinfo; - /* perform access checks */ - /* top level keys are done here without passing through the REGISTRY_HOOK api */ + return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKPT, q_u->access ); +} + +/******************************************************************* + ********************************************************************/ + +WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u) +{ + REGISTRY_KEY *keyinfo; - if ( !(sec_desc = construct_registry_sd( p->mem_ctx )) ) - return WERR_NOMEM; - - status = registry_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted ); - if ( !NT_STATUS_IS_OK(status) ) - return ntstatus_to_werror( status ); - - return open_registry_key( p, &r_u->pol, NULL, KEY_HKCR, access_granted ); + return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKCR, q_u->access ); } /******************************************************************* @@ -376,21 +266,9 @@ WERROR _reg_open_hkcr(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_ WERROR _reg_open_hku(pipes_struct *p, REG_Q_OPEN_HIVE *q_u, REG_R_OPEN_HIVE *r_u) { - SEC_DESC *sec_desc; - uint32 access_granted = 0; - NTSTATUS status; - - /* perform access checks */ - /* top level keys are done here without passing through the REGISTRY_HOOK api */ + REGISTRY_KEY *keyinfo; - if ( !(sec_desc = construct_registry_sd( p->mem_ctx )) ) - return WERR_NOMEM; - - status = registry_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted ); - if ( !NT_STATUS_IS_OK(status) ) - return ntstatus_to_werror( status ); - - return open_registry_key( p, &r_u->pol, NULL, KEY_HKU, access_granted ); + return open_registry_key( p, &r_u->pol, &keyinfo, NULL, KEY_HKU, q_u->access ); } /******************************************************************* @@ -401,9 +279,8 @@ WERROR _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTRY { fstring name; REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->pol); - REGISTRY_KEY *newkey; - uint32 access_granted; - WERROR result; + REGISTRY_KEY *newkey = NULL; + uint32 check_rights; if ( !parent ) return WERR_BADFID; @@ -412,29 +289,22 @@ WERROR _reg_open_entry(pipes_struct *p, REG_Q_OPEN_ENTRY *q_u, REG_R_OPEN_ENTRY /* check granted access first; what is the correct mask here? */ - if ( !(parent->access_granted & (SEC_RIGHTS_ENUM_SUBKEYS|SEC_RIGHTS_CREATE_SUBKEY|SEC_RIGHTS_QUERY_VALUE|SEC_RIGHTS_SET_VALUE)) ) + check_rights = ( SEC_RIGHTS_ENUM_SUBKEYS| + SEC_RIGHTS_CREATE_SUBKEY| + SEC_RIGHTS_QUERY_VALUE| + SEC_RIGHTS_SET_VALUE); + + if ( !(parent->access_granted & check_rights) ) return WERR_ACCESS_DENIED; - /* open the key first to get the appropriate REGISTRY_HOOK - and then check the premissions */ - - if ( !W_ERROR_IS_OK(result = open_registry_key( p, &r_u->handle, parent, name, 0 )) ) - return result; - - newkey = find_regkey_index_by_hnd(p, &r_u->handle); - - /* finally allow the backend to check the access for the requested key */ - - if ( !regkey_access_check( newkey, q_u->access, &access_granted, p->pipe_user.nt_user_token ) ) { - close_registry_key( p, &r_u->handle ); - return WERR_ACCESS_DENIED; - } - - /* if successful, save the granted access mask */ - - newkey->access_granted = access_granted; - - return WERR_OK; + /* + * very crazy, but regedit.exe on Win2k will attempt to call + * REG_OPEN_ENTRY with a keyname of "". We should return a new + * (second) handle here on the key->name. regedt32.exe does + * not do this stupidity. --jerry + */ + + return open_registry_key( p, &r_u->handle, &newkey, parent, name, q_u->access ); } /******************************************************************* @@ -454,16 +324,93 @@ WERROR _reg_query_value(pipes_struct *p, REG_Q_QUERY_VALUE *q_u, REG_R_QUERY_VAL return WERR_BADFID; DEBUG(7,("_reg_info: policy key name = [%s]\n", regkey->name)); + DEBUG(7,("_reg_info: policy key type = [%08x]\n", regkey->type)); rpcstr_pull(name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0); - DEBUG(5,("reg_info: looking up value: [%s]\n", name)); + DEBUG(5,("_reg_info: looking up value: [%s]\n", name)); if ( !(regvals = TALLOC_P( p->mem_ctx, REGVAL_CTR )) ) return WERR_NOMEM; - for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ ) + /* Handle QueryValue calls on HKEY_PERFORMANCE_DATA */ + if(regkey->type == REG_KEY_HKPD) + { + if(strequal(name, "Global")) + { + uint32 outbuf_len; + prs_struct prs_hkpd; + prs_init(&prs_hkpd, q_u->bufsize, p->mem_ctx, MARSHALL); + status = reg_perfcount_get_hkpd(&prs_hkpd, q_u->bufsize, &outbuf_len, NULL); + regval_ctr_addvalue(regvals, "HKPD", REG_BINARY, + prs_hkpd.data_p, outbuf_len); + val = dup_registry_value(regval_ctr_specific_value(regvals, 0)); + prs_mem_free(&prs_hkpd); + } + else if(strequal(name, "Counter 009")) + { + uint32 base_index; + uint32 buffer_size; + char *buffer; + + buffer = NULL; + base_index = reg_perfcount_get_base_index(); + buffer_size = reg_perfcount_get_counter_names(base_index, &buffer); + regval_ctr_addvalue(regvals, "Counter 009", + REG_MULTI_SZ, buffer, buffer_size); + + val = dup_registry_value(regval_ctr_specific_value(regvals, 0)); + + if(buffer_size > 0) + { + SAFE_FREE(buffer); + status = WERR_OK; + } + } + else if(strequal(name, "Explain 009")) + { + uint32 base_index; + uint32 buffer_size; + char *buffer; + + buffer = NULL; + base_index = reg_perfcount_get_base_index(); + buffer_size = reg_perfcount_get_counter_help(base_index, &buffer); + regval_ctr_addvalue(regvals, "Explain 009", + REG_MULTI_SZ, buffer, buffer_size); + + val = dup_registry_value(regval_ctr_specific_value(regvals, 0)); + + if(buffer_size > 0) + { + SAFE_FREE(buffer); + status = WERR_OK; + } + } + else if(isdigit(name[0])) + { + /* we probably have a request for a specific object here */ + uint32 outbuf_len; + prs_struct prs_hkpd; + prs_init(&prs_hkpd, q_u->bufsize, p->mem_ctx, MARSHALL); + status = reg_perfcount_get_hkpd(&prs_hkpd, q_u->bufsize, &outbuf_len, name); + regval_ctr_addvalue(regvals, "HKPD", REG_BINARY, + prs_hkpd.data_p, outbuf_len); + + val = dup_registry_value(regval_ctr_specific_value(regvals, 0)); + prs_mem_free(&prs_hkpd); + } + else + { + DEBUG(3,("Unsupported key name [%s] for HKPD.\n", name)); + return WERR_BADFILE; + } + } + /* HKPT calls can be handled out of reg_dynamic.c with the hkpt_params handler */ + else { + for ( i=0; fetch_reg_values_specific(regkey, &val, i); i++ ) + { DEBUG(10,("_reg_info: Testing value [%s]\n", val->valuename)); if ( strequal( val->valuename, name ) ) { DEBUG(10,("_reg_info: Found match for value [%s]\n", name)); @@ -472,6 +419,7 @@ WERROR _reg_query_value(pipes_struct *p, REG_Q_QUERY_VALUE *q_u, REG_R_QUERY_VAL } free_registry_value( val ); + } } init_reg_r_query_value(q_u->ptr_buf, r_u, val, status); @@ -482,7 +430,6 @@ WERROR _reg_query_value(pipes_struct *p, REG_Q_QUERY_VALUE *q_u, REG_R_QUERY_VAL return status; } - /***************************************************************************** Implementation of REG_QUERY_KEY ****************************************************************************/ @@ -998,7 +945,7 @@ static WERROR make_default_reg_sd( TALLOC_CTX *ctx, SEC_DESC **psd ) SEC_ACE ace[2]; /* at most 2 entries */ SEC_ACCESS mask; SEC_ACL *psa = NULL; - uint32 sd_size; + size_t sd_size; /* set the owner to BUILTIN\Administrator */ @@ -1092,7 +1039,7 @@ WERROR _reg_save_key(pipes_struct *p, REG_Q_SAVE_KEY *q_u, REG_R_SAVE_KEY *r_u) WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREATE_KEY_EX *r_u) { REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle); - REGISTRY_KEY *newparent; + REGISTRY_KEY *newparentinfo, *keyinfo; POLICY_HND newparent_handle; REGSUBKEY_CTR *subkeys; BOOL write_result; @@ -1109,7 +1056,6 @@ WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREAT if ( strrchr( name, '\\' ) ) { pstring newkeyname; char *ptr; - uint32 access_granted; /* (1) check for enumerate rights on the parent handle. CLients can try create things like 'SOFTWARE\Samba' on the HKLM handle. @@ -1122,19 +1068,11 @@ WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREAT ptr = strrchr( newkeyname, '\\' ); *ptr = '\0'; - result = open_registry_key( p, &newparent_handle, parent, newkeyname, 0 ); + result = open_registry_key( p, &newparent_handle, &newparentinfo, + parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) ); + if ( !W_ERROR_IS_OK(result) ) return result; - - newparent = find_regkey_index_by_hnd(p, &newparent_handle); - SMB_ASSERT( newparent != NULL ); - - if ( !regkey_access_check( newparent, REG_KEY_READ|REG_KEY_WRITE, &access_granted, p->pipe_user.nt_user_token ) ) { - result = WERR_ACCESS_DENIED; - goto done; - } - - newparent->access_granted = access_granted; /* copy the new key name (just the lower most keyname) */ @@ -1142,13 +1080,13 @@ WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREAT } else { /* use the existing open key information */ - newparent = parent; + newparentinfo = parent; memcpy( &newparent_handle, &q_u->handle, sizeof(POLICY_HND) ); } /* (3) check for create subkey rights on the correct parent */ - if ( !(newparent->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) { + if ( !(newparentinfo->access_granted & SEC_RIGHTS_CREATE_SUBKEY) ) { result = WERR_ACCESS_DENIED; goto done; } @@ -1160,12 +1098,12 @@ WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREAT /* (4) lookup the current keys and add the new one */ - fetch_reg_keys( newparent, subkeys ); + fetch_reg_keys( newparentinfo, subkeys ); regsubkey_ctr_addkey( subkeys, name ); /* now write to the registry backend */ - write_result = store_reg_keys( newparent, subkeys ); + write_result = store_reg_keys( newparentinfo, subkeys ); TALLOC_FREE( subkeys ); @@ -1173,16 +1111,15 @@ WERROR _reg_create_key_ex(pipes_struct *p, REG_Q_CREATE_KEY_EX *q_u, REG_R_CREAT return WERR_REG_IO_FAILURE; /* (5) open the new key and return the handle. Note that it is probably - not correct to grant full access on this open handle. We should pass - the new open through the regkey_access_check() like we do for - _reg_open_entry() but this is ok for now. */ + not correct to grant full access on this open handle. */ - result = open_registry_key( p, &r_u->handle, newparent, name, REG_KEY_ALL ); + result = open_registry_key( p, &r_u->handle, &keyinfo, newparentinfo, name, REG_KEY_READ ); + keyinfo->access_granted = REG_KEY_ALL; done: /* close any intermediate key handles */ - if ( newparent != parent ) + if ( newparentinfo != parent ) close_registry_key( p, &newparent_handle ); return result; @@ -1243,7 +1180,7 @@ WERROR _reg_set_value(pipes_struct *p, REG_Q_SET_VALUE *q_u, REG_R_SET_VALUE *r WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY *q_u, REG_R_DELETE_KEY *r_u) { REGISTRY_KEY *parent = find_regkey_index_by_hnd(p, &q_u->handle); - REGISTRY_KEY *newparent; + REGISTRY_KEY *newparentinfo; POLICY_HND newparent_handle; REGSUBKEY_CTR *subkeys; BOOL write_result; @@ -1252,6 +1189,15 @@ WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY *q_u, REG_R_DELETE_KEY if ( !parent ) return WERR_BADFID; + + /* MSDN says parent the handle must have been opened with DELETE access */ + + /* (1) check for delete rights on the parent */ + + if ( !(parent->access_granted & STD_RIGHT_DELETE_ACCESS) ) { + result = WERR_ACCESS_DENIED; + goto done; + } rpcstr_pull( name, q_u->name.string->buffer, sizeof(name), q_u->name.string->uni_str_len*2, 0 ); @@ -1260,50 +1206,24 @@ WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY *q_u, REG_R_DELETE_KEY if ( strrchr( name, '\\' ) ) { pstring newkeyname; char *ptr; - uint32 access_granted; - /* (1) check for enumerate rights on the parent handle. CLients can try - create things like 'SOFTWARE\Samba' on the HKLM handle. - (2) open the path to the child parent key if necessary */ + /* (2) open the path to the child parent key if necessary */ + /* split the registry path and save the subkeyname */ - if ( !(parent->access_granted & SEC_RIGHTS_ENUM_SUBKEYS) ) - return WERR_ACCESS_DENIED; - pstrcpy( newkeyname, name ); ptr = strrchr( newkeyname, '\\' ); *ptr = '\0'; + pstrcpy( name, ptr+1 ); - result = open_registry_key( p, &newparent_handle, parent, newkeyname, 0 ); + result = open_registry_key( p, &newparent_handle, &newparentinfo, parent, newkeyname, (REG_KEY_READ|REG_KEY_WRITE) ); if ( !W_ERROR_IS_OK(result) ) return result; - - newparent = find_regkey_index_by_hnd(p, &newparent_handle); - SMB_ASSERT( newparent != NULL ); - - if ( !regkey_access_check( newparent, REG_KEY_READ|REG_KEY_WRITE, &access_granted, p->pipe_user.nt_user_token ) ) { - result = WERR_ACCESS_DENIED; - goto done; - } - - newparent->access_granted = access_granted; - - /* copy the new key name (just the lower most keyname) */ - - pstrcpy( name, ptr+1 ); } else { /* use the existing open key information */ - newparent = parent; - memcpy( &newparent_handle, &q_u->handle, sizeof(POLICY_HND) ); + newparentinfo = parent; } - /* (3) check for create subkey rights on the correct parent */ - - if ( !(newparent->access_granted & STD_RIGHT_DELETE_ACCESS) ) { - result = WERR_ACCESS_DENIED; - goto done; - } - if ( !(subkeys = TALLOC_ZERO_P( p->mem_ctx, REGSUBKEY_CTR )) ) { result = WERR_NOMEM; goto done; @@ -1311,13 +1231,13 @@ WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY *q_u, REG_R_DELETE_KEY /* lookup the current keys and delete the new one */ - fetch_reg_keys( newparent, subkeys ); + fetch_reg_keys( newparentinfo, subkeys ); regsubkey_ctr_delkey( subkeys, name ); /* now write to the registry backend */ - write_result = store_reg_keys( newparent, subkeys ); + write_result = store_reg_keys( newparentinfo, subkeys ); TALLOC_FREE( subkeys ); @@ -1326,7 +1246,7 @@ WERROR _reg_delete_key(pipes_struct *p, REG_Q_DELETE_KEY *q_u, REG_R_DELETE_KEY done: /* close any intermediate key handles */ - if ( newparent != parent ) + if ( newparentinfo != parent ) close_registry_key( p, &newparent_handle ); return result; @@ -1414,5 +1334,3 @@ WERROR _reg_set_key_sec(pipes_struct *p, REG_Q_SET_KEY_SEC *q_u, REG_R_SET_KEY_ return WERR_ACCESS_DENIED; } - - diff --git a/source3/rpc_server/srv_samr_nt.c b/source3/rpc_server/srv_samr_nt.c index 656241a73f9..b69f03a3a28 100644 --- a/source3/rpc_server/srv_samr_nt.c +++ b/source3/rpc_server/srv_samr_nt.c @@ -6,7 +6,7 @@ * Copyright (C) Paul Ashton 1997, * Copyright (C) Marc Jacobsen 1999, * Copyright (C) Jeremy Allison 2001-2002, - * Copyright (C) Jean François Micouleau 1998-2001, + * Copyright (C) Jean François Micouleau 1998-2001, * Copyright (C) Jim McDonough 2002, * Copyright (C) Gerald (Jerry) Carter 2003-2004, * Copyright (C) Simo Sorce 2003. @@ -88,17 +88,17 @@ static NTSTATUS make_samr_object_sd( TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd SEC_ACL *psa = NULL; /* basic access for Everyone */ - + init_sec_access(&mask, map->generic_execute | map->generic_read ); init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - + /* add Full Access 'BUILTIN\Administrators' and 'BUILTIN\Account Operators */ - + init_sec_access(&mask, map->generic_all); init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); init_sec_ace(&ace[i++], &global_sid_Builtin_Account_Operators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - + /* Add Full Access for Domain Admins if we are a DC */ if ( IS_DC ) { @@ -108,14 +108,14 @@ static NTSTATUS make_samr_object_sd( TALLOC_CTX *ctx, SEC_DESC **psd, size_t *sd } /* if we have a sid, give it some special access */ - + if ( sid ) { init_sec_access( &mask, sid_access ); init_sec_ace(&ace[i++], sid, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - } - +} + /* create the security descriptor */ - + if ((psa = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) == NULL) return NT_STATUS_NO_MEMORY; @@ -347,7 +347,7 @@ NTSTATUS _samr_open_domain(pipes_struct *p, SAMR_Q_OPEN_DOMAIN *q_u, SAMR_R_OPEN uint32 acc_granted; uint32 des_access = q_u->flags; NTSTATUS status; - size_t sd_size; + size_t sd_size; SE_PRIV se_rights; r_u->status = NT_STATUS_OK; @@ -421,7 +421,6 @@ NTSTATUS _samr_get_usrdom_pwinfo(pipes_struct *p, SAMR_Q_GET_USRDOM_PWINFO *q_u, return r_u->status; } - /******************************************************************* _samr_set_sec_obj ********************************************************************/ @@ -1456,11 +1455,13 @@ static NTSTATUS get_user_info_18(pipes_struct *p, TALLOC_CTX *mem_ctx, SAM_USER_ BOOL ret; NTSTATUS nt_status; - if (!p->ntlmssp_auth_validated) + if (p->auth.auth_type != PIPE_AUTH_TYPE_NTLMSSP || p->auth.auth_type != PIPE_AUTH_TYPE_SPNEGO_NTLMSSP) { return NT_STATUS_ACCESS_DENIED; + } - if (!(p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SIGN) || !(p->ntlmssp_chal_flags & NTLMSSP_NEGOTIATE_SEAL)) + if (p->auth.auth_level != PIPE_AUTH_LEVEL_PRIVACY) { return NT_STATUS_ACCESS_DENIED; + } /* * Do *NOT* do become_root()/unbecome_root() here ! JRA. @@ -1794,11 +1795,12 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA time_t u_lock_duration, u_reset_time; NTTIME nt_lock_duration, nt_reset_time; uint32 lockout; - time_t u_logout; NTTIME nt_logout; uint32 account_policy_temp; + + time_t seq_num; uint32 server_role; uint32 num_users=0, num_groups=0, num_aliases=0; @@ -1819,19 +1821,19 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA switch (q_u->switch_value) { case 0x01: - account_policy_get(AP_MIN_PASSWORD_LEN, &account_policy_temp); + pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp); min_pass_len = account_policy_temp; - account_policy_get(AP_PASSWORD_HISTORY, &account_policy_temp); + pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp); pass_hist = account_policy_temp; - account_policy_get(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp); + pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp); flag = account_policy_temp; - account_policy_get(AP_MAX_PASSWORD_AGE, &account_policy_temp); + pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp); u_expire = account_policy_temp; - account_policy_get(AP_MIN_PASSWORD_AGE, &account_policy_temp); + pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp); u_min_age = account_policy_temp; unix_to_nt_time_abs(&nt_expire, u_expire); @@ -1847,21 +1849,23 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA num_groups=count_sam_groups(&info->disp_info); unbecome_root(); - account_policy_get(AP_TIME_TO_LOGOUT, &account_policy_temp); + pdb_get_account_policy(AP_TIME_TO_LOGOUT, &account_policy_temp); u_logout = account_policy_temp; unix_to_nt_time_abs(&nt_logout, u_logout); + if (!pdb_get_seq_num(&seq_num)) + seq_num = time(NULL); + server_role = ROLE_DOMAIN_PDC; if (lp_server_role() == ROLE_DOMAIN_BDC) server_role = ROLE_DOMAIN_BDC; - /* The time call below is to get a sequence number for the sam. FIXME !!! JRA. */ - init_unk_info2(&ctr->info.inf2, lp_serverstring(), lp_workgroup(), global_myname(), time(NULL), + init_unk_info2(&ctr->info.inf2, lp_serverstring(), lp_workgroup(), global_myname(), seq_num, num_users, num_groups, num_aliases, nt_logout, server_role); break; case 0x03: - account_policy_get(AP_TIME_TO_LOGOUT, (unsigned int *)&u_logout); + pdb_get_account_policy(AP_TIME_TO_LOGOUT, (unsigned int *)&u_logout); unix_to_nt_time_abs(&nt_logout, u_logout); init_unk_info3(&ctr->info.inf3, nt_logout); @@ -1880,18 +1884,21 @@ NTSTATUS _samr_query_dom_info(pipes_struct *p, SAMR_Q_QUERY_DOMAIN_INFO *q_u, SA init_unk_info7(&ctr->info.inf7, server_role); break; case 0x08: - init_unk_info8(&ctr->info.inf8, (uint32) time(NULL)); + if (!pdb_get_seq_num(&seq_num)) + seq_num = time(NULL); + + init_unk_info8(&ctr->info.inf8, (uint32) seq_num); break; case 0x0c: - account_policy_get(AP_LOCK_ACCOUNT_DURATION, &account_policy_temp); + pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &account_policy_temp); u_lock_duration = account_policy_temp; if (u_lock_duration != -1) u_lock_duration *= 60; - account_policy_get(AP_RESET_COUNT_TIME, &account_policy_temp); + pdb_get_account_policy(AP_RESET_COUNT_TIME, &account_policy_temp); u_reset_time = account_policy_temp * 60; - account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_temp); + pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_temp); lockout = account_policy_temp; unix_to_nt_time_abs(&nt_lock_duration, u_lock_duration); @@ -1955,7 +1962,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA rpcstr_pull(account, user_account.buffer, sizeof(account), user_account.uni_str_len*2, 0); strlower_m(account); - + pdb_init_sam(&sam_pass); become_root(); @@ -1968,7 +1975,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA } pdb_free_sam(&sam_pass); - + /********************************************************************* * HEADS UP! If we have to create a new user account, we have to get * a new RID from somewhere. This used to be done by the passdb @@ -1979,7 +1986,7 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA * of what ever passdb backend people may use. * --jerry (2003-07-10) *********************************************************************/ - + pw = Get_Pwnam(account); /* determine which user right we need to check based on the acb_info */ @@ -2005,27 +2012,27 @@ NTSTATUS _samr_create_user(pipes_struct *p, SAMR_Q_CREATE_USER *q_u, SAMR_R_CREA /* only Domain Admins can add a BDC or domain trust */ se_priv_copy( &se_rights, &se_priv_none ); can_add_account = nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ); - } } - + } + DEBUG(5, ("_samr_create_user: %s can add this account : %s\n", p->pipe_user_name, can_add_account ? "True":"False" )); /********** BEGIN Admin BLOCK **********/ - + if ( can_add_account ) become_root(); - + if ( !pw ) { if (*add_script) { - int add_ret; - - all_string_sub(add_script, "%u", account, sizeof(add_script)); - add_ret = smbrun(add_script,NULL); - DEBUG(add_ret ? 0 : 3,("_samr_create_user: Running the command `%s' gave %d\n", add_script, add_ret)); - } + int add_ret; + + all_string_sub(add_script, "%u", account, sizeof(add_script)); + add_ret = smbrun(add_script,NULL); + DEBUG(add_ret ? 0 : 3,("_samr_create_user: Running the command `%s' gave %d\n", add_script, add_ret)); + } } - + /* implicit call to getpwnam() next. we have a valid SID coming out of this call */ flush_pwnam_cache(); @@ -2147,7 +2154,7 @@ NTSTATUS _samr_connect(pipes_struct *p, SAMR_Q_CONNECT *q_u, SAMR_R_CONNECT *r_u uint32 acc_granted; uint32 des_access = q_u->access_mask; NTSTATUS nt_status; - size_t sd_size; + size_t sd_size; DEBUG(5,("_samr_connect: %d\n", __LINE__)); @@ -2198,7 +2205,7 @@ NTSTATUS _samr_connect4(pipes_struct *p, SAMR_Q_CONNECT4 *q_u, SAMR_R_CONNECT4 * uint32 acc_granted; uint32 des_access = q_u->access_mask; NTSTATUS nt_status; - size_t sd_size; + size_t sd_size; DEBUG(5,("_samr_connect4: %d\n", __LINE__)); @@ -2734,7 +2741,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE if (!NT_STATUS_IS_OK(r_u->status = access_check_samr_function(acc_granted, acc_required, "_samr_set_userinfo"))) { return r_u->status; } - + DEBUG(5, ("_samr_set_userinfo: sid:%s, level:%d\n", sid_string_static(&sid), switch_value)); if (ctr == NULL) { @@ -2765,7 +2772,7 @@ NTSTATUS _samr_set_userinfo(pipes_struct *p, SAMR_Q_SET_USERINFO *q_u, SAMR_R_SE if ( lp_enable_privileges() ) has_enough_rights = nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ); } - + DEBUG(5, ("_samr_set_userinfo: %s does%s possess sufficient rights\n", p->pipe_user_name, has_enough_rights ? "" : " not")); @@ -2905,7 +2912,7 @@ NTSTATUS _samr_set_userinfo2(pipes_struct *p, SAMR_Q_SET_USERINFO2 *q_u, SAMR_R_ if ( lp_enable_privileges() ) has_enough_rights = nt_token_check_domain_rid( p->pipe_user.nt_user_token, DOMAIN_GROUP_RID_ADMINS ); } - + DEBUG(5, ("_samr_set_userinfo: %s does%s possess sufficient rights\n", p->pipe_user_name, has_enough_rights ? "" : " not")); @@ -3597,7 +3604,7 @@ NTSTATUS _samr_delete_dom_group(pipes_struct *p, SAMR_Q_DELETE_DOM_GROUP *q_u, S gid=map.gid; /* check if group really exists */ - if ( (grp=getgrgid(gid)) == NULL) + if ( (grp=getgrgid(gid)) == NULL) return NT_STATUS_NO_SUCH_GROUP; se_priv_copy( &se_rights, &se_add_users ); @@ -4195,6 +4202,8 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW uint32 num_users=0, num_groups=0, num_aliases=0; uint32 account_policy_temp; + + time_t seq_num; uint32 server_role; if ((ctr = TALLOC_ZERO_P(p->mem_ctx, SAM_UNK_CTR)) == NULL) @@ -4212,19 +4221,19 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW switch (q_u->switch_value) { case 0x01: - account_policy_get(AP_MIN_PASSWORD_LEN, &account_policy_temp); + pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &account_policy_temp); min_pass_len = account_policy_temp; - account_policy_get(AP_PASSWORD_HISTORY, &account_policy_temp); + pdb_get_account_policy(AP_PASSWORD_HISTORY, &account_policy_temp); pass_hist = account_policy_temp; - account_policy_get(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp); + pdb_get_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, &account_policy_temp); flag = account_policy_temp; - account_policy_get(AP_MAX_PASSWORD_AGE, &account_policy_temp); + pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &account_policy_temp); u_expire = account_policy_temp; - account_policy_get(AP_MIN_PASSWORD_AGE, &account_policy_temp); + pdb_get_account_policy(AP_MIN_PASSWORD_AGE, &account_policy_temp); u_min_age = account_policy_temp; unix_to_nt_time_abs(&nt_expire, u_expire); @@ -4242,21 +4251,23 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW free_samr_db(info); - account_policy_get(AP_TIME_TO_LOGOUT, &account_policy_temp); + pdb_get_account_policy(AP_TIME_TO_LOGOUT, &account_policy_temp); u_logout = account_policy_temp; unix_to_nt_time_abs(&nt_logout, u_logout); + if (!pdb_get_seq_num(&seq_num)) + seq_num = time(NULL); + server_role = ROLE_DOMAIN_PDC; if (lp_server_role() == ROLE_DOMAIN_BDC) server_role = ROLE_DOMAIN_BDC; - /* The time call below is to get a sequence number for the sam. FIXME !!! JRA. */ - init_unk_info2(&ctr->info.inf2, lp_serverstring(), lp_workgroup(), global_myname(), time(NULL), + init_unk_info2(&ctr->info.inf2, lp_serverstring(), lp_workgroup(), global_myname(), seq_num, num_users, num_groups, num_aliases, nt_logout, server_role); break; case 0x03: - account_policy_get(AP_TIME_TO_LOGOUT, &account_policy_temp); + pdb_get_account_policy(AP_TIME_TO_LOGOUT, &account_policy_temp); u_logout = account_policy_temp; unix_to_nt_time_abs(&nt_logout, u_logout); @@ -4273,21 +4284,25 @@ NTSTATUS _samr_unknown_2e(pipes_struct *p, SAMR_Q_UNKNOWN_2E *q_u, SAMR_R_UNKNOW server_role = ROLE_DOMAIN_PDC; if (lp_server_role() == ROLE_DOMAIN_BDC) server_role = ROLE_DOMAIN_BDC; + init_unk_info7(&ctr->info.inf7, server_role); break; case 0x08: - init_unk_info8(&ctr->info.inf8, (uint32) time(NULL)); + if (!pdb_get_seq_num(&seq_num)) + seq_num = time(NULL); + + init_unk_info8(&ctr->info.inf8, (uint32) seq_num); break; case 0x0c: - account_policy_get(AP_LOCK_ACCOUNT_DURATION, &account_policy_temp); + pdb_get_account_policy(AP_LOCK_ACCOUNT_DURATION, &account_policy_temp); u_lock_duration = account_policy_temp; if (u_lock_duration != -1) u_lock_duration *= 60; - account_policy_get(AP_RESET_COUNT_TIME, &account_policy_temp); + pdb_get_account_policy(AP_RESET_COUNT_TIME, &account_policy_temp); u_reset_time = account_policy_temp * 60; - account_policy_get(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_temp); + pdb_get_account_policy(AP_BAD_ATTEMPT_LOCKOUT, &account_policy_temp); lockout = account_policy_temp; unix_to_nt_time_abs(&nt_lock_duration, u_lock_duration); @@ -4331,17 +4346,17 @@ NTSTATUS _samr_set_dom_info(pipes_struct *p, SAMR_Q_SET_DOMAIN_INFO *q_u, SAMR_R u_expire=nt_time_to_unix_abs(&q_u->ctr->info.inf1.expire); u_min_age=nt_time_to_unix_abs(&q_u->ctr->info.inf1.min_passwordage); - account_policy_set(AP_MIN_PASSWORD_LEN, (uint32)q_u->ctr->info.inf1.min_length_password); - account_policy_set(AP_PASSWORD_HISTORY, (uint32)q_u->ctr->info.inf1.password_history); - account_policy_set(AP_USER_MUST_LOGON_TO_CHG_PASS, (uint32)q_u->ctr->info.inf1.flag); - account_policy_set(AP_MAX_PASSWORD_AGE, (int)u_expire); - account_policy_set(AP_MIN_PASSWORD_AGE, (int)u_min_age); + pdb_set_account_policy(AP_MIN_PASSWORD_LEN, (uint32)q_u->ctr->info.inf1.min_length_password); + pdb_set_account_policy(AP_PASSWORD_HISTORY, (uint32)q_u->ctr->info.inf1.password_history); + pdb_set_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, (uint32)q_u->ctr->info.inf1.flag); + pdb_set_account_policy(AP_MAX_PASSWORD_AGE, (int)u_expire); + pdb_set_account_policy(AP_MIN_PASSWORD_AGE, (int)u_min_age); break; case 0x02: break; case 0x03: u_logout=nt_time_to_unix_abs(&q_u->ctr->info.inf3.logout); - account_policy_set(AP_TIME_TO_LOGOUT, (int)u_logout); + pdb_set_account_policy(AP_TIME_TO_LOGOUT, (int)u_logout); break; case 0x05: break; @@ -4356,9 +4371,9 @@ NTSTATUS _samr_set_dom_info(pipes_struct *p, SAMR_Q_SET_DOMAIN_INFO *q_u, SAMR_R u_reset_time=nt_time_to_unix_abs(&q_u->ctr->info.inf12.reset_count)/60; - account_policy_set(AP_LOCK_ACCOUNT_DURATION, (int)u_lock_duration); - account_policy_set(AP_RESET_COUNT_TIME, (int)u_reset_time); - account_policy_set(AP_BAD_ATTEMPT_LOCKOUT, (uint32)q_u->ctr->info.inf12.bad_attempt_lockout); + pdb_set_account_policy(AP_LOCK_ACCOUNT_DURATION, (int)u_lock_duration); + pdb_set_account_policy(AP_RESET_COUNT_TIME, (int)u_reset_time); + pdb_set_account_policy(AP_BAD_ATTEMPT_LOCKOUT, (uint32)q_u->ctr->info.inf12.bad_attempt_lockout); break; default: return NT_STATUS_INVALID_INFO_CLASS; diff --git a/source3/rpc_server/srv_samr_util.c b/source3/rpc_server/srv_samr_util.c index 24869d5d2bd..1d9a8ecd1db 100644 --- a/source3/rpc_server/srv_samr_util.c +++ b/source3/rpc_server/srv_samr_util.c @@ -291,7 +291,7 @@ void copy_id21_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_21 *from) uint32 expire; time_t new_time; if (pdb_get_pass_must_change_time(to) == 0) { - if (!account_policy_get(AP_MAX_PASSWORD_AGE, &expire) + if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire) || expire == (uint32)-1) { new_time = get_time_t_max(); } else { @@ -531,7 +531,7 @@ void copy_id23_to_sam_passwd(SAM_ACCOUNT *to, SAM_USER_INFO_23 *from) uint32 expire; time_t new_time; if (pdb_get_pass_must_change_time(to) == 0) { - if (!account_policy_get(AP_MAX_PASSWORD_AGE, &expire) + if (!pdb_get_account_policy(AP_MAX_PASSWORD_AGE, &expire) || expire == (uint32)-1) { new_time = get_time_t_max(); } else { diff --git a/source3/rpc_server/srv_spoolss_nt.c b/source3/rpc_server/srv_spoolss_nt.c index cda3f26137c..5233d6c252d 100644 --- a/source3/rpc_server/srv_spoolss_nt.c +++ b/source3/rpc_server/srv_spoolss_nt.c @@ -75,7 +75,7 @@ typedef struct _counter_printer_0 { static counter_printer_0 *counter_list; -static struct cli_state notify_cli; /* print notify back-channel */ +static struct rpc_pipe_client *notify_cli_pipe; /* print notify back-channel pipe handle*/ static uint32 smb_connections=0; @@ -166,7 +166,7 @@ static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle) return; } - result = cli_spoolss_reply_close_printer(¬ify_cli, notify_cli.mem_ctx, handle); + result = rpccli_spoolss_reply_close_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, handle); if (!W_ERROR_IS_OK(result)) DEBUG(0,("srv_spoolss_replycloseprinter: reply_close_printer failed [%s].\n", @@ -174,9 +174,8 @@ static void srv_spoolss_replycloseprinter(int snum, POLICY_HND *handle) /* if it's the last connection, deconnect the IPC$ share */ if (smb_connections==1) { - cli_nt_session_close(¬ify_cli); - cli_ulogoff(¬ify_cli); - cli_shutdown(¬ify_cli); + cli_shutdown(notify_cli_pipe->cli); + notify_cli_pipe = NULL; /* The above call shuts downn the pipe also. */ message_deregister(MSG_PRINTER_NOTIFY2); /* Tell the connections db we're no longer interested in @@ -688,7 +687,7 @@ static void notify_system_time(struct spoolss_notify_msg *msg, return; } - if (!prs_init(&ps, MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) { + if (!prs_init(&ps, RPC_MAX_PDU_FRAG_LEN, mem_ctx, MARSHALL)) { DEBUG(5, ("notify_system_time: prs_init() failed\n")); return; } @@ -1021,7 +1020,7 @@ static void send_notify2_changes( SPOOLSS_NOTIFY_MSG_CTR *ctr, uint32 idx ) } if ( sending_msg_count ) { - cli_spoolss_rrpcn( ¬ify_cli, mem_ctx, &p->notify.client_hnd, + rpccli_spoolss_rrpcn( notify_cli_pipe, mem_ctx, &p->notify.client_hnd, data_len, data, p->notify.change, 0 ); } } @@ -1075,7 +1074,8 @@ static BOOL notify2_unpack_msg( SPOOLSS_NOTIFY_MSG *msg, struct timeval *tv, voi Receive a notify2 message list ********************************************************************/ -static void receive_notify2_message_list(int msg_type, pid_t src, void *msg, size_t len) +static void receive_notify2_message_list(int msg_type, struct process_id src, + void *msg, size_t len) { size_t msg_count, i; char *buf = (char *)msg; @@ -1176,7 +1176,8 @@ static BOOL srv_spoolss_drv_upgrade_printer(char* drivername) DEBUG(10,("srv_spoolss_drv_upgrade_printer: Sending message about driver upgrade [%s]\n", drivername)); - message_send_pid(sys_getpid(), MSG_PRINTER_DRVUPGRADE, drivername, len+1, False); + message_send_pid(pid_to_procid(sys_getpid()), + MSG_PRINTER_DRVUPGRADE, drivername, len+1, False); return True; } @@ -1186,7 +1187,7 @@ static BOOL srv_spoolss_drv_upgrade_printer(char* drivername) over all printers, upgrading ones as necessary **********************************************************************/ -void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len) +void do_drv_upgrade_printer(int msg_type, struct process_id src, void *buf, size_t len) { fstring drivername; int snum; @@ -1272,7 +1273,8 @@ static BOOL srv_spoolss_reset_printerdata(char* drivername) DEBUG(10,("srv_spoolss_reset_printerdata: Sending message about resetting printerdata [%s]\n", drivername)); - message_send_pid(sys_getpid(), MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False); + message_send_pid(pid_to_procid(sys_getpid()), + MSG_PRINTERDATA_INIT_RESET, drivername, len+1, False); return True; } @@ -1282,7 +1284,8 @@ static BOOL srv_spoolss_reset_printerdata(char* drivername) over all printers, resetting printer data as neessary **********************************************************************/ -void reset_all_printerdata(int msg_type, pid_t src, void *buf, size_t len) +void reset_all_printerdata(int msg_type, struct process_id src, + void *buf, size_t len) { fstring drivername; int snum; @@ -2001,7 +2004,10 @@ WERROR _spoolss_deleteprinterdriver(pipes_struct *p, SPOOL_Q_DELETEPRINTERDRIVER /* this should not have failed---if it did, report to client */ if ( !W_ERROR_IS_OK(status_win2k) ) + { + status = status_win2k; goto done; + } } } @@ -2479,9 +2485,10 @@ done: Connect to the client machine. **********************************************************/ -static BOOL spoolss_connect_to_client(struct cli_state *the_cli, +static BOOL spoolss_connect_to_client(struct cli_state *the_cli, struct rpc_pipe_client **pp_pipe, struct in_addr *client_ip, const char *remote_machine) { + NTSTATUS ret; ZERO_STRUCTP(the_cli); if(cli_initialise(the_cli) == NULL) { @@ -2563,10 +2570,10 @@ static BOOL spoolss_connect_to_client(struct cli_state *the_cli, * Now start the NT Domain stuff :-). */ - if(cli_nt_session_open(the_cli, PI_SPOOLSS) == False) { - DEBUG(0,("spoolss_connect_to_client: unable to open the domain client session to machine %s. Error was : %s.\n", remote_machine, cli_errstr(the_cli))); - cli_nt_session_close(the_cli); - cli_ulogoff(the_cli); + *pp_pipe = cli_rpc_pipe_open_noauth(the_cli, PI_SPOOLSS, &ret); + if(!*pp_pipe) { + DEBUG(0,("spoolss_connect_to_client: unable to open the spoolss pipe on machine %s. Error was : %s.\n", + remote_machine, nt_errstr(ret))); cli_shutdown(the_cli); return False; } @@ -2589,13 +2596,14 @@ static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer, * and connect to the IPC$ share anonymously */ if (smb_connections==0) { + struct cli_state notify_cli; /* print notify back-channel */ fstring unix_printer; fstrcpy(unix_printer, printer+2); /* the +2 is to strip the leading 2 backslashs */ ZERO_STRUCT(notify_cli); - if(!spoolss_connect_to_client(¬ify_cli, client_ip, unix_printer)) + if(!spoolss_connect_to_client(¬ify_cli, ¬ify_cli_pipe, client_ip, unix_printer)) return False; message_register(MSG_PRINTER_NOTIFY2, receive_notify2_message_list); @@ -2614,7 +2622,7 @@ static BOOL srv_spoolss_replyopenprinter(int snum, const char *printer, smb_connections++; - result = cli_spoolss_reply_open_printer(¬ify_cli, notify_cli.mem_ctx, printer, localprinter, + result = rpccli_spoolss_reply_open_printer(notify_cli_pipe, notify_cli_pipe->cli->mem_ctx, printer, localprinter, type, handle); if (!W_ERROR_IS_OK(result)) @@ -6117,17 +6125,12 @@ static WERROR update_printer(pipes_struct *p, POLICY_HND *handle, uint32 level, || !strequal(printer->info_2->portname, old_printer->info_2->portname) || !strequal(printer->info_2->location, old_printer->info_2->location)) ) { + /* add_printer_hook() will call reload_services() */ + if ( !add_printer_hook(p->pipe_user.nt_user_token, printer) ) { result = WERR_ACCESS_DENIED; goto done; } - - /* - * make sure we actually reload the services after - * this as smb.conf could have a new section in it - * .... shouldn't .... but could - */ - reload_services(False); } /* diff --git a/source3/rpc_server/srv_srvsvc_nt.c b/source3/rpc_server/srv_srvsvc_nt.c index e9dd015421c..9643b2a7249 100644 --- a/source3/rpc_server/srv_srvsvc_nt.c +++ b/source3/rpc_server/srv_srvsvc_nt.c @@ -113,7 +113,8 @@ static void init_srv_share_info_2(pipes_struct *p, SRV_SHARE_INFO_2 *sh2, int sn What to do when smb.conf is updated. ********************************************************************/ -static void smb_conf_updated(int msg_type, pid_t src, void *buf, size_t len) +static void smb_conf_updated(int msg_type, struct process_id src, + void *buf, size_t len) { DEBUG(10,("smb_conf_updated: Got message saying smb.conf was updated. Reloading.\n")); reload_services(False); @@ -1394,7 +1395,7 @@ WERROR _srv_net_sess_del(pipes_struct *p, SRV_Q_NET_SESS_DEL *q_u, SRV_R_NET_SES become_root(); } - if (message_send_pid(session_list[snum].pid, MSG_SHUTDOWN, NULL, 0, False)) + if (message_send_pid(pid_to_procid(session_list[snum].pid), MSG_SHUTDOWN, NULL, 0, False)) r_u->status = WERR_OK; if (not_root) diff --git a/source3/rpc_server/srv_svcctl.c b/source3/rpc_server/srv_svcctl.c index 6ba26414d36..31d8bbe9b3d 100644 --- a/source3/rpc_server/srv_svcctl.c +++ b/source3/rpc_server/srv_svcctl.c @@ -309,24 +309,76 @@ static BOOL api_svcctl_query_service_config2(pipes_struct *p) return True; } +/******************************************************************* + ********************************************************************/ + +static BOOL api_svcctl_lock_service_db(pipes_struct *p) +{ + SVCCTL_Q_LOCK_SERVICE_DB q_u; + SVCCTL_R_LOCK_SERVICE_DB r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!svcctl_io_q_lock_service_db("", &q_u, data, 0)) + return False; + + r_u.status = _svcctl_lock_service_db(p, &q_u, &r_u); + + if(!svcctl_io_r_lock_service_db("", &r_u, rdata, 0)) + return False; + + return True; +} + + +/******************************************************************* + ********************************************************************/ + +static BOOL api_svcctl_unlock_service_db(pipes_struct *p) +{ + SVCCTL_Q_UNLOCK_SERVICE_DB q_u; + SVCCTL_R_UNLOCK_SERVICE_DB r_u; + prs_struct *data = &p->in_data.data; + prs_struct *rdata = &p->out_data.rdata; + + ZERO_STRUCT(q_u); + ZERO_STRUCT(r_u); + + if(!svcctl_io_q_unlock_service_db("", &q_u, data, 0)) + return False; + + r_u.status = _svcctl_unlock_service_db(p, &q_u, &r_u); + + if(!svcctl_io_r_unlock_service_db("", &r_u, rdata, 0)) + return False; + + return True; +} + + /******************************************************************* \PIPE\svcctl commands ********************************************************************/ static struct api_struct api_svcctl_cmds[] = { - { "SVCCTL_CLOSE_SERVICE" , SVCCTL_CLOSE_SERVICE , api_svcctl_close_service }, - { "SVCCTL_OPEN_SCMANAGER_W" , SVCCTL_OPEN_SCMANAGER_W , api_svcctl_open_scmanager }, - { "SVCCTL_OPEN_SERVICE_W" , SVCCTL_OPEN_SERVICE_W , api_svcctl_open_service }, - { "SVCCTL_GET_DISPLAY_NAME" , SVCCTL_GET_DISPLAY_NAME , api_svcctl_get_display_name }, - { "SVCCTL_QUERY_STATUS" , SVCCTL_QUERY_STATUS , api_svcctl_query_status }, - { "SVCCTL_QUERY_SERVICE_CONFIG_W", SVCCTL_QUERY_SERVICE_CONFIG_W, api_svcctl_query_service_config }, - { "SVCCTL_QUERY_SERVICE_CONFIG2_W", SVCCTL_QUERY_SERVICE_CONFIG2_W, api_svcctl_query_service_config2 }, - { "SVCCTL_ENUM_SERVICES_STATUS_W", SVCCTL_ENUM_SERVICES_STATUS_W, api_svcctl_enum_services_status }, - { "SVCCTL_ENUM_DEPENDENT_SERVICES_W", SVCCTL_ENUM_DEPENDENT_SERVICES_W, api_svcctl_enum_dependent_services }, - { "SVCCTL_START_SERVICE_W" , SVCCTL_START_SERVICE_W , api_svcctl_start_service }, - { "SVCCTL_CONTROL_SERVICE" , SVCCTL_CONTROL_SERVICE , api_svcctl_control_service }, - { "SVCCTL_QUERY_SERVICE_STATUSEX_W", SVCCTL_QUERY_SERVICE_STATUSEX_W, api_svcctl_query_service_status_ex } + { "SVCCTL_CLOSE_SERVICE" , SVCCTL_CLOSE_SERVICE , api_svcctl_close_service }, + { "SVCCTL_OPEN_SCMANAGER_W" , SVCCTL_OPEN_SCMANAGER_W , api_svcctl_open_scmanager }, + { "SVCCTL_OPEN_SERVICE_W" , SVCCTL_OPEN_SERVICE_W , api_svcctl_open_service }, + { "SVCCTL_GET_DISPLAY_NAME" , SVCCTL_GET_DISPLAY_NAME , api_svcctl_get_display_name }, + { "SVCCTL_QUERY_STATUS" , SVCCTL_QUERY_STATUS , api_svcctl_query_status }, + { "SVCCTL_QUERY_SERVICE_CONFIG_W" , SVCCTL_QUERY_SERVICE_CONFIG_W , api_svcctl_query_service_config }, + { "SVCCTL_QUERY_SERVICE_CONFIG2_W" , SVCCTL_QUERY_SERVICE_CONFIG2_W , api_svcctl_query_service_config2 }, + { "SVCCTL_ENUM_SERVICES_STATUS_W" , SVCCTL_ENUM_SERVICES_STATUS_W , api_svcctl_enum_services_status }, + { "SVCCTL_ENUM_DEPENDENT_SERVICES_W" , SVCCTL_ENUM_DEPENDENT_SERVICES_W , api_svcctl_enum_dependent_services }, + { "SVCCTL_START_SERVICE_W" , SVCCTL_START_SERVICE_W , api_svcctl_start_service }, + { "SVCCTL_CONTROL_SERVICE" , SVCCTL_CONTROL_SERVICE , api_svcctl_control_service }, + { "SVCCTL_QUERY_SERVICE_STATUSEX_W" , SVCCTL_QUERY_SERVICE_STATUSEX_W , api_svcctl_query_service_status_ex }, + { "SVCCTL_LOCK_SERVICE_DB" , SVCCTL_LOCK_SERVICE_DB , api_svcctl_lock_service_db }, + { "SVCCTL_UNLOCK_SERVICE_DB" , SVCCTL_UNLOCK_SERVICE_DB , api_svcctl_unlock_service_db } }; diff --git a/source3/rpc_server/srv_svcctl_nt.c b/source3/rpc_server/srv_svcctl_nt.c index 538b97a2b17..e8df2acb22f 100644 --- a/source3/rpc_server/srv_svcctl_nt.c +++ b/source3/rpc_server/srv_svcctl_nt.c @@ -1,8 +1,11 @@ /* * Unix SMB/CIFS implementation. * RPC Pipe client / server routines - * Copyright (C) Gerald (Jerry) Carter 2005, + * * Copyright (C) Marcin Krzysztof Porwit 2005. + * + * Largely Rewritten (Again) by: + * Copyright (C) Gerald (Jerry) Carter 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 @@ -19,51 +22,97 @@ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ -/* TODO - Do the OpenService service name matching case-independently, or at least make it an option. */ - - #include "includes.h" #undef DBGC_CLASS #define DBGC_CLASS DBGC_RPC_SRV -#define SERVICEDB_VERSION_V1 1 /* Will there be more? */ -#define INTERNAL_SERVICES_LIST "NETLOGON Spooler" - -/* */ -/* scripts will execute from the following libdir, if they are in the enable svcctl= */ -/* these should likely be symbolic links. Note that information about them will be extracted from the files themselves */ -/* using the LSB standard keynames for various information */ - -#define SVCCTL_SCRIPT_DIR "/svcctl/" - - -struct service_control_op_table { +struct service_control_op { const char *name; SERVICE_CONTROL_OPS *ops; }; extern SERVICE_CONTROL_OPS spoolss_svc_ops; +extern SERVICE_CONTROL_OPS rcinit_svc_ops; +extern SERVICE_CONTROL_OPS netlogon_svc_ops; +extern SERVICE_CONTROL_OPS winreg_svc_ops; -struct service_control_op_table svcctl_ops[] = { - { "Spooler", &spoolss_svc_ops }, - { "NETLOGON", NULL }, - { NULL, NULL } -}; +struct service_control_op *svcctl_ops; + +static struct generic_mapping scm_generic_map = + { SC_MANAGER_READ_ACCESS, SC_MANAGER_WRITE_ACCESS, SC_MANAGER_EXECUTE_ACCESS, SC_MANAGER_ALL_ACCESS }; +static struct generic_mapping svc_generic_map = + { SERVICE_READ_ACCESS, SERVICE_WRITE_ACCESS, SERVICE_EXECUTE_ACCESS, SERVICE_ALL_ACCESS }; /******************************************************************** ********************************************************************/ +BOOL init_service_op_table( void ) +{ + const char **service_list = lp_svcctl_list(); + int num_services = 3 + str_list_count( service_list ); + int i; + + if ( !(svcctl_ops = TALLOC_ARRAY( NULL, struct service_control_op, num_services+1)) ) { + DEBUG(0,("init_service_op_table: talloc() failed!\n")); + return False; + } + + /* services listed in smb.conf get the rc.init interface */ + + for ( i=0; service_list[i]; i++ ) { + svcctl_ops[i].name = talloc_strdup( svcctl_ops, service_list[i] ); + svcctl_ops[i].ops = &rcinit_svc_ops; + } + + /* add builtin services */ + + svcctl_ops[i].name = talloc_strdup( svcctl_ops, "Spooler" ); + svcctl_ops[i].ops = &spoolss_svc_ops; + i++; + + svcctl_ops[i].name = talloc_strdup( svcctl_ops, "NETLOGON" ); + svcctl_ops[i].ops = &netlogon_svc_ops; + i++; + + svcctl_ops[i].name = talloc_strdup( svcctl_ops, "RemoteRegistry" ); + svcctl_ops[i].ops = &winreg_svc_ops; + i++; + + /* NULL terminate the array */ + + svcctl_ops[i].name = NULL; + svcctl_ops[i].ops = NULL; + + return True; +} + +/******************************************************************** +********************************************************************/ + +static struct service_control_op* find_service_by_name( const char *name ) +{ + int i; + + for ( i=0; svcctl_ops[i].name; i++ ) { + if ( strequal( name, svcctl_ops[i].name ) ) + return &svcctl_ops[i]; + } + + return NULL; +} +/******************************************************************** +********************************************************************/ + static NTSTATUS svcctl_access_check( SEC_DESC *sec_desc, NT_USER_TOKEN *token, uint32 access_desired, uint32 *access_granted ) { NTSTATUS result; if ( geteuid() == sec_initial_uid() ) { - DEBUG(5,("svcctl_access_check: access check bypassed for 'root'\n")); - *access_granted = access_desired; - return NT_STATUS_OK; + DEBUG(5,("svcctl_access_check: using root's token\n")); + token = get_root_nt_token(); } se_access_check( sec_desc, token, access_desired, access_granted, &result ); @@ -81,7 +130,7 @@ static SEC_DESC* construct_scm_sd( TALLOC_CTX *ctx ) size_t i = 0; SEC_DESC *sd; SEC_ACL *acl; - uint32 sd_size; + size_t sd_size; /* basic access for Everyone */ @@ -105,51 +154,13 @@ static SEC_DESC* construct_scm_sd( TALLOC_CTX *ctx ) return sd; } -/******************************************************************** -********************************************************************/ - -static SEC_DESC* construct_service_sd( TALLOC_CTX *ctx ) -{ - SEC_ACE ace[4]; - SEC_ACCESS mask; - size_t i = 0; - SEC_DESC *sd; - SEC_ACL *acl; - uint32 sd_size; - - /* basic access for Everyone */ - - init_sec_access(&mask, SERVICE_READ_ACCESS ); - init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - - init_sec_access(&mask,SERVICE_EXECUTE_ACCESS ); - init_sec_ace(&ace[i++], &global_sid_Builtin_Power_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - - init_sec_access(&mask,SERVICE_ALL_ACCESS ); - init_sec_ace(&ace[i++], &global_sid_Builtin_Server_Operators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); - - /* create the security descriptor */ - - if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) ) - return NULL; - - if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) ) - return NULL; - - return sd; -} - /****************************************************************** free() function for REGISTRY_KEY *****************************************************************/ static void free_service_handle_info(void *ptr) { - SERVICE_INFO *info = (SERVICE_INFO*)ptr; - - SAFE_FREE(info->name); - SAFE_FREE(info); + TALLOC_FREE( ptr ); } /****************************************************************** @@ -171,44 +182,50 @@ static SERVICE_INFO *find_service_info_by_hnd(pipes_struct *p, POLICY_HND *hnd) /****************************************************************** *****************************************************************/ -static WERROR create_open_service_handle( pipes_struct *p, POLICY_HND *handle, +static WERROR create_open_service_handle( pipes_struct *p, POLICY_HND *handle, uint32 type, const char *service, uint32 access_granted ) { SERVICE_INFO *info = NULL; WERROR result = WERR_OK; + struct service_control_op *s_op; - if ( !(info = SMB_MALLOC_P( SERVICE_INFO )) ) + if ( !(info = TALLOC_ZERO_P( NULL, SERVICE_INFO )) ) return WERR_NOMEM; - ZERO_STRUCTP( info ); - /* the Service Manager has a NULL name */ - if ( !service ) { + info->type = SVC_HANDLE_IS_SCM; + + switch ( type ) { + case SVC_HANDLE_IS_SCM: info->type = SVC_HANDLE_IS_SCM; - } else { - int i; + break; + case SVC_HANDLE_IS_DBLOCK: + info->type = SVC_HANDLE_IS_DBLOCK; + break; + + case SVC_HANDLE_IS_SERVICE: info->type = SVC_HANDLE_IS_SERVICE; /* lookup the SERVICE_CONTROL_OPS */ - for ( i=0; svcctl_ops[i].name; i++ ) { - if ( strequal( svcctl_ops[i].name, service ) ) { - info->ops = svcctl_ops[i].ops; - break; - } - } - - if ( !svcctl_ops[i].name ) { + if ( !(s_op = find_service_by_name( service )) ) { result = WERR_NO_SUCH_SERVICE; goto done; } + + info->ops = s_op->ops; - if ( !(info->name = SMB_STRDUP( service )) ) { + if ( !(info->name = talloc_strdup( info, s_op->name )) ) { result = WERR_NOMEM; goto done; } + break; + + default: + result = WERR_NO_SUCH_SERVICE; + goto done; } info->access_granted = access_granted; @@ -241,11 +258,12 @@ WERROR _svcctl_open_scmanager(pipes_struct *p, SVCCTL_Q_OPEN_SCMANAGER *q_u, SVC if ( !(sec_desc = construct_scm_sd( p->mem_ctx )) ) return WERR_NOMEM; + se_map_generic( &q_u->access, &scm_generic_map ); status = svcctl_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted ); if ( !NT_STATUS_IS_OK(status) ) return ntstatus_to_werror( status ); - return create_open_service_handle( p, &r_u->handle, NULL, access_granted ); + return create_open_service_handle( p, &r_u->handle, SVC_HANDLE_IS_SCM, NULL, access_granted ); } /******************************************************************** @@ -268,21 +286,18 @@ WERROR _svcctl_open_service(pipes_struct *p, SVCCTL_Q_OPEN_SERVICE *q_u, SVCCTL_ if ( !find_service_info_by_hnd( p, &q_u->handle ) ) return WERR_BADFID; - /* perform access checks */ + /* perform access checks. Use the root token in order to ensure that we + retreive the security descriptor */ - if ( !(sec_desc = construct_service_sd( p->mem_ctx )) ) + if ( !(sec_desc = svcctl_get_secdesc( p->mem_ctx, service, get_root_nt_token() )) ) return WERR_NOMEM; + se_map_generic( &q_u->access, &svc_generic_map ); status = svcctl_access_check( sec_desc, p->pipe_user.nt_user_token, q_u->access, &access_granted ); if ( !NT_STATUS_IS_OK(status) ) return ntstatus_to_werror( status ); - -#if 0 /* FIXME!!! */ - if ( ! get_service_info(service_tdb, service, info) ) { - return WERR_NO_SUCH_SERVICE; -#endif - return create_open_service_handle( p, &r_u->handle, service, access_granted ); + return create_open_service_handle( p, &r_u->handle, SVC_HANDLE_IS_SERVICE, service, access_granted ); } /******************************************************************** @@ -299,7 +314,7 @@ WERROR _svcctl_close_service(pipes_struct *p, SVCCTL_Q_CLOSE_SERVICE *q_u, SVCCT WERROR _svcctl_get_display_name(pipes_struct *p, SVCCTL_Q_GET_DISPLAY_NAME *q_u, SVCCTL_R_GET_DISPLAY_NAME *r_u) { fstring service; - fstring displayname; + const char *display_name; SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); /* can only use an SCM handle here */ @@ -308,12 +323,9 @@ WERROR _svcctl_get_display_name(pipes_struct *p, SVCCTL_Q_GET_DISPLAY_NAME *q_u, return WERR_BADFID; rpcstr_pull(service, q_u->servicename.buffer, sizeof(service), q_u->servicename.uni_str_len*2, 0); - - /* need a tdb lookup here or something */ - fstrcpy( displayname, "FIX ME!" ); - - init_svcctl_r_get_display_name( r_u, displayname ); + display_name = svcctl_lookup_dispname( service, p->pipe_user.nt_user_token ); + init_svcctl_r_get_display_name( r_u, display_name ); return WERR_OK; } @@ -335,87 +347,40 @@ WERROR _svcctl_query_status(pipes_struct *p, SVCCTL_Q_QUERY_STATUS *q_u, SVCCTL_ /* try the service specific status call */ - if ( info->ops ) - return info->ops->service_status( &r_u->svc_status ); - - /* default action for now */ - - r_u->svc_status.type = 0x0020; - r_u->svc_status.state = 0x0004; - r_u->svc_status.controls_accepted = 0x0005; - - return WERR_OK; + return info->ops->service_status( info->name, &r_u->svc_status ); } +/******************************************************************** +********************************************************************/ -/********************************************************************* - TODO - for internal services, do similar to external services, except - we have to call the right status routine... -**********************************************************************/ - -static WERROR enum_internal_services(TALLOC_CTX *ctx,ENUM_SERVICES_STATUS **svc_ptr, int existing_services, uint32 *added) +static int enumerate_status( TALLOC_CTX *ctx, ENUM_SERVICES_STATUS **status, NT_USER_TOKEN *token ) { - int num_services = 2; - int i = 0; - ENUM_SERVICES_STATUS *services=NULL; - - if (!svc_ptr || !(*svc_ptr)) - return WERR_NOMEM; - - services = *svc_ptr; - - if ( (existing_services > 0) && svc_ptr && *svc_ptr ) { - ENUM_SERVICES_STATUS *tmp_services = NULL; - uint32 total_svc = existing_services + num_services; - - if ( !(tmp_services = TALLOC_REALLOC_ARRAY( ctx, services, ENUM_SERVICES_STATUS, total_svc )) ) - return WERR_NOMEM; - - services = tmp_services; - i += existing_services; - } - else { - if ( !(services = TALLOC_ARRAY( ctx, ENUM_SERVICES_STATUS, num_services )) ) - return WERR_NOMEM; + int num_services = 0; + int i; + ENUM_SERVICES_STATUS *st; + const char *display_name; + + /* just count */ + while ( svcctl_ops[num_services].name ) + num_services++; + + if ( !(st = TALLOC_ARRAY( ctx, ENUM_SERVICES_STATUS, num_services )) ) { + DEBUG(0,("enumerate_status: talloc() failed!\n")); + return -1; } - - DEBUG(8,("enum_internal_services: Creating %d services, starting index %d\n", - num_services, existing_services)); - - init_unistr( &services[i].servicename, "Spooler" ); - init_unistr( &services[i].displayname, "Print Spooler" ); - - services[i].status.type = 0x110; - services[i].status.controls_accepted = 0x0; - services[i].status.win32_exit_code = 0x0; - services[i].status.service_exit_code = 0x0; - services[i].status.check_point = 0x0; - services[i].status.wait_hint = 0x0; - if ( !lp_disable_spoolss() ) - services[i].status.state = SVCCTL_RUNNING; - else - services[i].status.state = SVCCTL_STOPPED; - - i++; - init_unistr( &services[i].servicename, "NETLOGON" ); - init_unistr( &services[i].displayname, "Net Logon" ); + for ( i=0; iservice_status( svcctl_ops[i].name, &st[i].status ); + } - services[i].status.type = 0x20; - services[i].status.controls_accepted = 0x0; - services[i].status.win32_exit_code = 0x0; - services[i].status.service_exit_code = 0x0; - services[i].status.check_point = 0x0; - services[i].status.wait_hint = 0x0; - if ( lp_servicenumber("NETLOGON") != -1 ) - services[i].status.state = SVCCTL_RUNNING; - else - services[i].status.state = SVCCTL_STOPPED; - - *added = num_services; - *svc_ptr = services; + *status = st; - return WERR_OK; + return num_services; } /******************************************************************** @@ -424,11 +389,12 @@ static WERROR enum_internal_services(TALLOC_CTX *ctx,ENUM_SERVICES_STATUS **svc_ WERROR _svcctl_enum_services_status(pipes_struct *p, SVCCTL_Q_ENUM_SERVICES_STATUS *q_u, SVCCTL_R_ENUM_SERVICES_STATUS *r_u) { ENUM_SERVICES_STATUS *services = NULL; - uint32 num_int_services, num_ext_services, total_services; + uint32 num_services; int i = 0; size_t buffer_size = 0; WERROR result = WERR_OK; SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); + NT_USER_TOKEN *token = p->pipe_user.nt_user_token; /* perform access checks */ @@ -438,50 +404,29 @@ WERROR _svcctl_enum_services_status(pipes_struct *p, SVCCTL_Q_ENUM_SERVICES_STAT if ( !(info->access_granted & SC_RIGHT_MGR_ENUMERATE_SERVICE) ) return WERR_ACCESS_DENIED; - num_int_services = 0; - num_ext_services = 0; - - /* num_services = str_list_count( lp_enable_svcctl() ); */ - - /* here's where we'll read the db of external services */ - /* _svcctl_read_LSB_data(NULL,NULL); */ - /* init_svcctl_db(); */ - - if ( !(services = TALLOC_ARRAY(p->mem_ctx, ENUM_SERVICES_STATUS, num_int_services+num_ext_services )) ) + if ( (num_services = enumerate_status( p->mem_ctx, &services, token )) == -1 ) return WERR_NOMEM; - if ( W_ERROR_IS_OK(enum_internal_services(p->mem_ctx, &services, 0, &num_int_services)) ) - DEBUG(8,("_svcctl_enum_services_status: Got %d internal services\n", num_int_services)); - -#if 0 - if ( W_ERROR_IS_OK(enum_external_services(p->mem_ctx, &services, num_int_services, &num_ext_services)) ) - DEBUG(8,("_svcctl_enum_services_status: Got %d external services\n", num_ext_services)); -#endif - - total_services = num_int_services + num_ext_services; - - DEBUG(8,("_svcctl_enum_services_status: total of %d services\n", total_services )); - - for ( i=0; i q_u->buffer_size ) { - total_services = 0; + num_services = 0; result = WERR_MORE_DATA; } rpcbuf_init(&r_u->buffer, q_u->buffer_size, p->mem_ctx); if ( W_ERROR_IS_OK(result) ) { - for ( i=0; ibuffer, 0 ); } r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size; - r_u->returned = total_services; + r_u->returned = num_services; if ( !(r_u->resume = TALLOC_P( p->mem_ctx, uint32 )) ) return WERR_NOMEM; @@ -506,7 +451,7 @@ WERROR _svcctl_start_service(pipes_struct *p, SVCCTL_Q_START_SERVICE *q_u, SVCCT if ( !(info->access_granted & SC_RIGHT_SVC_START) ) return WERR_ACCESS_DENIED; - return info->ops->start_service(); + return info->ops->start_service( info->name ); } /******************************************************************** @@ -517,18 +462,27 @@ WERROR _svcctl_control_service(pipes_struct *p, SVCCTL_Q_CONTROL_SERVICE *q_u, S SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); /* perform access checks */ - /* we only support stop so don't get complicated */ - + if ( !info || (info->type != SVC_HANDLE_IS_SERVICE) ) return WERR_BADFID; - if ( q_u->control != SVCCTL_CONTROL_STOP ) - return WERR_ACCESS_DENIED; - - if ( !(info->access_granted & SC_RIGHT_SVC_STOP) ) - return WERR_ACCESS_DENIED; + switch ( q_u->control ) { + case SVCCTL_CONTROL_STOP: + if ( !(info->access_granted & SC_RIGHT_SVC_STOP) ) + return WERR_ACCESS_DENIED; + + return info->ops->stop_service( info->name, &r_u->svc_status ); - return info->ops->stop_service( &r_u->svc_status ); + case SVCCTL_CONTROL_INTERROGATE: + if ( !(info->access_granted & SC_RIGHT_SVC_QUERY_STATUS) ) + return WERR_ACCESS_DENIED; + + return info->ops->service_status( info->name, &r_u->svc_status ); + } + + /* default control action */ + + return WERR_ACCESS_DENIED; } /******************************************************************** @@ -564,11 +518,8 @@ WERROR _svcctl_enum_dependent_services( pipes_struct *p, SVCCTL_Q_ENUM_DEPENDENT WERROR _svcctl_query_service_status_ex( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_STATUSEX *q_u, SVCCTL_R_QUERY_SERVICE_STATUSEX *r_u ) { - SERVICE_STATUS_PROCESS ssp; - POLICY_HND *handle; - SERVICE_INFO *service_info; - pstring command; SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); + uint32 buffer_size; /* perform access checks */ @@ -579,68 +530,80 @@ WERROR _svcctl_query_service_status_ex( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_ return WERR_ACCESS_DENIED; /* we have to set the outgoing buffer size to the same as the - incoming buffer size (even in the case of failure */ - - r_u->needed = q_u->buffer_size; - - /* need to find the service name by the handle that is open */ - handle = &(q_u->handle); + incoming buffer size (even in the case of failure) */ + rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx ); + r_u->needed = q_u->buffer_size; + + switch ( q_u->level ) { + case SVC_STATUS_PROCESS_INFO: + { + SERVICE_STATUS_PROCESS svc_stat_proc; - /* get rid of the easy errors */ + /* Get the status of the service.. */ + info->ops->service_status( info->name, &svc_stat_proc.status ); + svc_stat_proc.process_id = sys_getpid(); + svc_stat_proc.service_flags = 0x0; - if (q_u->info_level != SVC_STATUS_PROCESS_INFO) { - DEBUG(10, ("_svcctl_query_service_status_ex : Invalid information level specified\n")); - return WERR_UNKNOWN_LEVEL; + svcctl_io_service_status_process( "", &svc_stat_proc, &r_u->buffer, 0 ); + buffer_size = sizeof(SERVICE_STATUS_PROCESS); + break; + } + + default: + return WERR_UNKNOWN_LEVEL; } - service_info = find_service_info_by_hnd(p, handle); - - if (!service_info) { - DEBUG(10, ("_svcctl_query_service_status_ex : Can't find the service for the handle\n")); - return WERR_BADFID; - } - if (r_u->needed < (sizeof(SERVICE_STATUS_PROCESS)+sizeof(uint32)+sizeof(uint32))) { - DEBUG(10, ("_svcctl_query_service_status_ex : buffer size of [%d] is too small.\n",r_u->needed)); - return WERR_INSUFFICIENT_BUFFER; - } - - ZERO_STRUCT(ssp); - -#if 0 - if (!strwicmp(service_info->servicetype,"EXTERNAL")) - ssp.type = SVCCTL_WIN32_OWN_PROC; - else - ssp.type = SVCCTL_WIN32_SHARED_PROC; -#endif + buffer_size += buffer_size % 4; + r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size; - /* Get the status of the service.. */ + if (buffer_size > q_u->buffer_size ) + return WERR_MORE_DATA; + + return WERR_OK; +} - memset(command, 0, sizeof(command)); +/******************************************************************** +********************************************************************/ -#if 0 - slprintf(command, sizeof(command)-1, "%s%s%s %s", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, service_info->filename, "status"); +static WERROR fill_svc_config( TALLOC_CTX *ctx, const char *name, SERVICE_CONFIG *config, NT_USER_TOKEN *token ) +{ + REGVAL_CTR *values; + REGISTRY_VALUE *val; - DEBUG(10, ("_svcctl_query_service_status_ex: status command is [%s]\n", command)); + /* retrieve the registry values for this service */ + + if ( !(values = svcctl_fetch_regvalues( name, token )) ) + return WERR_REG_CORRUPT; + + /* now fill in the individual values */ + + config->displayname = TALLOC_ZERO_P( ctx, UNISTR2 ); + if ( (val = regval_ctr_getvalue( values, "DisplayName" )) != NULL ) + init_unistr2( config->displayname, regval_sz( val ), UNI_STR_TERMINATE ); + else + init_unistr2( config->displayname, name, UNI_STR_TERMINATE ); - /* TODO - wrap in privilege check */ + if ( (val = regval_ctr_getvalue( values, "ObjectName" )) != NULL ) { + config->startname = TALLOC_ZERO_P( ctx, UNISTR2 ); + init_unistr2( config->startname, regval_sz( val ), UNI_STR_TERMINATE ); + } + + if ( (val = regval_ctr_getvalue( values, "ImagePath" )) != NULL ) { + config->executablepath = TALLOC_ZERO_P( ctx, UNISTR2 ); + init_unistr2( config->executablepath, regval_sz( val ), UNI_STR_TERMINATE ); + } - ret = smbrun(command, &fd); - DEBUGADD(10, ("returned [%d]\n", ret)); - close(fd); - if(ret != 0) - DEBUG(10, ("_svcctl_query_service_status_ex: Command returned [%d]\n", ret)); + /* a few hard coded values */ + /* loadordergroup and dependencies are empty */ + + config->tag_id = 0x00000000; /* unassigned loadorder group */ + config->service_type = SVCCTL_WIN32_OWN_PROC; + config->start_type = SVCCTL_DEMAND_START; + config->error_control = SVCCTL_SVC_ERROR_NORMAL; - /* SET all service_stats bits here... */ - if (ret == 0) { - ssp.state = SVCCTL_RUNNING; - ssp.controls_accepted = SVCCTL_CONTROL_SHUTDOWN | SVCCTL_CONTROL_STOP; - } else { - ssp.state = SVCCTL_STOPPED; - ssp.controls_accepted = 0; - } -#endif + TALLOC_FREE( values ); return WERR_OK; } @@ -650,10 +613,9 @@ WERROR _svcctl_query_service_status_ex( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_ WERROR _svcctl_query_service_config( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CONFIG *q_u, SVCCTL_R_QUERY_SERVICE_CONFIG *r_u ) { - POLICY_HND *handle; - SERVICE_INFO *service_info; - uint32 needed_size; SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); + uint32 buffer_size; + WERROR wresult; /* perform access checks */ @@ -667,89 +629,19 @@ WERROR _svcctl_query_service_config( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CON incoming buffer size (even in the case of failure */ r_u->needed = q_u->buffer_size; + + wresult = fill_svc_config( p->mem_ctx, info->name, &r_u->config, p->pipe_user.nt_user_token ); + if ( !W_ERROR_IS_OK(wresult) ) + return wresult; + + buffer_size = svcctl_sizeof_service_config( &r_u->config ); + r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size; - /* need to find the service name by the handle that is open */ - handle = &(q_u->handle); - - service_info = find_service_info_by_hnd(p, handle); - -#if 0 - if (q_u->buffer_size < sizeof(Service_info)) { - /* have to report need more... */ - /* TODO worst case -- should actualy calc what we need here. */ - r_u->needed = sizeof(Service_info)+sizeof(pstring)*5; - DEBUG(10, ("_svcctl_query_service_config: NOT ENOUGH BUFFER ALLOCATED FOR RETURN DATA -- provided %d wanted %d\n", - q_u->buffer_size,r_u->needed)); - - return WERR_INSUFFICIENT_BUFFER; - } -#endif - if (!service_info) { - DEBUG(10, ("_svcctl_query_service_config : Can't find the service for the handle\n")); - return WERR_BADFID; - } - -#if 0 - if ( !(service_config = (SERVICE_CONFIG *)TALLOC_ZERO_P(p->mem_ctx, SERVICE_CONFIG)) ) - return WERR_NOMEM; -#endif - - r_u->config.service_type = SVCCTL_WIN32_OWN_PROC; - r_u->config.start_type = SVCCTL_DEMAND_START; - r_u->config.error_control = SVCCTL_SVC_ERROR_IGNORE; - r_u->config.tag_id = 0x00000000; - - /* Init the strings */ - - r_u->config.executablepath = TALLOC_ZERO_P(p->mem_ctx, UNISTR2); - r_u->config.loadordergroup = TALLOC_ZERO_P(p->mem_ctx, UNISTR2); - r_u->config.dependencies = TALLOC_ZERO_P(p->mem_ctx, UNISTR2); - r_u->config.startname = TALLOC_ZERO_P(p->mem_ctx, UNISTR2); - r_u->config.displayname = TALLOC_ZERO_P(p->mem_ctx, UNISTR2); - -#if 0 - pstrcpy(fullpathinfo,dyn_LIBDIR); - pstrcat(fullpathinfo,SVCCTL_SCRIPT_DIR); - pstrcat(fullpathinfo,service_info->filename); - /* Get and calculate the size of the fields. Note that we're still building the fields in the "too-small buffer case" - even though we throw it away. */ - - DEBUG(10, ("_svcctl_query_service_config: fullpath info [%s]\n",fullpathinfo)); - init_unistr2(r_u->config.executablepath,fullpathinfo,UNI_STR_TERMINATE); - init_unistr2(r_u->config.loadordergroup,"",UNI_STR_TERMINATE); - init_unistr2(r_u->config.dependencies,service_info->dependencies,UNI_STR_TERMINATE); - - /* TODO - if someone really cares, perhaps "LocalSystem" should be changed to something else here... */ - - init_unistr2(r_u->config.startname,"LocalSystem",UNI_STR_TERMINATE); - init_unistr2(r_u->config.displayname,service_info->servicename,UNI_STR_TERMINATE); -#endif - - needed_size = 0x04 + sizeof(SERVICE_CONFIG)+ 2*( - r_u->config.executablepath->uni_str_len + - r_u->config.loadordergroup->uni_str_len + - r_u->config.dependencies->uni_str_len + - r_u->config.startname->uni_str_len + - r_u->config.displayname->uni_str_len); - - DEBUG(10, ("_svcctl_query_service_config: ****** need to have a buffer of [%d], [%d] for struct \n",needed_size, - sizeof(SERVICE_CONFIG))); - DEBUG(10, ("\tsize of executable path : %d\n",r_u->config.executablepath->uni_str_len)); - DEBUG(10, ("\tsize of loadordergroup : %d\n", r_u->config.loadordergroup->uni_str_len)); - DEBUG(10, ("\tsize of dependencies : %d\n", r_u->config.dependencies->uni_str_len)); - DEBUG(10, ("\tsize of startname : %d\n", r_u->config.startname->uni_str_len)); - DEBUG(10, ("\tsize of displayname : %d\n", r_u->config.displayname->uni_str_len)); - - if (q_u->buffer_size < needed_size) { - /* have to report need more...*/ - r_u->needed = needed_size; - DEBUG(10, ("_svcctl_query_service_config: ****** zeroing strings for return\n")); - memset(&r_u->config,0,sizeof(SERVICE_CONFIG)); - DEBUG(10, ("_svcctl_query_service_config: Not enouh buffer provided for return -- provided %d wanted %d\n", - q_u->buffer_size,needed_size)); - return WERR_INSUFFICIENT_BUFFER; + if (buffer_size > q_u->buffer_size ) { + ZERO_STRUCTP( &r_u->config ); + return WERR_INSUFFICIENT_BUFFER; } - + return WERR_OK; } @@ -758,9 +650,8 @@ WERROR _svcctl_query_service_config( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CON WERROR _svcctl_query_service_config2( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CONFIG2 *q_u, SVCCTL_R_QUERY_SERVICE_CONFIG2 *r_u ) { - POLICY_HND *handle; - SERVICE_INFO *service_info; SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); + uint32 buffer_size; /* perform access checks */ @@ -773,55 +664,84 @@ WERROR _svcctl_query_service_config2( pipes_struct *p, SVCCTL_Q_QUERY_SERVICE_CO /* we have to set the outgoing buffer size to the same as the incoming buffer size (even in the case of failure */ - r_u->needed = q_u->buffer_size; - r_u->description = NULL; - r_u->returned = q_u->buffer_size; - r_u->offset = 4; + rpcbuf_init( &r_u->buffer, q_u->buffer_size, p->mem_ctx ); + r_u->needed = q_u->buffer_size; - handle = &(q_u->handle); + switch ( q_u->level ) { + case SERVICE_CONFIG_DESCRIPTION: + { + SERVICE_DESCRIPTION desc_buf; + const char *description; + + description = svcctl_lookup_description( info->name, p->pipe_user.nt_user_token ); + + ZERO_STRUCTP( &desc_buf ); - service_info = find_service_info_by_hnd(p, handle); + init_service_description_buffer( &desc_buf, description ); + svcctl_io_service_description( "", &desc_buf, &r_u->buffer, 0 ); + buffer_size = svcctl_sizeof_service_description( &desc_buf ); - if (!service_info) { - DEBUG(10, ("_svcctl_query_service_config2 : Can't find the service for the handle\n")); - return WERR_BADFID; - } - - /* - TODO - perhaps move the RPC_DATA_BLOB into the R_QUERY_SERVICE_CONFIG structure, and to the processing in here, vs - in the *r_query_config2 marshalling routine... - */ - -#if 0 - if (SERVICE_CONFIG_DESCRIPTION == q_u->info_level) { - if (service_info && service_info->shortdescription) { - /* length of the string, plus the terminator... */ - string_buffer_size = strlen(service_info->shortdescription)+1; - DEBUG(10, ("_svcctl_query_service_config: copying the description [%s] length [%d]\n", - service_info->shortdescription,string_buffer_size)); - - if (q_u->buffer_size >= ((string_buffer_size)*2+4)) { - r_u->description = TALLOC_ZERO_P(p->mem_ctx, UNISTR2); - if (!r_u->description) return WERR_NOMEM; - init_unistr2(r_u->description,service_info->shortdescription,UNI_STR_TERMINATE); - } + break; } - else { - string_buffer_size = 0; - } - DEBUG(10, ("_svcctl_query_service_config2: buffer needed is [%x], return buffer size is [%x]\n", - string_buffer_size,q_u->buffer_size)); - if (((string_buffer_size)*2+4) > q_u->buffer_size) { - r_u->needed = (string_buffer_size+1)*2+4; - DEBUG(10, ("_svcctl_query_service_config2: INSUFFICIENT BUFFER\n")); - return WERR_INSUFFICIENT_BUFFER; + break; + case SERVICE_CONFIG_FAILURE_ACTIONS: + { + SERVICE_FAILURE_ACTIONS actions; + + /* nothing to say...just service the request */ + + ZERO_STRUCTP( &actions ); + svcctl_io_service_fa( "", &actions, &r_u->buffer, 0 ); + buffer_size = svcctl_sizeof_service_fa( &actions ); + + break; } - DEBUG(10, ("_svcctl_query_service_config2: returning ok, needed is [%x], buffer size is [%x]\n", - r_u->needed,q_u->buffer_size)); + break; + + default: + return WERR_UNKNOWN_LEVEL; + } + + buffer_size += buffer_size % 4; + r_u->needed = (buffer_size > q_u->buffer_size) ? buffer_size : q_u->buffer_size; - return WERR_OK; - } -#endif + if (buffer_size > q_u->buffer_size ) + return WERR_INSUFFICIENT_BUFFER; - return WERR_ACCESS_DENIED; + return WERR_OK; +} + +/******************************************************************** +********************************************************************/ + +WERROR _svcctl_lock_service_db( pipes_struct *p, SVCCTL_Q_LOCK_SERVICE_DB *q_u, SVCCTL_R_LOCK_SERVICE_DB *r_u ) +{ + SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->handle ); + + /* perform access checks */ + + if ( !info || (info->type != SVC_HANDLE_IS_SCM) ) + return WERR_BADFID; + + if ( !(info->access_granted & SC_RIGHT_MGR_LOCK) ) + return WERR_ACCESS_DENIED; + + /* Just open a handle. Doesn't actually lock anything */ + + return create_open_service_handle( p, &r_u->h_lock, SVC_HANDLE_IS_DBLOCK, NULL, 0 ); +; +} + +/******************************************************************** +********************************************************************/ + +WERROR _svcctl_unlock_service_db( pipes_struct *p, SVCCTL_Q_UNLOCK_SERVICE_DB *q_u, SVCCTL_R_UNLOCK_SERVICE_DB *r_u ) +{ + SERVICE_INFO *info = find_service_info_by_hnd( p, &q_u->h_lock ); + + + if ( !info || (info->type != SVC_HANDLE_IS_DBLOCK) ) + return WERR_BADFID; + + return close_policy_hnd( p, &q_u->h_lock) ? WERR_OK : WERR_BADFID; } diff --git a/source3/rpcclient/cmd_dfs.c b/source3/rpcclient/cmd_dfs.c index 44e97f9881e..956dbfa4027 100644 --- a/source3/rpcclient/cmd_dfs.c +++ b/source3/rpcclient/cmd_dfs.c @@ -24,7 +24,7 @@ /* Check DFS is supported by the remote server */ -static NTSTATUS cmd_dfs_exist(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static NTSTATUS cmd_dfs_exist(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { BOOL dfs_exists; @@ -35,7 +35,7 @@ static NTSTATUS cmd_dfs_exist(struct cli_state *cli, TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } - result = cli_dfs_exist(cli, mem_ctx, &dfs_exists); + result = rpccli_dfs_exist(cli, mem_ctx, &dfs_exists); if (NT_STATUS_IS_OK(result)) printf("dfs is %spresent\n", dfs_exists ? "" : "not "); @@ -43,7 +43,7 @@ static NTSTATUS cmd_dfs_exist(struct cli_state *cli, TALLOC_CTX *mem_ctx, return result; } -static NTSTATUS cmd_dfs_add(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static NTSTATUS cmd_dfs_add(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS result; @@ -61,13 +61,13 @@ static NTSTATUS cmd_dfs_add(struct cli_state *cli, TALLOC_CTX *mem_ctx, sharename = argv[3]; comment = argv[4]; - result = cli_dfs_add(cli, mem_ctx, entrypath, servername, + result = rpccli_dfs_add(cli, mem_ctx, entrypath, servername, sharename, comment, flags); return result; } -static NTSTATUS cmd_dfs_remove(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static NTSTATUS cmd_dfs_remove(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS result; @@ -82,7 +82,7 @@ static NTSTATUS cmd_dfs_remove(struct cli_state *cli, TALLOC_CTX *mem_ctx, servername = argv[2]; sharename = argv[3]; - result = cli_dfs_remove(cli, mem_ctx, entrypath, servername, + result = rpccli_dfs_remove(cli, mem_ctx, entrypath, servername, sharename); return result; @@ -168,7 +168,7 @@ static void display_dfs_info_ctr(DFS_INFO_CTR *ctr) /* Enumerate dfs shares */ -static NTSTATUS cmd_dfs_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static NTSTATUS cmd_dfs_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { DFS_INFO_CTR ctr; @@ -183,7 +183,7 @@ static NTSTATUS cmd_dfs_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx, if (argc == 2) info_level = atoi(argv[1]); - result = cli_dfs_enum(cli, mem_ctx, info_level, &ctr); + result = rpccli_dfs_enum(cli, mem_ctx, info_level, &ctr); if (NT_STATUS_IS_OK(result)) display_dfs_info_ctr(&ctr); @@ -191,7 +191,7 @@ static NTSTATUS cmd_dfs_enum(struct cli_state *cli, TALLOC_CTX *mem_ctx, return result; } -static NTSTATUS cmd_dfs_getinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static NTSTATUS cmd_dfs_getinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS result; @@ -212,7 +212,7 @@ static NTSTATUS cmd_dfs_getinfo(struct cli_state *cli, TALLOC_CTX *mem_ctx, if (argc == 5) info_level = atoi(argv[4]); - result = cli_dfs_get_info(cli, mem_ctx, entrypath, servername, + result = rpccli_dfs_get_info(cli, mem_ctx, entrypath, servername, sharename, info_level, &ctr); if (NT_STATUS_IS_OK(result)) @@ -227,11 +227,11 @@ struct cmd_set dfs_commands[] = { { "DFS" }, - { "dfsexist", RPC_RTYPE_NTSTATUS, cmd_dfs_exist, NULL, PI_NETDFS, "Query DFS support", "" }, - { "dfsadd", RPC_RTYPE_NTSTATUS, cmd_dfs_add, NULL, PI_NETDFS, "Add a DFS share", "" }, - { "dfsremove", RPC_RTYPE_NTSTATUS, cmd_dfs_remove, NULL, PI_NETDFS, "Remove a DFS share", "" }, - { "dfsgetinfo",RPC_RTYPE_NTSTATUS, cmd_dfs_getinfo, NULL, PI_NETDFS, "Query DFS share info", "" }, - { "dfsenum", RPC_RTYPE_NTSTATUS, cmd_dfs_enum, NULL, PI_NETDFS, "Enumerate dfs shares", "" }, + { "dfsexist", RPC_RTYPE_NTSTATUS, cmd_dfs_exist, NULL, PI_NETDFS, NULL, "Query DFS support", "" }, + { "dfsadd", RPC_RTYPE_NTSTATUS, cmd_dfs_add, NULL, PI_NETDFS, NULL, "Add a DFS share", "" }, + { "dfsremove", RPC_RTYPE_NTSTATUS, cmd_dfs_remove, NULL, PI_NETDFS, NULL, "Remove a DFS share", "" }, + { "dfsgetinfo",RPC_RTYPE_NTSTATUS, cmd_dfs_getinfo, NULL, PI_NETDFS, NULL, "Query DFS share info", "" }, + { "dfsenum", RPC_RTYPE_NTSTATUS, cmd_dfs_enum, NULL, PI_NETDFS, NULL, "Enumerate dfs shares", "" }, { NULL } }; diff --git a/source3/rpcclient/cmd_ds.c b/source3/rpcclient/cmd_ds.c index 0a1fd7e012b..951d18a710e 100644 --- a/source3/rpcclient/cmd_ds.c +++ b/source3/rpcclient/cmd_ds.c @@ -24,14 +24,14 @@ /* Look up domain related information on a remote host */ -static NTSTATUS cmd_ds_dsrole_getprimarydominfo(struct cli_state *cli, +static NTSTATUS cmd_ds_dsrole_getprimarydominfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS result; DS_DOMINFO_CTR ctr; - result = cli_ds_getprimarydominfo( cli, mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr ); + result = rpccli_ds_getprimarydominfo( cli, mem_ctx, DsRolePrimaryDomainInfoBasic, &ctr ); if ( NT_STATUS_IS_OK(result) ) { printf ("Machine Role = [%d]\n", ctr.basic->machine_role); @@ -47,7 +47,7 @@ static NTSTATUS cmd_ds_dsrole_getprimarydominfo(struct cli_state *cli, return result; } -static NTSTATUS cmd_ds_enum_domain_trusts(struct cli_state *cli, +static NTSTATUS cmd_ds_enum_domain_trusts(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -57,7 +57,7 @@ static NTSTATUS cmd_ds_enum_domain_trusts(struct cli_state *cli, unsigned int num_domains = 0; int i; - result = cli_ds_enum_domain_trusts( cli, mem_ctx, cli->desthost, flags, + result = rpccli_ds_enum_domain_trusts( cli, mem_ctx, cli->cli->desthost, flags, &trusts, &num_domains ); printf( "%d domains returned\n", num_domains ); @@ -74,8 +74,8 @@ struct cmd_set ds_commands[] = { { "LSARPC-DS" }, - { "dsroledominfo", RPC_RTYPE_NTSTATUS, cmd_ds_dsrole_getprimarydominfo, NULL, PI_LSARPC_DS, "Get Primary Domain Information", "" }, - { "dsenumdomtrusts", RPC_RTYPE_NTSTATUS, cmd_ds_enum_domain_trusts, NULL, PI_NETLOGON, "Enumerate all trusted domains in an AD forest", "" }, + { "dsroledominfo", RPC_RTYPE_NTSTATUS, cmd_ds_dsrole_getprimarydominfo, NULL, PI_LSARPC_DS, NULL, "Get Primary Domain Information", "" }, + { "dsenumdomtrusts", RPC_RTYPE_NTSTATUS, cmd_ds_enum_domain_trusts, NULL, PI_NETLOGON, NULL, "Enumerate all trusted domains in an AD forest", "" }, - { NULL } +{ NULL } }; diff --git a/source3/rpcclient/cmd_echo.c b/source3/rpcclient/cmd_echo.c index fce8e4c7b8f..6d608ebaf10 100644 --- a/source3/rpcclient/cmd_echo.c +++ b/source3/rpcclient/cmd_echo.c @@ -22,7 +22,7 @@ #include "includes.h" #include "rpcclient.h" -static NTSTATUS cmd_echo_add_one(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static NTSTATUS cmd_echo_add_one(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { uint32 request = 1, response; @@ -36,7 +36,7 @@ static NTSTATUS cmd_echo_add_one(struct cli_state *cli, TALLOC_CTX *mem_ctx, if (argc == 2) request = atoi(argv[1]); - result = cli_echo_add_one(cli, mem_ctx, request, &response); + result = rpccli_echo_add_one(cli, mem_ctx, request, &response); if (!NT_STATUS_IS_OK(result)) goto done; @@ -47,7 +47,7 @@ done: return result; } -static NTSTATUS cmd_echo_data(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static NTSTATUS cmd_echo_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { uint32 size, i; @@ -65,7 +65,7 @@ static NTSTATUS cmd_echo_data(struct cli_state *cli, TALLOC_CTX *mem_ctx, for (i = 0; i < size; i++) in_data[i] = i & 0xff; - result = cli_echo_data(cli, mem_ctx, size, in_data, &out_data); + result = rpccli_echo_data(cli, mem_ctx, size, in_data, &out_data); if (!NT_STATUS_IS_OK(result)) goto done; @@ -84,7 +84,7 @@ done: return result; } -static NTSTATUS cmd_echo_source_data(struct cli_state *cli, +static NTSTATUS cmd_echo_source_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -99,7 +99,7 @@ static NTSTATUS cmd_echo_source_data(struct cli_state *cli, size = atoi(argv[1]); - result = cli_echo_source_data(cli, mem_ctx, size, &out_data); + result = rpccli_echo_source_data(cli, mem_ctx, size, &out_data); if (!NT_STATUS_IS_OK(result)) goto done; @@ -116,7 +116,7 @@ done: return result; } -static NTSTATUS cmd_echo_sink_data(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static NTSTATUS cmd_echo_sink_data(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { uint32 size, i; @@ -134,7 +134,7 @@ static NTSTATUS cmd_echo_sink_data(struct cli_state *cli, TALLOC_CTX *mem_ctx, for (i = 0; i < size; i++) in_data[i] = i & 0xff; - result = cli_echo_sink_data(cli, mem_ctx, size, in_data); + result = rpccli_echo_sink_data(cli, mem_ctx, size, in_data); if (!NT_STATUS_IS_OK(result)) goto done; @@ -151,9 +151,9 @@ struct cmd_set echo_commands[] = { { "ECHO" }, - { "echoaddone", RPC_RTYPE_NTSTATUS, cmd_echo_add_one, NULL, PI_ECHO, "Add one to a number", "" }, - { "echodata", RPC_RTYPE_NTSTATUS, cmd_echo_data, NULL, PI_ECHO, "Echo data", "" }, - { "sinkdata", RPC_RTYPE_NTSTATUS, cmd_echo_sink_data, NULL, PI_ECHO, "Sink data", "" }, - { "sourcedata", RPC_RTYPE_NTSTATUS, cmd_echo_source_data, NULL, PI_ECHO, "Source data", "" }, + { "echoaddone", RPC_RTYPE_NTSTATUS, cmd_echo_add_one, NULL, PI_ECHO, NULL, "Add one to a number", "" }, + { "echodata", RPC_RTYPE_NTSTATUS, cmd_echo_data, NULL, PI_ECHO, NULL, "Echo data", "" }, + { "sinkdata", RPC_RTYPE_NTSTATUS, cmd_echo_sink_data, NULL, PI_ECHO, NULL, "Sink data", "" }, + { "sourcedata", RPC_RTYPE_NTSTATUS, cmd_echo_source_data, NULL, PI_ECHO, NULL, "Source data", "" }, { NULL } }; diff --git a/source3/rpcclient/cmd_lsarpc.c b/source3/rpcclient/cmd_lsarpc.c index b01f6392477..00ed515245b 100644 --- a/source3/rpcclient/cmd_lsarpc.c +++ b/source3/rpcclient/cmd_lsarpc.c @@ -26,7 +26,7 @@ /* useful function to allow entering a name instead of a SID and * looking it up automatically */ -static NTSTATUS name_to_sid(struct cli_state *cli, +static NTSTATUS name_to_sid(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, DOM_SID *sid, const char *name) { @@ -41,17 +41,17 @@ static NTSTATUS name_to_sid(struct cli_state *cli, return NT_STATUS_OK; } - result = cli_lsa_open_policy(cli, mem_ctx, True, + result = rpccli_lsa_open_policy(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_lookup_names(cli, mem_ctx, &pol, 1, &name, &sids, &sid_types); + result = rpccli_lsa_lookup_names(cli, mem_ctx, &pol, 1, &name, &sids, &sid_types); if (!NT_STATUS_IS_OK(result)) goto done; - cli_lsa_close(cli, mem_ctx, &pol); + rpccli_lsa_close(cli, mem_ctx, &pol); *sid = sids[0]; @@ -62,7 +62,7 @@ done: /* Look up domain related information on a remote host */ -static NTSTATUS cmd_lsa_query_info_policy(struct cli_state *cli, +static NTSTATUS cmd_lsa_query_info_policy(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -88,25 +88,25 @@ static NTSTATUS cmd_lsa_query_info_policy(struct cli_state *cli, /* Lookup info policy */ switch (info_class) { case 12: - result = cli_lsa_open_policy2(cli, mem_ctx, True, + result = rpccli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_query_info_policy2(cli, mem_ctx, &pol, + result = rpccli_lsa_query_info_policy2(cli, mem_ctx, &pol, info_class, &domain_name, &dns_name, &forest_name, &dom_guid, &dom_sid); break; default: - result = cli_lsa_open_policy(cli, mem_ctx, True, + result = rpccli_lsa_open_policy(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, + result = rpccli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class, &domain_name, &dom_sid); } @@ -130,13 +130,16 @@ static NTSTATUS cmd_lsa_query_info_policy(struct cli_state *cli, printf("domain GUID is "); smb_uuid_string_static(*dom_guid); } + + rpccli_lsa_close(cli, mem_ctx, &pol); + done: return result; } /* Resolve a list of names to a list of sids */ -static NTSTATUS cmd_lsa_lookup_names(struct cli_state *cli, +static NTSTATUS cmd_lsa_lookup_names(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -151,14 +154,14 @@ static NTSTATUS cmd_lsa_lookup_names(struct cli_state *cli, return NT_STATUS_OK; } - result = cli_lsa_open_policy(cli, mem_ctx, True, + result = rpccli_lsa_open_policy(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_lookup_names(cli, mem_ctx, &pol, argc - 1, + result = rpccli_lsa_lookup_names(cli, mem_ctx, &pol, argc - 1, (const char**)(argv + 1), &sids, &types); if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) != @@ -176,7 +179,7 @@ static NTSTATUS cmd_lsa_lookup_names(struct cli_state *cli, sid_type_lookup(types[i]), types[i]); } - cli_lsa_close(cli, mem_ctx, &pol); + rpccli_lsa_close(cli, mem_ctx, &pol); done: return result; @@ -184,7 +187,7 @@ static NTSTATUS cmd_lsa_lookup_names(struct cli_state *cli, /* Resolve a list of SIDs to a list of names */ -static NTSTATUS cmd_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static NTSTATUS cmd_lsa_lookup_sids(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { POLICY_HND pol; @@ -200,7 +203,7 @@ static NTSTATUS cmd_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } - result = cli_lsa_open_policy(cli, mem_ctx, True, + result = rpccli_lsa_open_policy(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); @@ -224,7 +227,7 @@ static NTSTATUS cmd_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Lookup the SIDs */ - result = cli_lsa_lookup_sids(cli, mem_ctx, &pol, argc - 1, sids, + result = rpccli_lsa_lookup_sids(cli, mem_ctx, &pol, argc - 1, sids, &domains, &names, &types); if (!NT_STATUS_IS_OK(result) && NT_STATUS_V(result) != @@ -244,7 +247,7 @@ static NTSTATUS cmd_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx, names[i] ? names[i] : "*unknown*", types[i]); } - cli_lsa_close(cli, mem_ctx, &pol); + rpccli_lsa_close(cli, mem_ctx, &pol); done: return result; @@ -252,7 +255,7 @@ static NTSTATUS cmd_lsa_lookup_sids(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Enumerate list of trusted domains */ -static NTSTATUS cmd_lsa_enum_trust_dom(struct cli_state *cli, +static NTSTATUS cmd_lsa_enum_trust_dom(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -275,7 +278,7 @@ static NTSTATUS cmd_lsa_enum_trust_dom(struct cli_state *cli, enum_ctx = atoi(argv[2]); } - result = cli_lsa_open_policy(cli, mem_ctx, True, + result = rpccli_lsa_open_policy(cli, mem_ctx, True, POLICY_VIEW_LOCAL_INFORMATION, &pol); @@ -288,7 +291,7 @@ static NTSTATUS cmd_lsa_enum_trust_dom(struct cli_state *cli, /* Lookup list of trusted domains */ - result = cli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx, + result = rpccli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx, &num_domains, &domain_names, &domain_sids); if (!NT_STATUS_IS_OK(result) && @@ -307,13 +310,14 @@ static NTSTATUS cmd_lsa_enum_trust_dom(struct cli_state *cli, } } + rpccli_lsa_close(cli, mem_ctx, &pol); done: return result; } /* Enumerates privileges */ -static NTSTATUS cmd_lsa_enum_privilege(struct cli_state *cli, +static NTSTATUS cmd_lsa_enum_privilege(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -339,14 +343,14 @@ static NTSTATUS cmd_lsa_enum_privilege(struct cli_state *cli, if (argc==3) pref_max_length=atoi(argv[2]); - result = cli_lsa_open_policy(cli, mem_ctx, True, + result = rpccli_lsa_open_policy(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_enum_privilege(cli, mem_ctx, &pol, &enum_context, pref_max_length, + result = rpccli_lsa_enum_privilege(cli, mem_ctx, &pol, &enum_context, pref_max_length, &count, &privs_name, &privs_high, &privs_low); if (!NT_STATUS_IS_OK(result)) @@ -360,13 +364,14 @@ static NTSTATUS cmd_lsa_enum_privilege(struct cli_state *cli, privs_high[i], privs_low[i], privs_high[i], privs_low[i]); } + rpccli_lsa_close(cli, mem_ctx, &pol); done: return result; } /* Get privilege name */ -static NTSTATUS cmd_lsa_get_dispname(struct cli_state *cli, +static NTSTATUS cmd_lsa_get_dispname(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -383,14 +388,14 @@ static NTSTATUS cmd_lsa_get_dispname(struct cli_state *cli, return NT_STATUS_OK; } - result = cli_lsa_open_policy(cli, mem_ctx, True, + result = rpccli_lsa_open_policy(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_get_dispname(cli, mem_ctx, &pol, argv[1], lang_id, lang_id_sys, description, &lang_id_desc); + result = rpccli_lsa_get_dispname(cli, mem_ctx, &pol, argv[1], lang_id, lang_id_sys, description, &lang_id_desc); if (!NT_STATUS_IS_OK(result)) goto done; @@ -398,13 +403,14 @@ static NTSTATUS cmd_lsa_get_dispname(struct cli_state *cli, /* Print results */ printf("%s -> %s (language: 0x%x)\n", argv[1], description, lang_id_desc); + rpccli_lsa_close(cli, mem_ctx, &pol); done: return result; } /* Enumerate the LSA SIDS */ -static NTSTATUS cmd_lsa_enum_sids(struct cli_state *cli, +static NTSTATUS cmd_lsa_enum_sids(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -428,14 +434,14 @@ static NTSTATUS cmd_lsa_enum_sids(struct cli_state *cli, if (argc==3) pref_max_length=atoi(argv[2]); - result = cli_lsa_open_policy(cli, mem_ctx, True, + result = rpccli_lsa_open_policy(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_enum_sids(cli, mem_ctx, &pol, &enum_context, pref_max_length, + result = rpccli_lsa_enum_sids(cli, mem_ctx, &pol, &enum_context, pref_max_length, &count, &sids); if (!NT_STATUS_IS_OK(result)) @@ -451,13 +457,14 @@ static NTSTATUS cmd_lsa_enum_sids(struct cli_state *cli, printf("%s\n", sid_str); } + rpccli_lsa_close(cli, mem_ctx, &pol); done: return result; } /* Create a new account */ -static NTSTATUS cmd_lsa_create_account(struct cli_state *cli, +static NTSTATUS cmd_lsa_create_account(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -477,14 +484,14 @@ static NTSTATUS cmd_lsa_create_account(struct cli_state *cli, if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_open_policy2(cli, mem_ctx, True, + result = rpccli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &dom_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_create_account(cli, mem_ctx, &dom_pol, &sid, des_access, &user_pol); + result = rpccli_lsa_create_account(cli, mem_ctx, &dom_pol, &sid, des_access, &user_pol); if (!NT_STATUS_IS_OK(result)) goto done; @@ -492,6 +499,7 @@ static NTSTATUS cmd_lsa_create_account(struct cli_state *cli, printf("Account for SID %s successfully created\n\n", argv[1]); result = NT_STATUS_OK; + rpccli_lsa_close(cli, mem_ctx, &dom_pol); done: return result; } @@ -499,7 +507,7 @@ static NTSTATUS cmd_lsa_create_account(struct cli_state *cli, /* Enumerate the privileges of an SID */ -static NTSTATUS cmd_lsa_enum_privsaccounts(struct cli_state *cli, +static NTSTATUS cmd_lsa_enum_privsaccounts(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -522,19 +530,19 @@ static NTSTATUS cmd_lsa_enum_privsaccounts(struct cli_state *cli, if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_open_policy2(cli, mem_ctx, True, + result = rpccli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &dom_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_open_account(cli, mem_ctx, &dom_pol, &sid, access_desired, &user_pol); + result = rpccli_lsa_open_account(cli, mem_ctx, &dom_pol, &sid, access_desired, &user_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_enum_privsaccount(cli, mem_ctx, &user_pol, &count, &set); + result = rpccli_lsa_enum_privsaccount(cli, mem_ctx, &user_pol, &count, &set); if (!NT_STATUS_IS_OK(result)) goto done; @@ -547,6 +555,7 @@ static NTSTATUS cmd_lsa_enum_privsaccounts(struct cli_state *cli, printf("%u\t%u\t%u\n", set[i].luid.high, set[i].luid.low, set[i].attr); } + rpccli_lsa_close(cli, mem_ctx, &dom_pol); done: return result; } @@ -554,7 +563,7 @@ static NTSTATUS cmd_lsa_enum_privsaccounts(struct cli_state *cli, /* Enumerate the privileges of an SID via LsaEnumerateAccountRights */ -static NTSTATUS cmd_lsa_enum_acct_rights(struct cli_state *cli, +static NTSTATUS cmd_lsa_enum_acct_rights(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -576,14 +585,14 @@ static NTSTATUS cmd_lsa_enum_acct_rights(struct cli_state *cli, if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_open_policy2(cli, mem_ctx, True, + result = rpccli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &dom_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_enum_account_rights(cli, mem_ctx, &dom_pol, &sid, &count, &rights); + result = rpccli_lsa_enum_account_rights(cli, mem_ctx, &dom_pol, &sid, &count, &rights); if (!NT_STATUS_IS_OK(result)) goto done; @@ -594,6 +603,7 @@ static NTSTATUS cmd_lsa_enum_acct_rights(struct cli_state *cli, printf("\t%s\n", rights[i]); } + rpccli_lsa_close(cli, mem_ctx, &dom_pol); done: return result; } @@ -601,7 +611,7 @@ static NTSTATUS cmd_lsa_enum_acct_rights(struct cli_state *cli, /* add some privileges to a SID via LsaAddAccountRights */ -static NTSTATUS cmd_lsa_add_acct_rights(struct cli_state *cli, +static NTSTATUS cmd_lsa_add_acct_rights(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -619,19 +629,20 @@ static NTSTATUS cmd_lsa_add_acct_rights(struct cli_state *cli, if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_open_policy2(cli, mem_ctx, True, + result = rpccli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &dom_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_add_account_rights(cli, mem_ctx, &dom_pol, sid, + result = rpccli_lsa_add_account_rights(cli, mem_ctx, &dom_pol, sid, argc-2, argv+2); if (!NT_STATUS_IS_OK(result)) goto done; + rpccli_lsa_close(cli, mem_ctx, &dom_pol); done: return result; } @@ -639,7 +650,7 @@ static NTSTATUS cmd_lsa_add_acct_rights(struct cli_state *cli, /* remove some privileges to a SID via LsaRemoveAccountRights */ -static NTSTATUS cmd_lsa_remove_acct_rights(struct cli_state *cli, +static NTSTATUS cmd_lsa_remove_acct_rights(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -657,19 +668,21 @@ static NTSTATUS cmd_lsa_remove_acct_rights(struct cli_state *cli, if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_open_policy2(cli, mem_ctx, True, + result = rpccli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &dom_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_remove_account_rights(cli, mem_ctx, &dom_pol, sid, + result = rpccli_lsa_remove_account_rights(cli, mem_ctx, &dom_pol, sid, False, argc-2, argv+2); if (!NT_STATUS_IS_OK(result)) goto done; + rpccli_lsa_close(cli, mem_ctx, &dom_pol); + done: return result; } @@ -677,7 +690,7 @@ static NTSTATUS cmd_lsa_remove_acct_rights(struct cli_state *cli, /* Get a privilege value given its name */ -static NTSTATUS cmd_lsa_lookup_priv_value(struct cli_state *cli, +static NTSTATUS cmd_lsa_lookup_priv_value(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -690,14 +703,14 @@ static NTSTATUS cmd_lsa_lookup_priv_value(struct cli_state *cli, return NT_STATUS_OK; } - result = cli_lsa_open_policy2(cli, mem_ctx, True, + result = rpccli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_lookup_priv_value(cli, mem_ctx, &pol, argv[1], &luid); + result = rpccli_lsa_lookup_priv_value(cli, mem_ctx, &pol, argv[1], &luid); if (!NT_STATUS_IS_OK(result)) goto done; @@ -706,13 +719,14 @@ static NTSTATUS cmd_lsa_lookup_priv_value(struct cli_state *cli, printf("%u:%u (0x%x:0x%x)\n", luid.high, luid.low, luid.high, luid.low); + rpccli_lsa_close(cli, mem_ctx, &pol); done: return result; } /* Query LSA security object */ -static NTSTATUS cmd_lsa_query_secobj(struct cli_state *cli, +static NTSTATUS cmd_lsa_query_secobj(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -726,14 +740,14 @@ static NTSTATUS cmd_lsa_query_secobj(struct cli_state *cli, return NT_STATUS_OK; } - result = cli_lsa_open_policy2(cli, mem_ctx, True, + result = rpccli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_query_secobj(cli, mem_ctx, &pol, sec_info, &sdb); + result = rpccli_lsa_query_secobj(cli, mem_ctx, &pol, sec_info, &sdb); if (!NT_STATUS_IS_OK(result)) goto done; @@ -742,6 +756,7 @@ static NTSTATUS cmd_lsa_query_secobj(struct cli_state *cli, display_sec_desc(sdb->sec); + rpccli_lsa_close(cli, mem_ctx, &pol); done: return result; } @@ -800,7 +815,7 @@ static void display_trust_dom_info(LSA_TRUSTED_DOMAIN_INFO *info, uint32 info_cl } } -static NTSTATUS cmd_lsa_query_trustdominfobysid(struct cli_state *cli, +static NTSTATUS cmd_lsa_query_trustdominfobysid(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -823,12 +838,12 @@ static NTSTATUS cmd_lsa_query_trustdominfobysid(struct cli_state *cli, if (argc == 3) info_class = atoi(argv[2]); - result = cli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol); + result = rpccli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_query_trusted_domain_info_by_sid(cli, mem_ctx, &pol, + result = rpccli_lsa_query_trusted_domain_info_by_sid(cli, mem_ctx, &pol, info_class, &dom_sid, &info); if (!NT_STATUS_IS_OK(result)) @@ -838,12 +853,12 @@ static NTSTATUS cmd_lsa_query_trustdominfobysid(struct cli_state *cli, done: if (&pol) - cli_lsa_close(cli, mem_ctx, &pol); + rpccli_lsa_close(cli, mem_ctx, &pol); return result; } -static NTSTATUS cmd_lsa_query_trustdominfobyname(struct cli_state *cli, +static NTSTATUS cmd_lsa_query_trustdominfobyname(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -861,12 +876,12 @@ static NTSTATUS cmd_lsa_query_trustdominfobyname(struct cli_state *cli, if (argc == 3) info_class = atoi(argv[2]); - result = cli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol); + result = rpccli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_query_trusted_domain_info_by_name(cli, mem_ctx, &pol, + result = rpccli_lsa_query_trusted_domain_info_by_name(cli, mem_ctx, &pol, info_class, argv[1], &info); if (!NT_STATUS_IS_OK(result)) @@ -876,12 +891,12 @@ static NTSTATUS cmd_lsa_query_trustdominfobyname(struct cli_state *cli, done: if (&pol) - cli_lsa_close(cli, mem_ctx, &pol); + rpccli_lsa_close(cli, mem_ctx, &pol); return result; } -static NTSTATUS cmd_lsa_query_trustdominfo(struct cli_state *cli, +static NTSTATUS cmd_lsa_query_trustdominfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -904,18 +919,18 @@ static NTSTATUS cmd_lsa_query_trustdominfo(struct cli_state *cli, if (argc == 3) info_class = atoi(argv[2]); - result = cli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol); + result = rpccli_lsa_open_policy2(cli, mem_ctx, True, access_mask, &pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_open_trusted_domain(cli, mem_ctx, &pol, + result = rpccli_lsa_open_trusted_domain(cli, mem_ctx, &pol, &dom_sid, access_mask, &trustdom_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_lsa_query_trusted_domain_info(cli, mem_ctx, &trustdom_pol, + result = rpccli_lsa_query_trusted_domain_info(cli, mem_ctx, &trustdom_pol, info_class, &dom_sid, &info); if (!NT_STATUS_IS_OK(result)) @@ -925,7 +940,7 @@ static NTSTATUS cmd_lsa_query_trustdominfo(struct cli_state *cli, done: if (&pol) - cli_lsa_close(cli, mem_ctx, &pol); + rpccli_lsa_close(cli, mem_ctx, &pol); return result; } @@ -938,27 +953,27 @@ struct cmd_set lsarpc_commands[] = { { "LSARPC" }, - { "lsaquery", RPC_RTYPE_NTSTATUS, cmd_lsa_query_info_policy, NULL, PI_LSARPC, "Query info policy", "" }, - { "lookupsids", RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_sids, NULL, PI_LSARPC, "Convert SIDs to names", "" }, - { "lookupnames", RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_names, NULL, PI_LSARPC, "Convert names to SIDs", "" }, - { "enumtrust", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_trust_dom, NULL, PI_LSARPC, "Enumerate trusted domains", "Usage: [preferred max number] [enum context (0)]" }, - { "enumprivs", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_privilege, NULL, PI_LSARPC, "Enumerate privileges", "" }, - { "getdispname", RPC_RTYPE_NTSTATUS, cmd_lsa_get_dispname, NULL, PI_LSARPC, "Get the privilege name", "" }, - { "lsaenumsid", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_sids, NULL, PI_LSARPC, "Enumerate the LSA SIDS", "" }, - { "lsacreateaccount", RPC_RTYPE_NTSTATUS, cmd_lsa_create_account, NULL, PI_LSARPC, "Create a new lsa account", "" }, - { "lsaenumprivsaccount", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_privsaccounts, NULL, PI_LSARPC, "Enumerate the privileges of an SID", "" }, - { "lsaenumacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_acct_rights, NULL, PI_LSARPC, "Enumerate the rights of an SID", "" }, + { "lsaquery", RPC_RTYPE_NTSTATUS, cmd_lsa_query_info_policy, NULL, PI_LSARPC, NULL, "Query info policy", "" }, + { "lookupsids", RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_sids, NULL, PI_LSARPC, NULL, "Convert SIDs to names", "" }, + { "lookupnames", RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_names, NULL, PI_LSARPC, NULL, "Convert names to SIDs", "" }, + { "enumtrust", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_trust_dom, NULL, PI_LSARPC, NULL, "Enumerate trusted domains", "Usage: [preferred max number] [enum context (0)]" }, + { "enumprivs", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_privilege, NULL, PI_LSARPC, NULL, "Enumerate privileges", "" }, + { "getdispname", RPC_RTYPE_NTSTATUS, cmd_lsa_get_dispname, NULL, PI_LSARPC, NULL, "Get the privilege name", "" }, + { "lsaenumsid", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_sids, NULL, PI_LSARPC, NULL, "Enumerate the LSA SIDS", "" }, + { "lsacreateaccount", RPC_RTYPE_NTSTATUS, cmd_lsa_create_account, NULL, PI_LSARPC, NULL, "Create a new lsa account", "" }, + { "lsaenumprivsaccount", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_privsaccounts, NULL, PI_LSARPC, NULL, "Enumerate the privileges of an SID", "" }, + { "lsaenumacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_enum_acct_rights, NULL, PI_LSARPC, NULL, "Enumerate the rights of an SID", "" }, #if 0 { "lsaaddpriv", RPC_RTYPE_NTSTATUS, cmd_lsa_add_priv, NULL, PI_LSARPC, "Assign a privilege to a SID", "" }, { "lsadelpriv", RPC_RTYPE_NTSTATUS, cmd_lsa_del_priv, NULL, PI_LSARPC, "Revoke a privilege from a SID", "" }, #endif - { "lsaaddacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_add_acct_rights, NULL, PI_LSARPC, "Add rights to an account", "" }, - { "lsaremoveacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_remove_acct_rights, NULL, PI_LSARPC, "Remove rights from an account", "" }, - { "lsalookupprivvalue", RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_priv_value, NULL, PI_LSARPC, "Get a privilege value given its name", "" }, - { "lsaquerysecobj", RPC_RTYPE_NTSTATUS, cmd_lsa_query_secobj, NULL, PI_LSARPC, "Query LSA security object", "" }, - { "lsaquerytrustdominfo",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfo, NULL, PI_LSARPC, "Query LSA trusted domains info (given a SID)", "" }, - { "lsaquerytrustdominfobyname",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfobyname, NULL, PI_LSARPC, "Query LSA trusted domains info (given a name), only works for Windows > 2k", "" }, - { "lsaquerytrustdominfobysid",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfobysid, NULL, PI_LSARPC, "Query LSA trusted domains info (given a SID)", "" }, + { "lsaaddacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_add_acct_rights, NULL, PI_LSARPC, NULL, "Add rights to an account", "" }, + { "lsaremoveacctrights", RPC_RTYPE_NTSTATUS, cmd_lsa_remove_acct_rights, NULL, PI_LSARPC, NULL, "Remove rights from an account", "" }, + { "lsalookupprivvalue", RPC_RTYPE_NTSTATUS, cmd_lsa_lookup_priv_value, NULL, PI_LSARPC, NULL, "Get a privilege value given its name", "" }, + { "lsaquerysecobj", RPC_RTYPE_NTSTATUS, cmd_lsa_query_secobj, NULL, PI_LSARPC, NULL, "Query LSA security object", "" }, + { "lsaquerytrustdominfo",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfo, NULL, PI_LSARPC, NULL, "Query LSA trusted domains info (given a SID)", "" }, + { "lsaquerytrustdominfobyname",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfobyname, NULL, PI_LSARPC, NULL, "Query LSA trusted domains info (given a name), only works for Windows > 2k", "" }, + { "lsaquerytrustdominfobysid",RPC_RTYPE_NTSTATUS, cmd_lsa_query_trustdominfobysid, NULL, PI_LSARPC, NULL, "Query LSA trusted domains info (given a SID)", "" }, { NULL } }; diff --git a/source3/rpcclient/cmd_netlogon.c b/source3/rpcclient/cmd_netlogon.c index b55306ddc88..153daa5cf2d 100644 --- a/source3/rpcclient/cmd_netlogon.c +++ b/source3/rpcclient/cmd_netlogon.c @@ -22,7 +22,7 @@ #include "includes.h" #include "rpcclient.h" -static NTSTATUS cmd_netlogon_logon_ctrl2(struct cli_state *cli, +static NTSTATUS cmd_netlogon_logon_ctrl2(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -34,7 +34,7 @@ static NTSTATUS cmd_netlogon_logon_ctrl2(struct cli_state *cli, return NT_STATUS_OK; } - result = cli_netlogon_logon_ctrl2(cli, mem_ctx, query_level); + result = rpccli_netlogon_logon_ctrl2(cli, mem_ctx, query_level); if (!NT_STATUS_IS_OK(result)) goto done; @@ -45,7 +45,7 @@ static NTSTATUS cmd_netlogon_logon_ctrl2(struct cli_state *cli, return result; } -static NTSTATUS cmd_netlogon_getdcname(struct cli_state *cli, +static NTSTATUS cmd_netlogon_getdcname(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -57,7 +57,7 @@ static NTSTATUS cmd_netlogon_getdcname(struct cli_state *cli, return NT_STATUS_OK; } - result = cli_netlogon_getdcname(cli, mem_ctx, argv[1], dcname); + result = rpccli_netlogon_getdcname(cli, mem_ctx, cli->cli->desthost, argv[1], dcname); if (!NT_STATUS_IS_OK(result)) goto done; @@ -70,7 +70,7 @@ static NTSTATUS cmd_netlogon_getdcname(struct cli_state *cli, return result; } -static NTSTATUS cmd_netlogon_logon_ctrl(struct cli_state *cli, +static NTSTATUS cmd_netlogon_logon_ctrl(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -166,7 +166,7 @@ static void display_sam_sync(uint32 num_deltas, SAM_DELTA_HDR *hdr_deltas, /* Perform sam synchronisation */ -static NTSTATUS cmd_netlogon_sam_sync(struct cli_state *cli, +static NTSTATUS cmd_netlogon_sam_sync(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -174,7 +174,6 @@ static NTSTATUS cmd_netlogon_sam_sync(struct cli_state *cli, uint32 database_id = 0, num_deltas; SAM_DELTA_HDR *hdr_deltas; SAM_DELTA_CTR *deltas; - DOM_CRED ret_creds; if (argc > 2) { fprintf(stderr, "Usage: %s [database_id]\n", argv[0]); @@ -184,12 +183,9 @@ static NTSTATUS cmd_netlogon_sam_sync(struct cli_state *cli, if (argc == 2) database_id = atoi(argv[1]); - /* on first call the returnAuthenticator is empty */ - memset(&ret_creds, 0, sizeof(ret_creds)); - /* Synchronise sam database */ - result = cli_netlogon_sam_sync(cli, mem_ctx, &ret_creds, database_id, + result = rpccli_netlogon_sam_sync(cli, mem_ctx, database_id, 0, &num_deltas, &hdr_deltas, &deltas); if (!NT_STATUS_IS_OK(result)) @@ -205,7 +201,7 @@ static NTSTATUS cmd_netlogon_sam_sync(struct cli_state *cli, /* Perform sam delta synchronisation */ -static NTSTATUS cmd_netlogon_sam_deltas(struct cli_state *cli, +static NTSTATUS cmd_netlogon_sam_deltas(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -226,7 +222,7 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct cli_state *cli, seqnum.low = tmp & 0xffff; seqnum.high = 0; - result = cli_netlogon_sam_deltas(cli, mem_ctx, database_id, + result = rpccli_netlogon_sam_deltas(cli, mem_ctx, database_id, seqnum, &num_deltas, &hdr_deltas, &deltas); @@ -243,7 +239,7 @@ static NTSTATUS cmd_netlogon_sam_deltas(struct cli_state *cli, /* Log on a domain user */ -static NTSTATUS cmd_netlogon_sam_logon(struct cli_state *cli, +static NTSTATUS cmd_netlogon_sam_logon(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -252,7 +248,6 @@ static NTSTATUS cmd_netlogon_sam_logon(struct cli_state *cli, const char *username, *password; uint32 neg_flags = 0x000001ff; int auth_level = 2; - DOM_CRED ret_creds; /* Check arguments */ @@ -277,12 +272,8 @@ static NTSTATUS cmd_netlogon_sam_logon(struct cli_state *cli, /* Perform the sam logon */ - ZERO_STRUCT(ret_creds); + result = rpccli_netlogon_sam_logon(cli, mem_ctx, lp_workgroup(), username, password, logon_type); - result = cli_netlogon_sam_logon(cli, mem_ctx, &ret_creds, username, password, logon_type); - - clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds); - if (!NT_STATUS_IS_OK(result)) goto done; @@ -292,12 +283,11 @@ static NTSTATUS cmd_netlogon_sam_logon(struct cli_state *cli, /* Change the trust account password */ -static NTSTATUS cmd_netlogon_change_trust_pw(struct cli_state *cli, +static NTSTATUS cmd_netlogon_change_trust_pw(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - DOM_CRED ret_creds; /* Check arguments */ @@ -308,13 +298,9 @@ static NTSTATUS cmd_netlogon_change_trust_pw(struct cli_state *cli, /* Perform the sam logon */ - ZERO_STRUCT(ret_creds); - result = trust_pw_find_change_and_store_it(cli, mem_ctx, lp_workgroup()); - clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), &ret_creds); - if (!NT_STATUS_IS_OK(result)) goto done; @@ -329,13 +315,13 @@ struct cmd_set netlogon_commands[] = { { "NETLOGON" }, - { "logonctrl2", RPC_RTYPE_NTSTATUS, cmd_netlogon_logon_ctrl2, NULL, PI_NETLOGON, "Logon Control 2", "" }, - { "getdcname", RPC_RTYPE_NTSTATUS, cmd_netlogon_getdcname, NULL, PI_NETLOGON, "Get trusted DC name", "" }, - { "logonctrl", RPC_RTYPE_NTSTATUS, cmd_netlogon_logon_ctrl, NULL, PI_NETLOGON, "Logon Control", "" }, - { "samsync", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_sync, NULL, PI_NETLOGON, "Sam Synchronisation", "" }, - { "samdeltas", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_deltas, NULL, PI_NETLOGON, "Query Sam Deltas", "" }, - { "samlogon", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_logon, NULL, PI_NETLOGON, "Sam Logon", "" }, - { "change_trust_pw", RPC_RTYPE_NTSTATUS, cmd_netlogon_change_trust_pw, NULL, PI_NETLOGON, "Change Trust Account Password", "" }, + { "logonctrl2", RPC_RTYPE_NTSTATUS, cmd_netlogon_logon_ctrl2, NULL, PI_NETLOGON, NULL, "Logon Control 2", "" }, + { "getdcname", RPC_RTYPE_NTSTATUS, cmd_netlogon_getdcname, NULL, PI_NETLOGON, NULL, "Get trusted DC name", "" }, + { "logonctrl", RPC_RTYPE_NTSTATUS, cmd_netlogon_logon_ctrl, NULL, PI_NETLOGON, NULL, "Logon Control", "" }, + { "samsync", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_sync, NULL, PI_NETLOGON, NULL, "Sam Synchronisation", "" }, + { "samdeltas", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_deltas, NULL, PI_NETLOGON, NULL, "Query Sam Deltas", "" }, + { "samlogon", RPC_RTYPE_NTSTATUS, cmd_netlogon_sam_logon, NULL, PI_NETLOGON, NULL, "Sam Logon", "" }, + { "change_trust_pw", RPC_RTYPE_NTSTATUS, cmd_netlogon_change_trust_pw, NULL, PI_NETLOGON, NULL, "Change Trust Account Password", "" }, { NULL } }; diff --git a/source3/rpcclient/cmd_samr.c b/source3/rpcclient/cmd_samr.c index acb39271050..a05c2c8a0b0 100644 --- a/source3/rpcclient/cmd_samr.c +++ b/source3/rpcclient/cmd_samr.c @@ -300,14 +300,14 @@ static void display_sam_info_5(SAM_ENTRY5 *e5, SAM_STR5 *s5) /**************************************************************************** Try samr_connect4 first, then samr_conenct if it fails ****************************************************************************/ -static NTSTATUS try_samr_connects(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static NTSTATUS try_samr_connects(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, uint32 access_mask, POLICY_HND *connect_pol) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - result = cli_samr_connect4(cli, mem_ctx, access_mask, connect_pol); + result = rpccli_samr_connect4(cli, mem_ctx, access_mask, connect_pol); if (!NT_STATUS_IS_OK(result)) { - result = cli_samr_connect(cli, mem_ctx, access_mask, + result = rpccli_samr_connect(cli, mem_ctx, access_mask, connect_pol); } return result; @@ -316,7 +316,7 @@ static NTSTATUS try_samr_connects(struct cli_state *cli, TALLOC_CTX *mem_ctx, /********************************************************************** * Query user information */ -static NTSTATUS cmd_samr_query_user(struct cli_state *cli, +static NTSTATUS cmd_samr_query_user(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -342,7 +342,7 @@ static NTSTATUS cmd_samr_query_user(struct cli_state *cli, sscanf(argv[3], "%x", &access_mask); - slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); strupper_m(server); result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, @@ -351,14 +351,14 @@ static NTSTATUS cmd_samr_query_user(struct cli_state *cli, if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_open_user(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol, access_mask, user_rid, &user_pol); @@ -367,7 +367,7 @@ static NTSTATUS cmd_samr_query_user(struct cli_state *cli, ZERO_STRUCT(user_ctr); - result = cli_samr_query_userinfo(cli, mem_ctx, &user_pol, + result = rpccli_samr_query_userinfo(cli, mem_ctx, &user_pol, info_level, &user_ctr); if (!NT_STATUS_IS_OK(result)) @@ -385,6 +385,10 @@ static NTSTATUS cmd_samr_query_user(struct cli_state *cli, break; } + rpccli_samr_close(cli, mem_ctx, &user_pol); + rpccli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(cli, mem_ctx, &connect_pol); + done: return result; } @@ -435,7 +439,7 @@ static void display_group_info_ctr(GROUP_INFO_CTR *ctr) /*********************************************************************** * Query group information */ -static NTSTATUS cmd_samr_query_group(struct cli_state *cli, +static NTSTATUS cmd_samr_query_group(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -460,7 +464,7 @@ static NTSTATUS cmd_samr_query_group(struct cli_state *cli, if (argc > 3) sscanf(argv[3], "%x", &access_mask); - slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); strupper_m(server); result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, @@ -469,21 +473,21 @@ static NTSTATUS cmd_samr_query_group(struct cli_state *cli, if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_open_group(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_group(cli, mem_ctx, &domain_pol, access_mask, group_rid, &group_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_query_groupinfo(cli, mem_ctx, &group_pol, + result = rpccli_samr_query_groupinfo(cli, mem_ctx, &group_pol, info_level, &group_ctr); if (!NT_STATUS_IS_OK(result)) { goto done; @@ -491,13 +495,16 @@ static NTSTATUS cmd_samr_query_group(struct cli_state *cli, display_group_info_ctr(group_ctr); + rpccli_samr_close(cli, mem_ctx, &group_pol); + rpccli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(cli, mem_ctx, &connect_pol); done: return result; } /* Query groups a user is a member of */ -static NTSTATUS cmd_samr_query_usergroups(struct cli_state *cli, +static NTSTATUS cmd_samr_query_usergroups(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -522,7 +529,7 @@ static NTSTATUS cmd_samr_query_usergroups(struct cli_state *cli, if (argc > 2) sscanf(argv[2], "%x", &access_mask); - slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); strupper_m(server); result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, @@ -531,21 +538,21 @@ static NTSTATUS cmd_samr_query_usergroups(struct cli_state *cli, if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_open_user(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol, access_mask, user_rid, &user_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_query_usergroups(cli, mem_ctx, &user_pol, + result = rpccli_samr_query_usergroups(cli, mem_ctx, &user_pol, &num_groups, &user_gids); if (!NT_STATUS_IS_OK(result)) @@ -556,13 +563,16 @@ static NTSTATUS cmd_samr_query_usergroups(struct cli_state *cli, user_gids[i].g_rid, user_gids[i].attr); } + rpccli_samr_close(cli, mem_ctx, &user_pol); + rpccli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(cli, mem_ctx, &connect_pol); done: return result; } /* Query aliases a user is a member of */ -static NTSTATUS cmd_samr_query_useraliases(struct cli_state *cli, +static NTSTATUS cmd_samr_query_useraliases(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -602,7 +612,7 @@ static NTSTATUS cmd_samr_query_useraliases(struct cli_state *cli, sid2[i].num_auths = sid2[i].sid.num_auths; } - slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); strupper_m(server); result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, @@ -612,11 +622,11 @@ static NTSTATUS cmd_samr_query_useraliases(struct cli_state *cli, goto done; if (StrCaseCmp(argv[1], "domain")==0) - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, access_mask, &domain_sid, &domain_pol); else if (StrCaseCmp(argv[1], "builtin")==0) - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, access_mask, &global_sid_Builtin, &domain_pol); @@ -628,7 +638,7 @@ static NTSTATUS cmd_samr_query_useraliases(struct cli_state *cli, if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_query_useraliases(cli, mem_ctx, &domain_pol, + result = rpccli_samr_query_useraliases(cli, mem_ctx, &domain_pol, num_sids, sid2, &num_aliases, &alias_rids); @@ -639,13 +649,15 @@ static NTSTATUS cmd_samr_query_useraliases(struct cli_state *cli, printf("\tgroup rid:[0x%x]\n", alias_rids[i]); } + rpccli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(cli, mem_ctx, &connect_pol); done: return result; } /* Query members of a group */ -static NTSTATUS cmd_samr_query_groupmem(struct cli_state *cli, +static NTSTATUS cmd_samr_query_groupmem(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -666,7 +678,7 @@ static NTSTATUS cmd_samr_query_groupmem(struct cli_state *cli, if (argc > 2) sscanf(argv[2], "%x", &access_mask); - slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); strupper_m(server); result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, @@ -675,21 +687,21 @@ static NTSTATUS cmd_samr_query_groupmem(struct cli_state *cli, if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_open_group(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_group(cli, mem_ctx, &domain_pol, access_mask, group_rid, &group_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_query_groupmem(cli, mem_ctx, &group_pol, + result = rpccli_samr_query_groupmem(cli, mem_ctx, &group_pol, &num_members, &group_rids, &group_attrs); @@ -701,13 +713,16 @@ static NTSTATUS cmd_samr_query_groupmem(struct cli_state *cli, group_attrs[i]); } + rpccli_samr_close(cli, mem_ctx, &group_pol); + rpccli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(cli, mem_ctx, &connect_pol); done: return result; } /* Enumerate domain users */ -static NTSTATUS cmd_samr_enum_dom_users(struct cli_state *cli, +static NTSTATUS cmd_samr_enum_dom_users(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -743,7 +758,7 @@ static NTSTATUS cmd_samr_enum_dom_users(struct cli_state *cli, /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, access_mask, &domain_sid, &domain_pol); @@ -758,7 +773,7 @@ static NTSTATUS cmd_samr_enum_dom_users(struct cli_state *cli, size = 0xffff; do { - result = cli_samr_enum_dom_users( + result = rpccli_samr_enum_dom_users( cli, mem_ctx, &domain_pol, &start_idx, acb_mask, size, &dom_users, &dom_rids, &num_dom_users); @@ -774,17 +789,17 @@ static NTSTATUS cmd_samr_enum_dom_users(struct cli_state *cli, done: if (got_domain_pol) - cli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(cli, mem_ctx, &domain_pol); if (got_connect_pol) - cli_samr_close(cli, mem_ctx, &connect_pol); + rpccli_samr_close(cli, mem_ctx, &connect_pol); return result; } /* Enumerate domain groups */ -static NTSTATUS cmd_samr_enum_dom_groups(struct cli_state *cli, +static NTSTATUS cmd_samr_enum_dom_groups(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -815,7 +830,7 @@ static NTSTATUS cmd_samr_enum_dom_groups(struct cli_state *cli, /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, access_mask, &domain_sid, &domain_pol); @@ -830,7 +845,7 @@ static NTSTATUS cmd_samr_enum_dom_groups(struct cli_state *cli, size = 0xffff; do { - result = cli_samr_enum_dom_groups( + result = rpccli_samr_enum_dom_groups( cli, mem_ctx, &domain_pol, &start_idx, size, &dom_groups, &num_dom_groups); @@ -847,17 +862,17 @@ static NTSTATUS cmd_samr_enum_dom_groups(struct cli_state *cli, done: if (got_domain_pol) - cli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(cli, mem_ctx, &domain_pol); if (got_connect_pol) - cli_samr_close(cli, mem_ctx, &connect_pol); + rpccli_samr_close(cli, mem_ctx, &connect_pol); return result; } /* Enumerate alias groups */ -static NTSTATUS cmd_samr_enum_als_groups(struct cli_state *cli, +static NTSTATUS cmd_samr_enum_als_groups(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -889,11 +904,11 @@ static NTSTATUS cmd_samr_enum_als_groups(struct cli_state *cli, /* Get domain policy handle */ if (StrCaseCmp(argv[1], "domain")==0) - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, access_mask, &domain_sid, &domain_pol); else if (StrCaseCmp(argv[1], "builtin")==0) - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, access_mask, &global_sid_Builtin, &domain_pol); else @@ -910,7 +925,7 @@ static NTSTATUS cmd_samr_enum_als_groups(struct cli_state *cli, size = 0xffff; /* Number of groups to retrieve */ do { - result = cli_samr_enum_als_groups( + result = rpccli_samr_enum_als_groups( cli, mem_ctx, &domain_pol, &start_idx, size, &als_groups, &num_als_groups); @@ -926,17 +941,17 @@ static NTSTATUS cmd_samr_enum_als_groups(struct cli_state *cli, done: if (got_domain_pol) - cli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(cli, mem_ctx, &domain_pol); if (got_connect_pol) - cli_samr_close(cli, mem_ctx, &connect_pol); + rpccli_samr_close(cli, mem_ctx, &connect_pol); return result; } /* Query alias membership */ -static NTSTATUS cmd_samr_query_aliasmem(struct cli_state *cli, +static NTSTATUS cmd_samr_query_aliasmem(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -967,11 +982,11 @@ static NTSTATUS cmd_samr_query_aliasmem(struct cli_state *cli, /* Open handle on domain */ if (StrCaseCmp(argv[1], "domain")==0) - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); else if (StrCaseCmp(argv[1], "builtin")==0) - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &global_sid_Builtin, &domain_pol); else @@ -982,13 +997,13 @@ static NTSTATUS cmd_samr_query_aliasmem(struct cli_state *cli, /* Open handle on alias */ - result = cli_samr_open_alias(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_alias(cli, mem_ctx, &domain_pol, access_mask, alias_rid, &alias_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_query_aliasmem(cli, mem_ctx, &alias_pol, + result = rpccli_samr_query_aliasmem(cli, mem_ctx, &alias_pol, &num_members, &alias_sids); if (!NT_STATUS_IS_OK(result)) @@ -1001,13 +1016,16 @@ static NTSTATUS cmd_samr_query_aliasmem(struct cli_state *cli, printf("\tsid:[%s]\n", sid_str); } + rpccli_samr_close(cli, mem_ctx, &alias_pol); + rpccli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(cli, mem_ctx, &connect_pol); done: return result; } /* Query display info */ -static NTSTATUS cmd_samr_query_dispinfo(struct cli_state *cli, +static NTSTATUS cmd_samr_query_dispinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1059,7 +1077,7 @@ static NTSTATUS cmd_samr_query_dispinfo(struct cli_state *cli, /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, access_mask, &domain_sid, &domain_pol); @@ -1101,7 +1119,7 @@ static NTSTATUS cmd_samr_query_dispinfo(struct cli_state *cli, get_query_dispinfo_params( loop_count, &max_entries, &max_size); - result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol, + result = rpccli_samr_query_dispinfo(cli, mem_ctx, &domain_pol, &start_idx, info_level, &num_entries, max_entries, max_size, &ctr); @@ -1135,13 +1153,15 @@ static NTSTATUS cmd_samr_query_dispinfo(struct cli_state *cli, } } while ( NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); + rpccli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(cli, mem_ctx, &connect_pol); done: return result; } /* Query domain info */ -static NTSTATUS cmd_samr_query_dominfo(struct cli_state *cli, +static NTSTATUS cmd_samr_query_dominfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1172,7 +1192,7 @@ static NTSTATUS cmd_samr_query_dominfo(struct cli_state *cli, /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, access_mask, &domain_sid, &domain_pol); @@ -1181,7 +1201,7 @@ static NTSTATUS cmd_samr_query_dominfo(struct cli_state *cli, /* Query domain info */ - result = cli_samr_query_dom_info(cli, mem_ctx, &domain_pol, + result = rpccli_samr_query_dom_info(cli, mem_ctx, &domain_pol, switch_level, &ctr); if (!NT_STATUS_IS_OK(result)) @@ -1213,14 +1233,14 @@ static NTSTATUS cmd_samr_query_dominfo(struct cli_state *cli, done: - cli_samr_close(cli, mem_ctx, &domain_pol); - cli_samr_close(cli, mem_ctx, &connect_pol); + rpccli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(cli, mem_ctx, &connect_pol); return result; } /* Create domain user */ -static NTSTATUS cmd_samr_create_dom_user(struct cli_state *cli, +static NTSTATUS cmd_samr_create_dom_user(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1251,7 +1271,7 @@ static NTSTATUS cmd_samr_create_dom_user(struct cli_state *cli, /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, access_mask, &domain_sid, &domain_pol); @@ -1263,20 +1283,20 @@ static NTSTATUS cmd_samr_create_dom_user(struct cli_state *cli, acb_info = ACB_NORMAL; unknown = 0xe005000b; /* No idea what this is - a permission mask? */ - result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol, + result = rpccli_samr_create_dom_user(cli, mem_ctx, &domain_pol, acct_name, acb_info, unknown, &user_pol, &user_rid); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_close(cli, mem_ctx, &user_pol); + result = rpccli_samr_close(cli, mem_ctx, &user_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_close(cli, mem_ctx, &domain_pol); + result = rpccli_samr_close(cli, mem_ctx, &domain_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_close(cli, mem_ctx, &connect_pol); + result = rpccli_samr_close(cli, mem_ctx, &connect_pol); if (!NT_STATUS_IS_OK(result)) goto done; done: @@ -1285,7 +1305,7 @@ static NTSTATUS cmd_samr_create_dom_user(struct cli_state *cli, /* Create domain group */ -static NTSTATUS cmd_samr_create_dom_group(struct cli_state *cli, +static NTSTATUS cmd_samr_create_dom_group(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1314,7 +1334,7 @@ static NTSTATUS cmd_samr_create_dom_group(struct cli_state *cli, /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, access_mask, &domain_sid, &domain_pol); @@ -1323,20 +1343,20 @@ static NTSTATUS cmd_samr_create_dom_group(struct cli_state *cli, /* Create domain user */ - result = cli_samr_create_dom_group(cli, mem_ctx, &domain_pol, + result = rpccli_samr_create_dom_group(cli, mem_ctx, &domain_pol, grp_name, MAXIMUM_ALLOWED_ACCESS, &group_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_close(cli, mem_ctx, &group_pol); + result = rpccli_samr_close(cli, mem_ctx, &group_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_close(cli, mem_ctx, &domain_pol); + result = rpccli_samr_close(cli, mem_ctx, &domain_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_close(cli, mem_ctx, &connect_pol); + result = rpccli_samr_close(cli, mem_ctx, &connect_pol); if (!NT_STATUS_IS_OK(result)) goto done; done: @@ -1345,7 +1365,7 @@ static NTSTATUS cmd_samr_create_dom_group(struct cli_state *cli, /* Lookup sam names */ -static NTSTATUS cmd_samr_lookup_names(struct cli_state *cli, +static NTSTATUS cmd_samr_lookup_names(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1372,11 +1392,11 @@ static NTSTATUS cmd_samr_lookup_names(struct cli_state *cli, goto done; if (StrCaseCmp(argv[1], "domain")==0) - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); else if (StrCaseCmp(argv[1], "builtin")==0) - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &global_sid_Builtin, &domain_pol); else @@ -1393,7 +1413,7 @@ static NTSTATUS cmd_samr_lookup_names(struct cli_state *cli, for (i = 0; i < argc - 2; i++) names[i] = argv[i + 2]; - result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, + result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol, flags, num_names, names, &num_rids, &rids, &name_types); @@ -1406,13 +1426,15 @@ static NTSTATUS cmd_samr_lookup_names(struct cli_state *cli, printf("name %s: 0x%x (%d)\n", names[i], rids[i], name_types[i]); + rpccli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(cli, mem_ctx, &connect_pol); done: return result; } /* Lookup sam rids */ -static NTSTATUS cmd_samr_lookup_rids(struct cli_state *cli, +static NTSTATUS cmd_samr_lookup_rids(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1435,7 +1457,7 @@ static NTSTATUS cmd_samr_lookup_rids(struct cli_state *cli, if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); @@ -1450,7 +1472,7 @@ static NTSTATUS cmd_samr_lookup_rids(struct cli_state *cli, for (i = 0; i < argc - 1; i++) sscanf(argv[i + 1], "%i", &rids[i]); - result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol, num_rids, rids, + result = rpccli_samr_lookup_rids(cli, mem_ctx, &domain_pol, num_rids, rids, &num_names, &names, &name_types); if (!NT_STATUS_IS_OK(result) && @@ -1462,13 +1484,15 @@ static NTSTATUS cmd_samr_lookup_rids(struct cli_state *cli, for (i = 0; i < num_names; i++) printf("rid 0x%x: %s (%d)\n", rids[i], names[i], name_types[i]); + rpccli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(cli, mem_ctx, &connect_pol); done: return result; } /* Delete domain user */ -static NTSTATUS cmd_samr_delete_dom_user(struct cli_state *cli, +static NTSTATUS cmd_samr_delete_dom_user(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1492,7 +1516,7 @@ static NTSTATUS cmd_samr_delete_dom_user(struct cli_state *cli, if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); @@ -1505,7 +1529,7 @@ static NTSTATUS cmd_samr_delete_dom_user(struct cli_state *cli, uint32 *user_rids, num_rids, *name_types; uint32 flags = 0x000003e8; /* Unknown */ - result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, + result = rpccli_samr_lookup_names(cli, mem_ctx, &domain_pol, flags, 1, (const char **)&argv[1], &num_rids, &user_rids, &name_types); @@ -1513,7 +1537,7 @@ static NTSTATUS cmd_samr_delete_dom_user(struct cli_state *cli, if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_open_user(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol, access_mask, user_rids[0], &user_pol); @@ -1523,13 +1547,17 @@ static NTSTATUS cmd_samr_delete_dom_user(struct cli_state *cli, /* Delete user */ - result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol); + result = rpccli_samr_delete_dom_user(cli, mem_ctx, &user_pol); if (!NT_STATUS_IS_OK(result)) goto done; /* Display results */ + rpccli_samr_close(cli, mem_ctx, &user_pol); + rpccli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(cli, mem_ctx, &connect_pol); + done: return result; } @@ -1537,7 +1565,7 @@ static NTSTATUS cmd_samr_delete_dom_user(struct cli_state *cli, /********************************************************************** * Query user security object */ -static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli, +static NTSTATUS cmd_samr_query_sec_obj(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1565,7 +1593,7 @@ static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli, sscanf(argv[1], "%i", &user_rid); } - slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->desthost); + slprintf(server, sizeof(fstring)-1, "\\\\%s", cli->cli->desthost); strupper_m(server); result = try_samr_connects(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); @@ -1574,7 +1602,7 @@ static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli, goto done; if (domain || user_rid) - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &domain_sid, &domain_pol); @@ -1582,7 +1610,7 @@ static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli, goto done; if (user_rid) - result = cli_samr_open_user(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_user(cli, mem_ctx, &domain_pol, MAXIMUM_ALLOWED_ACCESS, user_rid, &user_pol); @@ -1601,7 +1629,7 @@ static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli, /* Query SAM security object */ - result = cli_samr_query_sec_obj(cli, mem_ctx, pol, info_level, ctx, + result = rpccli_samr_query_sec_obj(cli, mem_ctx, pol, info_level, ctx, &sec_desc_buf); if (!NT_STATUS_IS_OK(result)) @@ -1609,12 +1637,15 @@ static NTSTATUS cmd_samr_query_sec_obj(struct cli_state *cli, display_sec_desc(sec_desc_buf->sec); + rpccli_samr_close(cli, mem_ctx, &user_pol); + rpccli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(cli, mem_ctx, &connect_pol); done: talloc_destroy(ctx); return result; } -static NTSTATUS cmd_samr_get_dom_pwinfo(struct cli_state *cli, +static NTSTATUS cmd_samr_get_dom_pwinfo(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1626,7 +1657,7 @@ static NTSTATUS cmd_samr_get_dom_pwinfo(struct cli_state *cli, return NT_STATUS_OK; } - result = cli_samr_get_dom_pwinfo(cli, mem_ctx, &unk_0, &unk_1) ; + result = rpccli_samr_get_dom_pwinfo(cli, mem_ctx, &unk_0, &unk_1) ; if (NT_STATUS_IS_OK(result)) { printf("unk_0 = 0x%08x\n", unk_0); @@ -1638,7 +1669,7 @@ static NTSTATUS cmd_samr_get_dom_pwinfo(struct cli_state *cli, /* Look up domain name */ -static NTSTATUS cmd_samr_lookup_domain(struct cli_state *cli, +static NTSTATUS cmd_samr_lookup_domain(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1660,13 +1691,13 @@ static NTSTATUS cmd_samr_lookup_domain(struct cli_state *cli, if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(cli, mem_ctx, &connect_pol, access_mask, &domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_lookup_domain( + result = rpccli_samr_lookup_domain( cli, mem_ctx, &connect_pol, domain_name, &sid); sid_to_string(sid_string,&sid); @@ -1675,6 +1706,8 @@ static NTSTATUS cmd_samr_lookup_domain(struct cli_state *cli, printf("SAMR_LOOKUP_DOMAIN: Domain Name: %s Domain SID: %s\n", domain_name,sid_string); + rpccli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(cli, mem_ctx, &connect_pol); done: return result; } @@ -1686,26 +1719,26 @@ struct cmd_set samr_commands[] = { { "SAMR" }, - { "queryuser", RPC_RTYPE_NTSTATUS, cmd_samr_query_user, NULL, PI_SAMR, "Query user info", "" }, - { "querygroup", RPC_RTYPE_NTSTATUS, cmd_samr_query_group, NULL, PI_SAMR, "Query group info", "" }, - { "queryusergroups", RPC_RTYPE_NTSTATUS, cmd_samr_query_usergroups, NULL, PI_SAMR, "Query user groups", "" }, - { "queryuseraliases", RPC_RTYPE_NTSTATUS, cmd_samr_query_useraliases, NULL, PI_SAMR, "Query user aliases", "" }, - { "querygroupmem", RPC_RTYPE_NTSTATUS, cmd_samr_query_groupmem, NULL, PI_SAMR, "Query group membership", "" }, - { "queryaliasmem", RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasmem, NULL, PI_SAMR, "Query alias membership", "" }, - { "querydispinfo", RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo, NULL, PI_SAMR, "Query display info", "" }, - { "querydominfo", RPC_RTYPE_NTSTATUS, cmd_samr_query_dominfo, NULL, PI_SAMR, "Query domain info", "" }, - { "enumdomusers", RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_users, NULL, PI_SAMR, "Enumerate domain users", "" }, - { "enumdomgroups", RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_groups, NULL, PI_SAMR, "Enumerate domain groups", "" }, - { "enumalsgroups", RPC_RTYPE_NTSTATUS, cmd_samr_enum_als_groups, NULL, PI_SAMR, "Enumerate alias groups", "" }, - - { "createdomuser", RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_user, NULL, PI_SAMR, "Create domain user", "" }, - { "createdomgroup", RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_group, NULL, PI_SAMR, "Create domain group", "" }, - { "samlookupnames", RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names, NULL, PI_SAMR, "Look up names", "" }, - { "samlookuprids", RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids, NULL, PI_SAMR, "Look up names", "" }, - { "deletedomuser", RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user, NULL, PI_SAMR, "Delete domain user", "" }, - { "samquerysecobj", RPC_RTYPE_NTSTATUS, cmd_samr_query_sec_obj, NULL, PI_SAMR, "Query SAMR security object", "" }, - { "getdompwinfo", RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo, NULL, PI_SAMR, "Retrieve domain password info", "" }, - - { "lookupdomain", RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain, NULL, PI_SAMR, "Lookup Domain Name", "" }, + { "queryuser", RPC_RTYPE_NTSTATUS, cmd_samr_query_user, NULL, PI_SAMR, NULL, "Query user info", "" }, + { "querygroup", RPC_RTYPE_NTSTATUS, cmd_samr_query_group, NULL, PI_SAMR, NULL, "Query group info", "" }, + { "queryusergroups", RPC_RTYPE_NTSTATUS, cmd_samr_query_usergroups, NULL, PI_SAMR, NULL, "Query user groups", "" }, + { "queryuseraliases", RPC_RTYPE_NTSTATUS, cmd_samr_query_useraliases, NULL, PI_SAMR, NULL, "Query user aliases", "" }, + { "querygroupmem", RPC_RTYPE_NTSTATUS, cmd_samr_query_groupmem, NULL, PI_SAMR, NULL, "Query group membership", "" }, + { "queryaliasmem", RPC_RTYPE_NTSTATUS, cmd_samr_query_aliasmem, NULL, PI_SAMR, NULL, "Query alias membership", "" }, + { "querydispinfo", RPC_RTYPE_NTSTATUS, cmd_samr_query_dispinfo, NULL, PI_SAMR, NULL, "Query display info", "" }, + { "querydominfo", RPC_RTYPE_NTSTATUS, cmd_samr_query_dominfo, NULL, PI_SAMR, NULL, "Query domain info", "" }, + { "enumdomusers", RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_users, NULL, PI_SAMR, NULL, "Enumerate domain users", "" }, + { "enumdomgroups", RPC_RTYPE_NTSTATUS, cmd_samr_enum_dom_groups, NULL, PI_SAMR, NULL, "Enumerate domain groups", "" }, + { "enumalsgroups", RPC_RTYPE_NTSTATUS, cmd_samr_enum_als_groups, NULL, PI_SAMR, NULL, "Enumerate alias groups", "" }, + + { "createdomuser", RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_user, NULL, PI_SAMR, NULL, "Create domain user", "" }, + { "createdomgroup", RPC_RTYPE_NTSTATUS, cmd_samr_create_dom_group, NULL, PI_SAMR, NULL, "Create domain group", "" }, + { "samlookupnames", RPC_RTYPE_NTSTATUS, cmd_samr_lookup_names, NULL, PI_SAMR, NULL, "Look up names", "" }, + { "samlookuprids", RPC_RTYPE_NTSTATUS, cmd_samr_lookup_rids, NULL, PI_SAMR, NULL, "Look up names", "" }, + { "deletedomuser", RPC_RTYPE_NTSTATUS, cmd_samr_delete_dom_user, NULL, PI_SAMR, NULL, "Delete domain user", "" }, + { "samquerysecobj", RPC_RTYPE_NTSTATUS, cmd_samr_query_sec_obj, NULL, PI_SAMR, NULL, "Query SAMR security object", "" }, + { "getdompwinfo", RPC_RTYPE_NTSTATUS, cmd_samr_get_dom_pwinfo, NULL, PI_SAMR, NULL, "Retrieve domain password info", "" }, + + { "lookupdomain", RPC_RTYPE_NTSTATUS, cmd_samr_lookup_domain, NULL, PI_SAMR, NULL, "Lookup Domain Name", "" }, { NULL } }; diff --git a/source3/rpcclient/cmd_spoolss.c b/source3/rpcclient/cmd_spoolss.c index 1b3d3b7e0c4..0ae16e8f1ae 100644 --- a/source3/rpcclient/cmd_spoolss.c +++ b/source3/rpcclient/cmd_spoolss.c @@ -93,7 +93,7 @@ static const char *cmd_spoolss_get_short_archi(const char *long_archi) /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_open_printer_ex(struct cli_state *cli, +static WERROR cmd_spoolss_open_printer_ex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -110,20 +110,20 @@ static WERROR cmd_spoolss_open_printer_ex(struct cli_state *cli, if (!cli) return WERR_GENERAL_FAILURE; - slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost); strupper_m(servername); fstrcpy(user, cli->user_name); fstrcpy(printername, argv[1]); /* Open the printer handle */ - werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, + werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", PRINTER_ALL_ACCESS, servername, user, &hnd); if (W_ERROR_IS_OK(werror)) { printf("Printer %s opened successfully\n", printername); - werror = cli_spoolss_close_printer(cli, mem_ctx, &hnd); + werror = rpccli_spoolss_close_printer(cli, mem_ctx, &hnd); if (!W_ERROR_IS_OK(werror)) { printf("Error closing printer handle! (%s)\n", @@ -298,7 +298,7 @@ static void display_print_info_7(PRINTER_INFO_7 *i7) /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_enum_printers(struct cli_state *cli, +static WERROR cmd_spoolss_enum_printers(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -320,13 +320,13 @@ static WERROR cmd_spoolss_enum_printers(struct cli_state *cli, if (argc == 3) fstrcpy(name, argv[2]); else { - slprintf(name, sizeof(name)-1, "\\\\%s", cli->desthost); + slprintf(name, sizeof(name)-1, "\\\\%s", cli->cli->desthost); strupper_m(name); } ZERO_STRUCT(ctr); - result = cli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL, + result = rpccli_spoolss_enum_printers(cli, mem_ctx, name, PRINTER_ENUM_LOCAL, info_level, &num_printers, &ctr); if (W_ERROR_IS_OK(result)) { @@ -419,7 +419,7 @@ static void display_port_info_2(PORT_INFO_2 *i2) /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_enum_ports(struct cli_state *cli, +static WERROR cmd_spoolss_enum_ports(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -440,7 +440,7 @@ static WERROR cmd_spoolss_enum_ports(struct cli_state *cli, ZERO_STRUCT(ctr); - result = cli_spoolss_enum_ports(cli, mem_ctx, info_level, &returned, &ctr); + result = rpccli_spoolss_enum_ports(cli, mem_ctx, info_level, &returned, &ctr); if (W_ERROR_IS_OK(result)) { int i; @@ -466,7 +466,7 @@ static WERROR cmd_spoolss_enum_ports(struct cli_state *cli, /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_setprinter(struct cli_state *cli, +static WERROR cmd_spoolss_setprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -491,13 +491,13 @@ static WERROR cmd_spoolss_setprinter(struct cli_state *cli, fstrcpy(comment, argv[2]); } - slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost); strupper_m(servername); slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]); fstrcpy(user, cli->user_name); /* get a printer handle */ - result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", + result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", PRINTER_ALL_ACCESS, servername, user, &pol); @@ -507,7 +507,7 @@ static WERROR cmd_spoolss_setprinter(struct cli_state *cli, opened_hnd = True; /* Get printer info */ - result = cli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr); + result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr); if (!W_ERROR_IS_OK(result)) goto done; @@ -518,13 +518,13 @@ static WERROR cmd_spoolss_setprinter(struct cli_state *cli, ctr.printers_2->devmode = NULL; ctr.printers_2->secdesc = NULL; - result = cli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0); + result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0); if (W_ERROR_IS_OK(result)) printf("Success in setting comment.\n"); done: if (opened_hnd) - cli_spoolss_close_printer(cli, mem_ctx, &pol); + rpccli_spoolss_close_printer(cli, mem_ctx, &pol); return result; } @@ -532,7 +532,7 @@ static WERROR cmd_spoolss_setprinter(struct cli_state *cli, /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_setprintername(struct cli_state *cli, +static WERROR cmd_spoolss_setprintername(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -557,13 +557,13 @@ static WERROR cmd_spoolss_setprintername(struct cli_state *cli, fstrcpy(new_printername, argv[2]); } - slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost); strupper_m(servername); slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]); fstrcpy(user, cli->user_name); /* get a printer handle */ - result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", + result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", PRINTER_ALL_ACCESS, servername, user, &pol); @@ -573,7 +573,7 @@ static WERROR cmd_spoolss_setprintername(struct cli_state *cli, opened_hnd = True; /* Get printer info */ - result = cli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr); + result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr); if (!W_ERROR_IS_OK(result)) goto done; @@ -583,13 +583,13 @@ static WERROR cmd_spoolss_setprintername(struct cli_state *cli, ctr.printers_2->devmode = NULL; ctr.printers_2->secdesc = NULL; - result = cli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0); + result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, info_level, &ctr, 0); if (W_ERROR_IS_OK(result)) printf("Success in setting printername.\n"); done: if (opened_hnd) - cli_spoolss_close_printer(cli, mem_ctx, &pol); + rpccli_spoolss_close_printer(cli, mem_ctx, &pol); return result; } @@ -597,7 +597,7 @@ static WERROR cmd_spoolss_setprintername(struct cli_state *cli, /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_getprinter(struct cli_state *cli, +static WERROR cmd_spoolss_getprinter(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -620,14 +620,14 @@ static WERROR cmd_spoolss_getprinter(struct cli_state *cli, info_level = atoi(argv[2]); } - slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost); strupper_m(servername); slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]); fstrcpy(user, cli->user_name); /* get a printer handle */ - result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, + result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, servername, user, &pol); @@ -638,7 +638,7 @@ static WERROR cmd_spoolss_getprinter(struct cli_state *cli, /* Get printer info */ - result = cli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr); + result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, info_level, &ctr); if (!W_ERROR_IS_OK(result)) goto done; @@ -668,7 +668,7 @@ static WERROR cmd_spoolss_getprinter(struct cli_state *cli, done: if (opened_hnd) - cli_spoolss_close_printer(cli, mem_ctx, &pol); + rpccli_spoolss_close_printer(cli, mem_ctx, &pol); return result; } @@ -729,7 +729,7 @@ static void display_reg_value(REGISTRY_VALUE value) /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli, +static WERROR cmd_spoolss_getprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -751,7 +751,7 @@ static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli, /* Open a printer handle */ - slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost); strupper_m(servername); if (strncmp(argv[1], ".", sizeof(".")) == 0) fstrcpy(printername, servername); @@ -762,7 +762,7 @@ static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli, /* get a printer handle */ - result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, + result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, servername, user, &pol); @@ -773,7 +773,7 @@ static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli, /* Get printer info */ - result = cli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value); + result = rpccli_spoolss_getprinterdata(cli, mem_ctx, &pol, valuename, &value); if (!W_ERROR_IS_OK(result)) goto done; @@ -786,7 +786,7 @@ static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli, done: if (opened_hnd) - cli_spoolss_close_printer(cli, mem_ctx, &pol); + rpccli_spoolss_close_printer(cli, mem_ctx, &pol); return result; } @@ -794,7 +794,7 @@ static WERROR cmd_spoolss_getprinterdata(struct cli_state *cli, /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli, +static WERROR cmd_spoolss_getprinterdataex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -818,7 +818,7 @@ static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli, /* Open a printer handle */ - slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost); strupper_m(servername); if (strncmp(argv[1], ".", sizeof(".")) == 0) fstrcpy(printername, servername); @@ -829,7 +829,7 @@ static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli, /* get a printer handle */ - result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, + result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, servername, user, &pol); @@ -840,7 +840,7 @@ static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli, /* Get printer info */ - result = cli_spoolss_getprinterdataex(cli, mem_ctx, &pol, keyname, + result = rpccli_spoolss_getprinterdataex(cli, mem_ctx, &pol, keyname, valuename, &value); if (!W_ERROR_IS_OK(result)) @@ -854,7 +854,7 @@ static WERROR cmd_spoolss_getprinterdataex(struct cli_state *cli, done: if (opened_hnd) - cli_spoolss_close_printer(cli, mem_ctx, &pol); + rpccli_spoolss_close_printer(cli, mem_ctx, &pol); return result; } @@ -972,7 +972,7 @@ static void display_print_driver_3(DRIVER_INFO_3 *i1) /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_getdriver(struct cli_state *cli, +static WERROR cmd_spoolss_getdriver(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -994,7 +994,7 @@ static WERROR cmd_spoolss_getdriver(struct cli_state *cli, } /* get the arguments need to open the printer handle */ - slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost); strupper_m(servername); fstrcpy(user, cli->user_name); slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]); @@ -1003,7 +1003,7 @@ static WERROR cmd_spoolss_getdriver(struct cli_state *cli, /* Open a printer handle */ - werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", + werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", PRINTER_ACCESS_USE, servername, user, &pol); @@ -1018,7 +1018,7 @@ static WERROR cmd_spoolss_getdriver(struct cli_state *cli, for (i=0; archi_table[i].long_archi!=NULL; i++) { - werror = cli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level, + werror = rpccli_spoolss_getprinterdriver( cli, mem_ctx, &pol, info_level, archi_table[i].long_archi, archi_table[i].version, &ctr); @@ -1050,7 +1050,7 @@ static WERROR cmd_spoolss_getdriver(struct cli_state *cli, /* Cleanup */ if (opened_hnd) - cli_spoolss_close_printer (cli, mem_ctx, &pol); + rpccli_spoolss_close_printer (cli, mem_ctx, &pol); if ( success ) werror = WERR_OK; @@ -1061,7 +1061,7 @@ static WERROR cmd_spoolss_getdriver(struct cli_state *cli, /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_enum_drivers(struct cli_state *cli, +static WERROR cmd_spoolss_enum_drivers(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1089,7 +1089,7 @@ static WERROR cmd_spoolss_enum_drivers(struct cli_state *cli, if ( i>0 && strequal(archi_table[i].long_archi, archi_table[i-1].long_archi) ) continue; - werror = cli_spoolss_enumprinterdrivers( + werror = rpccli_spoolss_enumprinterdrivers( cli, mem_ctx, info_level, archi_table[i].long_archi, &returned, &ctr); @@ -1154,7 +1154,7 @@ static void display_printdriverdir_1(DRIVER_DIRECTORY_1 *i1) /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_getdriverdir(struct cli_state *cli, +static WERROR cmd_spoolss_getdriverdir(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1176,7 +1176,7 @@ static WERROR cmd_spoolss_getdriverdir(struct cli_state *cli, /* Get the directory. Only use Info level 1 */ - result = cli_spoolss_getprinterdriverdir(cli, mem_ctx, 1, env, &ctr); + result = rpccli_spoolss_getprinterdriverdir(cli, mem_ctx, 1, env, &ctr); if (W_ERROR_IS_OK(result)) display_printdriverdir_1(ctr.info1); @@ -1293,7 +1293,7 @@ static BOOL init_drv_info_3_members ( TALLOC_CTX *mem_ctx, DRIVER_INFO_3 *info, /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli, +static WERROR cmd_spoolss_addprinterdriver(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1344,7 +1344,7 @@ static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli, ctr.info3 = &info3; - result = cli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr); + result = rpccli_spoolss_addprinterdriver (cli, mem_ctx, level, &ctr); if (W_ERROR_IS_OK(result)) { rpcstr_pull(driver_name, info3.name.buffer, @@ -1360,7 +1360,7 @@ static WERROR cmd_spoolss_addprinterdriver(struct cli_state *cli, /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_addprinterex(struct cli_state *cli, +static WERROR cmd_spoolss_addprinterex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1377,7 +1377,7 @@ static WERROR cmd_spoolss_addprinterex(struct cli_state *cli, return WERR_OK; } - slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost); strupper_m(servername); /* Fill in the DRIVER_INFO_2 struct */ @@ -1407,7 +1407,7 @@ static WERROR cmd_spoolss_addprinterex(struct cli_state *cli, */ ctr.printers_2 = &info2; - result = cli_spoolss_addprinterex (cli, mem_ctx, level, &ctr); + result = rpccli_spoolss_addprinterex (cli, mem_ctx, level, &ctr); if (W_ERROR_IS_OK(result)) printf ("Printer %s successfully installed.\n", argv[1]); @@ -1418,7 +1418,7 @@ static WERROR cmd_spoolss_addprinterex(struct cli_state *cli, /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_setdriver(struct cli_state *cli, +static WERROR cmd_spoolss_setdriver(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1439,14 +1439,14 @@ static WERROR cmd_spoolss_setdriver(struct cli_state *cli, return WERR_OK; } - slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost); strupper_m(servername); slprintf(printername, sizeof(printername)-1, "%s\\%s", servername, argv[1]); fstrcpy(user, cli->user_name); /* Get a printer handle */ - result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", + result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", PRINTER_ALL_ACCESS, servername, user, &pol); @@ -1460,7 +1460,7 @@ static WERROR cmd_spoolss_setdriver(struct cli_state *cli, ZERO_STRUCT (info2); ctr.printers_2 = &info2; - result = cli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr); + result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, level, &ctr); if (!W_ERROR_IS_OK(result)) { printf ("Unable to retrieve printer information!\n"); @@ -1471,7 +1471,7 @@ static WERROR cmd_spoolss_setdriver(struct cli_state *cli, init_unistr(&ctr.printers_2->drivername, argv[2]); - result = cli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0); + result = rpccli_spoolss_setprinter(cli, mem_ctx, &pol, level, &ctr, 0); if (!W_ERROR_IS_OK(result)) { printf("SetPrinter call failed!\n"); @@ -1484,7 +1484,7 @@ done: /* Cleanup */ if (opened_hnd) - cli_spoolss_close_printer(cli, mem_ctx, &pol); + rpccli_spoolss_close_printer(cli, mem_ctx, &pol); return result; } @@ -1493,7 +1493,7 @@ done: /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_deletedriverex(struct cli_state *cli, +static WERROR cmd_spoolss_deletedriverex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1526,7 +1526,7 @@ static WERROR cmd_spoolss_deletedriverex(struct cli_state *cli, continue; /* make the call to remove the driver */ - result = cli_spoolss_deleteprinterdriverex( + result = rpccli_spoolss_deleteprinterdriverex( cli, mem_ctx, archi_table[i].long_archi, argv[1], archi_table[i].version); if ( !W_ERROR_IS_OK(result) ) @@ -1551,7 +1551,7 @@ static WERROR cmd_spoolss_deletedriverex(struct cli_state *cli, /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_deletedriver(struct cli_state *cli, +static WERROR cmd_spoolss_deletedriver(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1566,14 +1566,14 @@ static WERROR cmd_spoolss_deletedriver(struct cli_state *cli, return WERR_OK; } - slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost); strupper_m(servername); /* delete the driver for all architectures */ for (i=0; archi_table[i].long_archi; i++) { /* make the call to remove the driver */ - result = cli_spoolss_deleteprinterdriver( + result = rpccli_spoolss_deleteprinterdriver( cli, mem_ctx, archi_table[i].long_archi, argv[1]); if ( !W_ERROR_IS_OK(result) ) { @@ -1596,7 +1596,7 @@ static WERROR cmd_spoolss_deletedriver(struct cli_state *cli, /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_getprintprocdir(struct cli_state *cli, +static WERROR cmd_spoolss_getprintprocdir(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1610,7 +1610,7 @@ static WERROR cmd_spoolss_getprintprocdir(struct cli_state *cli, return WERR_OK; } - if (asprintf(&servername, "\\\\%s", cli->desthost) < 0) + if (asprintf(&servername, "\\\\%s", cli->cli->desthost) < 0) return WERR_NOMEM; strupper_m(servername); @@ -1620,7 +1620,7 @@ static WERROR cmd_spoolss_getprintprocdir(struct cli_state *cli, return WERR_NOMEM; } - result = cli_spoolss_getprintprocessordirectory( + result = rpccli_spoolss_getprintprocessordirectory( cli, mem_ctx, servername, environment, procdir); if (W_ERROR_IS_OK(result)) @@ -1635,7 +1635,7 @@ static WERROR cmd_spoolss_getprintprocdir(struct cli_state *cli, /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static WERROR cmd_spoolss_addform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { POLICY_HND handle; @@ -1653,11 +1653,11 @@ static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Get a printer handle */ - asprintf(&servername, "\\\\%s", cli->desthost); + asprintf(&servername, "\\\\%s", cli->cli->desthost); strupper_m(servername); asprintf(&printername, "%s\\%s", servername, argv[1]); - werror = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", + werror = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", PRINTER_ALL_ACCESS, servername, cli->user_name, &handle); @@ -1680,11 +1680,11 @@ static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Add the form */ - werror = cli_spoolss_addform(cli, mem_ctx, &handle, 1, &form); + werror = rpccli_spoolss_addform(cli, mem_ctx, &handle, 1, &form); done: if (got_handle) - cli_spoolss_close_printer(cli, mem_ctx, &handle); + rpccli_spoolss_close_printer(cli, mem_ctx, &handle); SAFE_FREE(servername); SAFE_FREE(printername); @@ -1695,7 +1695,7 @@ static WERROR cmd_spoolss_addform(struct cli_state *cli, TALLOC_CTX *mem_ctx, /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static WERROR cmd_spoolss_setform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { POLICY_HND handle; @@ -1713,11 +1713,11 @@ static WERROR cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Get a printer handle */ - asprintf(&servername, "\\\\%s", cli->desthost); + asprintf(&servername, "\\\\%s", cli->cli->desthost); strupper_m(servername); asprintf(&printername, "%s\\%s", servername, argv[1]); - werror = cli_spoolss_open_printer_ex( + werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &handle); @@ -1739,11 +1739,11 @@ static WERROR cmd_spoolss_setform(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Set the form */ - werror = cli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form); + werror = rpccli_spoolss_setform(cli, mem_ctx, &handle, 1, argv[2], &form); done: if (got_handle) - cli_spoolss_close_printer(cli, mem_ctx, &handle); + rpccli_spoolss_close_printer(cli, mem_ctx, &handle); SAFE_FREE(servername); SAFE_FREE(printername); @@ -1792,7 +1792,7 @@ static void display_form(FORM_1 *form) /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static WERROR cmd_spoolss_getform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { POLICY_HND handle; @@ -1810,11 +1810,11 @@ static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Get a printer handle */ - asprintf(&servername, "\\\\%s", cli->desthost); + asprintf(&servername, "\\\\%s", cli->cli->desthost); strupper_m(servername); asprintf(&printername, "%s\\%s", servername, argv[1]); - werror = cli_spoolss_open_printer_ex( + werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &handle); @@ -1825,7 +1825,7 @@ static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Get the form */ - werror = cli_spoolss_getform(cli, mem_ctx, &handle, argv[2], 1, &form); + werror = rpccli_spoolss_getform(cli, mem_ctx, &handle, argv[2], 1, &form); if (!W_ERROR_IS_OK(werror)) goto done; @@ -1834,7 +1834,7 @@ static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx, done: if (got_handle) - cli_spoolss_close_printer(cli, mem_ctx, &handle); + rpccli_spoolss_close_printer(cli, mem_ctx, &handle); SAFE_FREE(servername); SAFE_FREE(printername); @@ -1845,7 +1845,7 @@ static WERROR cmd_spoolss_getform(struct cli_state *cli, TALLOC_CTX *mem_ctx, /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_deleteform(struct cli_state *cli, +static WERROR cmd_spoolss_deleteform(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1863,11 +1863,11 @@ static WERROR cmd_spoolss_deleteform(struct cli_state *cli, /* Get a printer handle */ - asprintf(&servername, "\\\\%s", cli->desthost); + asprintf(&servername, "\\\\%s", cli->cli->desthost); strupper_m(servername); asprintf(&printername, "%s\\%s", servername, argv[1]); - werror = cli_spoolss_open_printer_ex( + werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &handle); @@ -1878,11 +1878,11 @@ static WERROR cmd_spoolss_deleteform(struct cli_state *cli, /* Delete the form */ - werror = cli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]); + werror = rpccli_spoolss_deleteform(cli, mem_ctx, &handle, argv[2]); done: if (got_handle) - cli_spoolss_close_printer(cli, mem_ctx, &handle); + rpccli_spoolss_close_printer(cli, mem_ctx, &handle); SAFE_FREE(servername); SAFE_FREE(printername); @@ -1893,7 +1893,7 @@ static WERROR cmd_spoolss_deleteform(struct cli_state *cli, /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_enum_forms(struct cli_state *cli, +static WERROR cmd_spoolss_enum_forms(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1913,11 +1913,11 @@ static WERROR cmd_spoolss_enum_forms(struct cli_state *cli, /* Get a printer handle */ - asprintf(&servername, "\\\\%s", cli->desthost); + asprintf(&servername, "\\\\%s", cli->cli->desthost); strupper_m(servername); asprintf(&printername, "%s\\%s", servername, argv[1]); - werror = cli_spoolss_open_printer_ex( + werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &handle); @@ -1929,7 +1929,7 @@ static WERROR cmd_spoolss_enum_forms(struct cli_state *cli, /* Enumerate forms */ offered = needed = 0; - werror = cli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms); + werror = rpccli_spoolss_enumforms(cli, mem_ctx, &handle, level, &num_forms, &forms); if (!W_ERROR_IS_OK(werror)) goto done; @@ -1944,7 +1944,7 @@ static WERROR cmd_spoolss_enum_forms(struct cli_state *cli, done: if (got_handle) - cli_spoolss_close_printer(cli, mem_ctx, &handle); + rpccli_spoolss_close_printer(cli, mem_ctx, &handle); SAFE_FREE(servername); SAFE_FREE(printername); @@ -1955,7 +1955,7 @@ static WERROR cmd_spoolss_enum_forms(struct cli_state *cli, /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli, +static WERROR cmd_spoolss_setprinterdata(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -1975,7 +1975,7 @@ static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli, return WERR_INVALID_PARAM; } - slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost); strupper_m(servername); slprintf(printername, sizeof(servername)-1, "%s\\%s", servername, argv[1]); fstrcpy(user, cli->user_name); @@ -2004,7 +2004,7 @@ static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli, } /* get a printer handle */ - result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", + result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, servername, user, &pol); if (!W_ERROR_IS_OK(result)) @@ -2014,7 +2014,7 @@ static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli, ctr.printers_0 = &info; - result = cli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr); + result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr); if (!W_ERROR_IS_OK(result)) goto done; @@ -2082,7 +2082,7 @@ static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli, goto done; } - result = cli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value); + result = rpccli_spoolss_setprinterdata(cli, mem_ctx, &pol, &value); if (!W_ERROR_IS_OK(result)) { printf ("Unable to set [%s=%s]!\n", argv[3], argv[4]); @@ -2090,7 +2090,7 @@ static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli, } printf("\tSetPrinterData succeeded [%s: %s]\n", argv[3], argv[4]); - result = cli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr); + result = rpccli_spoolss_getprinter(cli, mem_ctx, &pol, 0, &ctr); if (!W_ERROR_IS_OK(result)) goto done; @@ -2101,7 +2101,7 @@ static WERROR cmd_spoolss_setprinterdata(struct cli_state *cli, done: /* cleanup */ if (opened_hnd) - cli_spoolss_close_printer(cli, mem_ctx, &pol); + rpccli_spoolss_close_printer(cli, mem_ctx, &pol); return result; } @@ -2151,7 +2151,7 @@ static void display_job_info_2(JOB_INFO_2 *job) /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_enum_jobs(struct cli_state *cli, +static WERROR cmd_spoolss_enum_jobs(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -2173,14 +2173,14 @@ static WERROR cmd_spoolss_enum_jobs(struct cli_state *cli, /* Open printer handle */ - slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost); strupper_m(servername); fstrcpy(user, cli->user_name); - slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->desthost); + slprintf(printername, sizeof(servername)-1, "\\\\%s\\", cli->cli->desthost); strupper_m(printername); pstrcat(printername, argv[1]); - result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, + result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, servername, user, &hnd); @@ -2192,7 +2192,7 @@ static WERROR cmd_spoolss_enum_jobs(struct cli_state *cli, /* Enumerate ports */ offered = needed = 0; - result = cli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000, + result = rpccli_spoolss_enumjobs(cli, mem_ctx, &hnd, level, 0, 1000, &num_jobs, &ctr); if (!W_ERROR_IS_OK(result)) @@ -2214,7 +2214,7 @@ static WERROR cmd_spoolss_enum_jobs(struct cli_state *cli, done: if (got_hnd) - cli_spoolss_close_printer(cli, mem_ctx, &hnd); + rpccli_spoolss_close_printer(cli, mem_ctx, &hnd); return result; } @@ -2222,7 +2222,7 @@ done: /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_enum_data( struct cli_state *cli, +static WERROR cmd_spoolss_enum_data( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -2240,14 +2240,14 @@ static WERROR cmd_spoolss_enum_data( struct cli_state *cli, /* Open printer handle */ - slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost); strupper_m(servername); fstrcpy(user, cli->user_name); - slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost); + slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost); strupper_m(printername); pstrcat(printername, argv[1]); - result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, + result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, servername, user, &hnd); @@ -2258,12 +2258,12 @@ static WERROR cmd_spoolss_enum_data( struct cli_state *cli, /* Enumerate data */ - result = cli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0, + result = rpccli_spoolss_enumprinterdata(cli, mem_ctx, &hnd, i, 0, 0, &val_needed, &data_needed, NULL); while (W_ERROR_IS_OK(result)) { REGISTRY_VALUE value; - result = cli_spoolss_enumprinterdata( + result = rpccli_spoolss_enumprinterdata( cli, mem_ctx, &hnd, i++, val_needed, data_needed, 0, 0, &value); if (W_ERROR_IS_OK(result)) @@ -2274,7 +2274,7 @@ static WERROR cmd_spoolss_enum_data( struct cli_state *cli, done: if (got_hnd) - cli_spoolss_close_printer(cli, mem_ctx, &hnd); + rpccli_spoolss_close_printer(cli, mem_ctx, &hnd); return result; } @@ -2282,7 +2282,7 @@ done: /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_enum_data_ex( struct cli_state *cli, +static WERROR cmd_spoolss_enum_data_ex( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -2304,14 +2304,14 @@ static WERROR cmd_spoolss_enum_data_ex( struct cli_state *cli, /* Open printer handle */ - slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost); strupper_m(servername); fstrcpy(user, cli->user_name); - slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost); + slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost); strupper_m(printername); pstrcat(printername, argv[1]); - result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, + result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, servername, user, &hnd); @@ -2325,7 +2325,7 @@ static WERROR cmd_spoolss_enum_data_ex( struct cli_state *cli, if ( !(ctr = TALLOC_ZERO_P( mem_ctx, REGVAL_CTR )) ) return WERR_NOMEM; - result = cli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr); + result = rpccli_spoolss_enumprinterdataex(cli, mem_ctx, &hnd, keyname, ctr); if (!W_ERROR_IS_OK(result)) goto done; @@ -2338,7 +2338,7 @@ static WERROR cmd_spoolss_enum_data_ex( struct cli_state *cli, done: if (got_hnd) - cli_spoolss_close_printer(cli, mem_ctx, &hnd); + rpccli_spoolss_close_printer(cli, mem_ctx, &hnd); return result; } @@ -2346,7 +2346,7 @@ done: /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_enum_printerkey( struct cli_state *cli, +static WERROR cmd_spoolss_enum_printerkey( struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -2370,14 +2370,14 @@ static WERROR cmd_spoolss_enum_printerkey( struct cli_state *cli, /* Open printer handle */ - slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->cli->desthost); strupper_m(servername); fstrcpy(user, cli->user_name); - slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->desthost); + slprintf(printername, sizeof(printername)-1, "\\\\%s\\", cli->cli->desthost); strupper_m(printername); pstrcat(printername, argv[1]); - result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername, + result = rpccli_spoolss_open_printer_ex(cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, servername, user, &hnd); @@ -2388,7 +2388,7 @@ static WERROR cmd_spoolss_enum_printerkey( struct cli_state *cli, /* Enumerate subkeys */ - result = cli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL); + result = rpccli_spoolss_enumprinterkey(cli, mem_ctx, &hnd, keyname, &keylist, NULL); if (!W_ERROR_IS_OK(result)) goto done; @@ -2406,7 +2406,7 @@ static WERROR cmd_spoolss_enum_printerkey( struct cli_state *cli, done: if (got_hnd) - cli_spoolss_close_printer(cli, mem_ctx, &hnd); + rpccli_spoolss_close_printer(cli, mem_ctx, &hnd); return result; } @@ -2414,7 +2414,7 @@ done: /**************************************************************************** ****************************************************************************/ -static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli, +static WERROR cmd_spoolss_rffpcnex(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -2432,14 +2432,14 @@ static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli, /* Open printer */ - slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->desthost); + slprintf(servername, sizeof(servername) - 1, "\\\\%s", cli->cli->desthost); strupper_m(servername); - slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->desthost, + slprintf(printername, sizeof(printername) - 1, "\\\\%s\\%s", cli->cli->desthost, argv[1]); strupper_m(printername); - result = cli_spoolss_open_printer_ex( + result = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername, "", MAXIMUM_ALLOWED_ACCESS, servername, cli->user_name, &hnd); @@ -2477,7 +2477,7 @@ static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli, slprintf(servername, sizeof(servername) - 1, "\\\\%s", myhostname()); strupper_m(servername); - result = cli_spoolss_rffpcnex( + result = rpccli_spoolss_rffpcnex( cli, mem_ctx, &hnd, 0, 0, servername, 123, &option); if (!W_ERROR_IS_OK(result)) { @@ -2487,44 +2487,236 @@ static WERROR cmd_spoolss_rffpcnex(struct cli_state *cli, done: if (got_hnd) - cli_spoolss_close_printer(cli, mem_ctx, &hnd); + rpccli_spoolss_close_printer(cli, mem_ctx, &hnd); return result; } +/**************************************************************************** +****************************************************************************/ + +static BOOL compare_printer( struct rpc_pipe_client *cli1, POLICY_HND *hnd1, + struct rpc_pipe_client *cli2, POLICY_HND *hnd2 ) +{ + PRINTER_INFO_CTR ctr1, ctr2; + WERROR werror; + TALLOC_CTX *mem_ctx = talloc_init("compare_printer"); + + printf("Retrieving printer propertiesfor %s...", cli1->cli->desthost); + werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 2, &ctr1); + if ( !W_ERROR_IS_OK(werror) ) { + printf("failed (%s)\n", dos_errstr(werror)); + talloc_destroy(mem_ctx); + return False; + } + printf("ok\n"); + + printf("Retrieving printer properties for %s...", cli2->cli->desthost); + werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 2, &ctr2); + if ( !W_ERROR_IS_OK(werror) ) { + printf("failed (%s)\n", dos_errstr(werror)); + talloc_destroy(mem_ctx); + return False; + } + printf("ok\n"); + + talloc_destroy(mem_ctx); + + return True; +} + +/**************************************************************************** +****************************************************************************/ + +static BOOL compare_printer_secdesc( struct rpc_pipe_client *cli1, POLICY_HND *hnd1, + struct rpc_pipe_client *cli2, POLICY_HND *hnd2 ) +{ + PRINTER_INFO_CTR ctr1, ctr2; + WERROR werror; + TALLOC_CTX *mem_ctx = talloc_init("compare_printer_secdesc"); + SEC_DESC *sd1, *sd2; + BOOL result = True; + + + printf("Retreiving printer security for %s...", cli1->cli->desthost); + werror = rpccli_spoolss_getprinter( cli1, mem_ctx, hnd1, 3, &ctr1); + if ( !W_ERROR_IS_OK(werror) ) { + printf("failed (%s)\n", dos_errstr(werror)); + result = False; + goto done; + } + printf("ok\n"); + + printf("Retrieving printer security for %s...", cli2->cli->desthost); + werror = rpccli_spoolss_getprinter( cli2, mem_ctx, hnd2, 3, &ctr2); + if ( !W_ERROR_IS_OK(werror) ) { + printf("failed (%s)\n", dos_errstr(werror)); + result = False; + goto done; + } + printf("ok\n"); + + + printf("++ "); + + if ( (ctr1.printers_3 != ctr2.printers_3) && (!ctr1.printers_3 || !ctr2.printers_3) ) { + printf("NULL PRINTER_INFO_3!\n"); + result = False; + goto done; + } + + sd1 = ctr1.printers_3->secdesc; + sd2 = ctr2.printers_3->secdesc; + + if ( (sd1 != sd2) && ( !sd1 || !sd2 ) ) { + printf("NULL secdesc!\n"); + result = False; + goto done; + } + + if ( (ctr1.printers_3->flags != ctr1.printers_3->flags ) || !sec_desc_equal( sd1, sd2 ) ) { + printf("Security Descriptors *not* equal!\n"); + result = False; + goto done; + } + + printf("Security descriptors match\n"); + +done: + talloc_destroy(mem_ctx); + return result; +} + + +/**************************************************************************** +****************************************************************************/ + +static WERROR cmd_spoolss_printercmp(struct rpc_pipe_client *cli, + TALLOC_CTX *mem_ctx, int argc, + const char **argv) +{ + fstring printername, servername1, servername2; + pstring printername_path; + struct cli_state *cli_server1 = cli->cli; + struct cli_state *cli_server2 = NULL; + struct rpc_pipe_client *cli2 = NULL; + POLICY_HND hPrinter1, hPrinter2; + NTSTATUS nt_status; + WERROR werror; + + if ( argc != 3 ) { + printf("Usage: %s \n", argv[0]); + return WERR_OK; + } + + fstrcpy( printername, argv[1] ); + + fstr_sprintf( servername1, cli->cli->desthost ); + fstrcpy( servername2, argv[2] ); + strupper_m( servername1 ); + strupper_m( servername2 ); + + + /* first get the connection to the remote server */ + + nt_status = cli_full_connection(&cli_server2, global_myname(), servername2, + NULL, 0, + "IPC$", "IPC", + cmdline_auth_info.username, + lp_workgroup(), + cmdline_auth_info.password, + cmdline_auth_info.use_kerberos ? CLI_FULL_CONNECTION_USE_KERBEROS : 0, + cmdline_auth_info.signing_state, NULL); + + if ( !NT_STATUS_IS_OK(nt_status) ) + return WERR_GENERAL_FAILURE; + + cli2 = cli_rpc_pipe_open_noauth(cli_server2, PI_SPOOLSS, &nt_status); + if (!cli2) { + printf("failed to open spoolss pipe on server %s (%s)\n", + servername2, nt_errstr(nt_status)); + return WERR_GENERAL_FAILURE; + } + + /* now open up both printers */ + + pstr_sprintf( printername_path, "\\\\%s\\%s", servername1, printername ); + printf("Opening %s...", printername_path); + werror = rpccli_spoolss_open_printer_ex( cli, mem_ctx, printername_path, + "", PRINTER_ALL_ACCESS, servername1, cli_server1->user_name, &hPrinter1); + if ( !W_ERROR_IS_OK(werror) ) { + printf("failed (%s)\n", dos_errstr(werror)); + goto done; + } + printf("ok\n"); + + pstr_sprintf( printername_path, "\\\\%s\\%s", servername2, printername ); + printf("Opening %s...", printername_path); + werror = rpccli_spoolss_open_printer_ex( cli2, mem_ctx, printername_path, + "", PRINTER_ALL_ACCESS, servername2, cli_server2->user_name, &hPrinter2 ); + if ( !W_ERROR_IS_OK(werror) ) { + printf("failed (%s)\n", dos_errstr(werror)); + goto done; + } + printf("ok\n"); + + + compare_printer( cli, &hPrinter1, cli2, &hPrinter2 ); + compare_printer_secdesc( cli, &hPrinter1, cli2, &hPrinter2 ); +#if 0 + compare_printerdata( cli_server1, &hPrinter1, cli_server2, &hPrinter2 ); +#endif + + +done: + /* cleanup */ + + printf("Closing printers..."); + rpccli_spoolss_close_printer( cli, mem_ctx, &hPrinter1 ); + rpccli_spoolss_close_printer( cli2, mem_ctx, &hPrinter2 ); + printf("ok\n"); + + /* close the second remote connection */ + + cli_shutdown( cli_server2 ); + + return WERR_OK; +} + /* List of commands exported by this module */ struct cmd_set spoolss_commands[] = { { "SPOOLSS" }, - { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, PI_SPOOLSS, "Add a print driver", "" }, - { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, PI_SPOOLSS, "Add a printer", "" }, - { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, PI_SPOOLSS, "Delete a printer driver", "" }, - { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, PI_SPOOLSS, "Delete a printer driver with files", "" }, - { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, PI_SPOOLSS, "Enumerate printer data", "" }, - { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, PI_SPOOLSS, "Enumerate printer data for a key", "" }, - { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, PI_SPOOLSS, "Enumerate printer keys", "" }, - { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, PI_SPOOLSS, "Enumerate print jobs", "" }, - { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, PI_SPOOLSS, "Enumerate printer ports", "" }, - { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, PI_SPOOLSS, "Enumerate installed printer drivers", "" }, - { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, PI_SPOOLSS, "Enumerate printers", "" }, - { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, PI_SPOOLSS, "Get print driver data", "" }, - { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, PI_SPOOLSS, "Get printer driver data with keyname", ""}, - { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, PI_SPOOLSS, "Get print driver information", "" }, - { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, PI_SPOOLSS, "Get print driver upload directory", "" }, - { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, PI_SPOOLSS, "Get printer info", "" }, - { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, PI_SPOOLSS, "Open printer handle", "" }, - { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, PI_SPOOLSS, "Set printer driver", "" }, - { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, PI_SPOOLSS, "Get print processor directory", "" }, - { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, PI_SPOOLSS, "Add form", "" }, - { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, PI_SPOOLSS, "Set form", "" }, - { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, PI_SPOOLSS, "Get form", "" }, - { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, PI_SPOOLSS, "Delete form", "" }, - { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, PI_SPOOLSS, "Enumerate forms", "" }, - { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, PI_SPOOLSS, "Set printer comment", "" }, - { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, PI_SPOOLSS, "Set printername", "" }, - { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, PI_SPOOLSS, "Set REG_SZ printer data", "" }, - { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, PI_SPOOLSS, "Rffpcnex test", "" }, + { "adddriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterdriver, PI_SPOOLSS, NULL, "Add a print driver", "" }, + { "addprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addprinterex, PI_SPOOLSS, NULL, "Add a printer", "" }, + { "deldriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriver, PI_SPOOLSS, NULL, "Delete a printer driver", "" }, + { "deldriverex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deletedriverex, PI_SPOOLSS, NULL, "Delete a printer driver with files", "" }, + { "enumdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data, PI_SPOOLSS, NULL, "Enumerate printer data", "" }, + { "enumdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_data_ex, PI_SPOOLSS, NULL, "Enumerate printer data for a key", "" }, + { "enumkey", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printerkey, PI_SPOOLSS, NULL, "Enumerate printer keys", "" }, + { "enumjobs", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_jobs, PI_SPOOLSS, NULL, "Enumerate print jobs", "" }, + { "enumports", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_ports, PI_SPOOLSS, NULL, "Enumerate printer ports", "" }, + { "enumdrivers", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_drivers, PI_SPOOLSS, NULL, "Enumerate installed printer drivers", "" }, + { "enumprinters", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_printers, PI_SPOOLSS, NULL, "Enumerate printers", "" }, + { "getdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdata, PI_SPOOLSS, NULL, "Get print driver data", "" }, + { "getdataex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinterdataex, PI_SPOOLSS, NULL, "Get printer driver data with keyname", ""}, + { "getdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriver, PI_SPOOLSS, NULL, "Get print driver information", "" }, + { "getdriverdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getdriverdir, PI_SPOOLSS, NULL, "Get print driver upload directory", "" }, + { "getprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprinter, PI_SPOOLSS, NULL, "Get printer info", "" }, + { "openprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_open_printer_ex, PI_SPOOLSS, NULL, "Open printer handle", "" }, + { "setdriver", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setdriver, PI_SPOOLSS, NULL, "Set printer driver", "" }, + { "getprintprocdir", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getprintprocdir, PI_SPOOLSS, NULL, "Get print processor directory", "" }, + { "addform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_addform, PI_SPOOLSS, NULL, "Add form", "" }, + { "setform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setform, PI_SPOOLSS, NULL, "Set form", "" }, + { "getform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_getform, PI_SPOOLSS, NULL, "Get form", "" }, + { "deleteform", RPC_RTYPE_WERROR, NULL, cmd_spoolss_deleteform, PI_SPOOLSS, NULL, "Delete form", "" }, + { "enumforms", RPC_RTYPE_WERROR, NULL, cmd_spoolss_enum_forms, PI_SPOOLSS, NULL, "Enumerate forms", "" }, + { "setprinter", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinter, PI_SPOOLSS, NULL, "Set printer comment", "" }, + { "setprintername", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprintername, PI_SPOOLSS, NULL, "Set printername", "" }, + { "setprinterdata", RPC_RTYPE_WERROR, NULL, cmd_spoolss_setprinterdata, PI_SPOOLSS, NULL, "Set REG_SZ printer data", "" }, + { "rffpcnex", RPC_RTYPE_WERROR, NULL, cmd_spoolss_rffpcnex, PI_SPOOLSS, NULL, "Rffpcnex test", "" }, + { "printercmp", RPC_RTYPE_WERROR, NULL, cmd_spoolss_printercmp, PI_SPOOLSS, NULL, "Printer comparison test", "" }, { NULL } }; diff --git a/source3/rpcclient/cmd_srvsvc.c b/source3/rpcclient/cmd_srvsvc.c index 1d173ffdff1..da81a82c8d5 100644 --- a/source3/rpcclient/cmd_srvsvc.c +++ b/source3/rpcclient/cmd_srvsvc.c @@ -179,7 +179,7 @@ static void display_srv_info_102(SRV_INFO_102 *sv102) } /* Server query info */ -static WERROR cmd_srvsvc_srv_query_info(struct cli_state *cli, +static WERROR cmd_srvsvc_srv_query_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -195,7 +195,7 @@ static WERROR cmd_srvsvc_srv_query_info(struct cli_state *cli, if (argc == 2) info_level = atoi(argv[1]); - result = cli_srvsvc_net_srv_get_info(cli, mem_ctx, info_level, + result = rpccli_srvsvc_net_srv_get_info(cli, mem_ctx, info_level, &ctr); if (!W_ERROR_IS_OK(result)) { @@ -270,7 +270,7 @@ static void display_share_info_502(SRV_SHARE_INFO_502 *info502) } -static WERROR cmd_srvsvc_net_share_enum(struct cli_state *cli, +static WERROR cmd_srvsvc_net_share_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -290,7 +290,7 @@ static WERROR cmd_srvsvc_net_share_enum(struct cli_state *cli, init_enum_hnd(&hnd, 0); - result = cli_srvsvc_net_share_enum( + result = rpccli_srvsvc_net_share_enum( cli, mem_ctx, info_level, &ctr, preferred_len, &hnd); if (!W_ERROR_IS_OK(result) || !ctr.num_entries) @@ -320,7 +320,7 @@ static WERROR cmd_srvsvc_net_share_enum(struct cli_state *cli, return result; } -static WERROR cmd_srvsvc_net_share_get_info(struct cli_state *cli, +static WERROR cmd_srvsvc_net_share_get_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -336,7 +336,7 @@ static WERROR cmd_srvsvc_net_share_get_info(struct cli_state *cli, if (argc == 3) info_level = atoi(argv[2]); - result = cli_srvsvc_net_share_get_info(cli, mem_ctx, argv[1], info_level, &info); + result = rpccli_srvsvc_net_share_get_info(cli, mem_ctx, argv[1], info_level, &info); if (!W_ERROR_IS_OK(result)) goto done; @@ -362,7 +362,7 @@ static WERROR cmd_srvsvc_net_share_get_info(struct cli_state *cli, return result; } -static WERROR cmd_srvsvc_net_share_set_info(struct cli_state *cli, +static WERROR cmd_srvsvc_net_share_set_info(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -376,7 +376,7 @@ static WERROR cmd_srvsvc_net_share_set_info(struct cli_state *cli, } /* retrieve share info */ - result = cli_srvsvc_net_share_get_info(cli, mem_ctx, argv[1], info_level, &info_get); + result = rpccli_srvsvc_net_share_get_info(cli, mem_ctx, argv[1], info_level, &info_get); if (!W_ERROR_IS_OK(result)) goto done; @@ -385,13 +385,13 @@ static WERROR cmd_srvsvc_net_share_set_info(struct cli_state *cli, init_unistr2(&(info_get.share.info502.info_502_str.uni_remark), argv[2], UNI_STR_TERMINATE); /* set share info */ - result = cli_srvsvc_net_share_set_info(cli, mem_ctx, argv[1], info_level, &info_get); + result = rpccli_srvsvc_net_share_set_info(cli, mem_ctx, argv[1], info_level, &info_get); if (!W_ERROR_IS_OK(result)) goto done; /* re-retrieve share info and display */ - result = cli_srvsvc_net_share_get_info(cli, mem_ctx, argv[1], info_level, &info_get); + result = rpccli_srvsvc_net_share_get_info(cli, mem_ctx, argv[1], info_level, &info_get); if (!W_ERROR_IS_OK(result)) goto done; @@ -401,11 +401,12 @@ static WERROR cmd_srvsvc_net_share_set_info(struct cli_state *cli, return result; } -static WERROR cmd_srvsvc_net_remote_tod(struct cli_state *cli, +static WERROR cmd_srvsvc_net_remote_tod(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { TIME_OF_DAY_INFO tod; + fstring srv_name_slash; WERROR result; if (argc > 1) { @@ -413,8 +414,9 @@ static WERROR cmd_srvsvc_net_remote_tod(struct cli_state *cli, return WERR_OK; } - result = cli_srvsvc_net_remote_tod( - cli, mem_ctx, cli->srv_name_slash, &tod); + fstr_sprintf(srv_name_slash, "\\\\%s", cli->cli->desthost); + result = rpccli_srvsvc_net_remote_tod( + cli, mem_ctx, srv_name_slash, &tod); if (!W_ERROR_IS_OK(result)) goto done; @@ -423,7 +425,7 @@ static WERROR cmd_srvsvc_net_remote_tod(struct cli_state *cli, return result; } -static WERROR cmd_srvsvc_net_file_enum(struct cli_state *cli, +static WERROR cmd_srvsvc_net_file_enum(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { @@ -445,7 +447,7 @@ static WERROR cmd_srvsvc_net_file_enum(struct cli_state *cli, ZERO_STRUCT(ctr); - result = cli_srvsvc_net_file_enum( + result = rpccli_srvsvc_net_file_enum( cli, mem_ctx, info_level, NULL, &ctr, preferred_len, &hnd); if (!W_ERROR_IS_OK(result)) @@ -461,12 +463,12 @@ struct cmd_set srvsvc_commands[] = { { "SRVSVC" }, - { "srvinfo", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_srv_query_info, PI_SRVSVC, "Server query info", "" }, - { "netshareenum",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_enum, PI_SRVSVC, "Enumerate shares", "" }, - { "netsharegetinfo",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_get_info, PI_SRVSVC, "Get Share Info", "" }, - { "netsharesetinfo",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_set_info, PI_SRVSVC, "Set Share Info", "" }, - { "netfileenum", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_file_enum, PI_SRVSVC, "Enumerate open files", "" }, - { "netremotetod",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_remote_tod, PI_SRVSVC, "Fetch remote time of day", "" }, + { "srvinfo", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_srv_query_info, PI_SRVSVC, NULL, "Server query info", "" }, + { "netshareenum",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_enum, PI_SRVSVC, NULL, "Enumerate shares", "" }, + { "netsharegetinfo",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_get_info, PI_SRVSVC, NULL, "Get Share Info", "" }, + { "netsharesetinfo",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_share_set_info, PI_SRVSVC, NULL, "Set Share Info", "" }, + { "netfileenum", RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_file_enum, PI_SRVSVC, NULL, "Enumerate open files", "" }, + { "netremotetod",RPC_RTYPE_WERROR, NULL, cmd_srvsvc_net_remote_tod, PI_SRVSVC, NULL, "Fetch remote time of day", "" }, { NULL } }; diff --git a/source3/rpcclient/cmd_test.c b/source3/rpcclient/cmd_test.c new file mode 100644 index 00000000000..94545dc74e6 --- /dev/null +++ b/source3/rpcclient/cmd_test.c @@ -0,0 +1,68 @@ +/* + Unix SMB/CIFS implementation. + RPC pipe client + + 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" +#include "rpcclient.h" + +static NTSTATUS cmd_testme(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv) +{ + struct rpc_pipe_client *lsa_pipe = NULL, *samr_pipe = NULL; + NTSTATUS status = NT_STATUS_UNSUCCESSFUL; + POLICY_HND pol; + + d_printf("testme\n"); + + lsa_pipe = cli_rpc_pipe_open_noauth(cli->cli, PI_LSARPC, &status); + if (lsa_pipe == NULL) goto done; + + samr_pipe = cli_rpc_pipe_open_noauth(cli->cli, PI_SAMR, &status); + if (samr_pipe == NULL) goto done; + + status = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, False, + SEC_RIGHTS_QUERY_VALUE, &pol); + + if (!NT_STATUS_IS_OK(status)) + goto done; + + status = rpccli_lsa_close(lsa_pipe, mem_ctx, &pol); + + if (!NT_STATUS_IS_OK(status)) + goto done; + + done: + if (lsa_pipe != NULL) cli_rpc_pipe_close(lsa_pipe); + if (samr_pipe != NULL) cli_rpc_pipe_close(samr_pipe); + + return status; +} + +/* List of commands exported by this module */ + +struct cmd_set test_commands[] = { + + { "TESTING" }, + + { "testme", RPC_RTYPE_NTSTATUS, cmd_testme, NULL, + -1, NULL, "Sample test", "testme" }, + + { NULL } +}; diff --git a/source3/rpcclient/cmd_wkssvc.c b/source3/rpcclient/cmd_wkssvc.c index 137ff3bdae9..a65cd1f799f 100644 --- a/source3/rpcclient/cmd_wkssvc.c +++ b/source3/rpcclient/cmd_wkssvc.c @@ -19,6 +19,8 @@ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA. */ +THIS IS NO LONGER USED - NEEDS REMOVAL. + #include "includes.h" #define DEBUG_TESTING diff --git a/source3/rpcclient/rpcclient.c b/source3/rpcclient/rpcclient.c index 34e81cafe68..630add0e9bd 100644 --- a/source3/rpcclient/rpcclient.c +++ b/source3/rpcclient/rpcclient.c @@ -25,6 +25,8 @@ DOM_SID domain_sid; +static enum pipe_auth_type pipe_default_auth_type = PIPE_AUTH_TYPE_NONE; +static enum pipe_auth_level pipe_default_auth_level = PIPE_AUTH_LEVEL_NONE; /* List to hold groups of commands. * @@ -128,29 +130,28 @@ static void fetch_machine_sid(struct cli_state *cli) static BOOL got_domain_sid; TALLOC_CTX *mem_ctx; DOM_SID *dom_sid = NULL; + struct rpc_pipe_client *lsapipe = NULL; if (got_domain_sid) return; - if (!(mem_ctx=talloc_init("fetch_machine_sid"))) - { + if (!(mem_ctx=talloc_init("fetch_machine_sid"))) { DEBUG(0,("fetch_machine_sid: talloc_init returned NULL!\n")); goto error; } - - if (!cli_nt_session_open (cli, PI_LSARPC)) { - fprintf(stderr, "could not initialise lsa pipe\n"); + if ((lsapipe = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result)) == NULL) { + fprintf(stderr, "could not initialise lsa pipe. Error was %s\n", nt_errstr(result) ); goto error; } - result = cli_lsa_open_policy(cli, mem_ctx, True, + result = rpccli_lsa_open_policy(lsapipe, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); if (!NT_STATUS_IS_OK(result)) { goto error; } - result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class, + result = rpccli_lsa_query_info_policy(lsapipe, mem_ctx, &pol, info_class, &domain_name, &dom_sid); if (!NT_STATUS_IS_OK(result)) { goto error; @@ -159,13 +160,18 @@ static void fetch_machine_sid(struct cli_state *cli) got_domain_sid = True; sid_copy( &domain_sid, dom_sid ); - cli_lsa_close(cli, mem_ctx, &pol); - cli_nt_session_close(cli); + rpccli_lsa_close(lsapipe, mem_ctx, &pol); + cli_rpc_pipe_close(lsapipe); talloc_destroy(mem_ctx); return; error: + + if (lsapipe) { + cli_rpc_pipe_close(lsapipe); + } + fprintf(stderr, "could not obtain sid for domain %s\n", cli->domain); if (!NT_STATUS_IS_OK(result)) { @@ -177,7 +183,7 @@ static void fetch_machine_sid(struct cli_state *cli) /* List the available commands on a given pipe */ -static NTSTATUS cmd_listcommands(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static NTSTATUS cmd_listcommands(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { struct cmd_list *tmp; @@ -222,7 +228,7 @@ static NTSTATUS cmd_listcommands(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Display help on commands */ -static NTSTATUS cmd_help(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static NTSTATUS cmd_help(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { struct cmd_list *tmp; @@ -282,7 +288,7 @@ static NTSTATUS cmd_help(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Change the debug level */ -static NTSTATUS cmd_debuglevel(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static NTSTATUS cmd_debuglevel(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { if (argc > 2) { @@ -299,114 +305,118 @@ static NTSTATUS cmd_debuglevel(struct cli_state *cli, TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -static NTSTATUS cmd_quit(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static NTSTATUS cmd_quit(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { exit(0); return NT_STATUS_OK; /* NOTREACHED */ } -static NTSTATUS cmd_sign(struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) +static NTSTATUS cmd_set_ss_level(void) { - if (cli->pipe_auth_flags == (AUTH_PIPE_NTLMSSP|AUTH_PIPE_SIGN)) { - return NT_STATUS_OK; - } else { - /* still have session, just need to use it again */ - cli->pipe_auth_flags = AUTH_PIPE_NTLMSSP; - cli->pipe_auth_flags |= AUTH_PIPE_SIGN; - if (cli->pipes[cli->pipe_idx].fnum != 0) - cli_nt_session_close(cli); - } + struct cmd_list *tmp; - return NT_STATUS_OK; -} + /* Close any existing connections not at this level. */ -static NTSTATUS cmd_seal(struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) -{ - if (cli->pipe_auth_flags == (AUTH_PIPE_NTLMSSP|AUTH_PIPE_SIGN|AUTH_PIPE_SEAL)) { - return NT_STATUS_OK; - } else { - /* still have session, just need to use it again */ - cli->pipe_auth_flags = AUTH_PIPE_NTLMSSP; - cli->pipe_auth_flags |= AUTH_PIPE_SIGN; - cli->pipe_auth_flags |= AUTH_PIPE_SEAL; - if (cli->pipes[cli->pipe_idx].fnum != 0) - cli_nt_session_close(cli); - } - return NT_STATUS_OK; + for (tmp = cmd_list; tmp; tmp = tmp->next) { + struct cmd_set *tmp_set; + + for (tmp_set = tmp->cmd_set; tmp_set->name; tmp_set++) { + if (tmp_set->rpc_pipe == NULL) { + continue; + } + + if (tmp_set->rpc_pipe->auth.auth_type != pipe_default_auth_type || + tmp_set->rpc_pipe->auth.auth_level != pipe_default_auth_level) { + cli_rpc_pipe_close(tmp_set->rpc_pipe); + tmp_set->rpc_pipe = NULL; + } + } + } + return NT_STATUS_OK; } -static NTSTATUS cmd_none(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static NTSTATUS cmd_sign(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { - if (cli->pipe_auth_flags == 0) { + pipe_default_auth_level = PIPE_AUTH_LEVEL_INTEGRITY; + pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP; + + if (argc > 2) { + printf("Usage: %s [NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]\n", argv[0]); return NT_STATUS_OK; - } else { - /* still have session, just need to use it again */ - cli->pipe_auth_flags = 0; - if (cli->pipes[cli->pipe_idx].fnum != 0) - cli_nt_session_close(cli); } - cli->pipe_auth_flags = 0; - return NT_STATUS_OK; -} - -static NTSTATUS setup_schannel(struct cli_state *cli, int pipe_auth_flags, - int argc, const char **argv) -{ - NTSTATUS ret; - static uchar zeros[16]; - uchar trust_password[16]; - uint32 sec_channel_type; if (argc == 2) { - strhex_to_str(cli->sess_key, strlen(argv[1]), argv[1]); - cli->pipe_auth_flags = pipe_auth_flags; - return NT_STATUS_OK; + if (strequal(argv[1], "NTLMSSP")) { + pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP; + } else if (strequal(argv[1], "NTLMSSP_SPNEGO")) { + pipe_default_auth_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP; + } else if (strequal(argv[1], "SCHANNEL")) { + pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL; + } else { + printf("unknown type %s\n", argv[1]); + return NT_STATUS_INVALID_LEVEL; + } } - /* Cleanup */ + printf("debuglevel is %d\n", DEBUGLEVEL); + return cmd_set_ss_level(); +} - if ((memcmp(cli->sess_key, zeros, sizeof(cli->sess_key)) != 0) && - (cli->pipe_auth_flags == pipe_auth_flags)) { - /* already in this mode nothing to do */ - return NT_STATUS_OK; - } - - if (!secrets_fetch_trust_account_password(lp_workgroup(), - trust_password, - NULL, &sec_channel_type)) { - return NT_STATUS_UNSUCCESSFUL; +static NTSTATUS cmd_seal(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv) +{ + pipe_default_auth_level = PIPE_AUTH_LEVEL_PRIVACY; + pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP; + + if (argc > 2) { + printf("Usage: %s [NTLMSSP|NTLMSSP_SPNEGO|SCHANNEL]\n", argv[0]); + return NT_STATUS_OK; } - ret = cli_nt_setup_netsec(cli, sec_channel_type, pipe_auth_flags, trust_password); - if (NT_STATUS_IS_OK(ret)) { - char *hex_session_key; - hex_session_key = hex_encode(NULL, cli->pipes[cli->pipe_idx].auth_info.sess_key, - sizeof(cli->pipes[cli->pipe_idx].auth_info.sess_key)); - printf("Got Session key: %s\n", hex_session_key); - talloc_free(hex_session_key); + if (argc == 2) { + if (strequal(argv[1], "NTLMSSP")) { + pipe_default_auth_type = PIPE_AUTH_TYPE_NTLMSSP; + } else if (strequal(argv[1], "NTLMSSP_SPNEGO")) { + pipe_default_auth_type = PIPE_AUTH_TYPE_SPNEGO_NTLMSSP; + } else if (strequal(argv[1], "SCHANNEL")) { + pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL; + } else { + printf("unknown type %s\n", argv[1]); + return NT_STATUS_INVALID_LEVEL; + } } - return ret; + return cmd_set_ss_level(); } +static NTSTATUS cmd_none(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, + int argc, const char **argv) +{ + pipe_default_auth_level = PIPE_AUTH_LEVEL_NONE; + pipe_default_auth_type = PIPE_AUTH_TYPE_NONE; + + return cmd_set_ss_level(); +} -static NTSTATUS cmd_schannel(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static NTSTATUS cmd_schannel(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { d_printf("Setting schannel - sign and seal\n"); - return setup_schannel(cli, AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN | AUTH_PIPE_SEAL, - argc, argv); + pipe_default_auth_level = PIPE_AUTH_LEVEL_PRIVACY; + pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL; + + return cmd_set_ss_level(); } -static NTSTATUS cmd_schannel_sign(struct cli_state *cli, TALLOC_CTX *mem_ctx, +static NTSTATUS cmd_schannel_sign(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv) { d_printf("Setting schannel - sign only\n"); - return setup_schannel(cli, AUTH_PIPE_NETSEC | AUTH_PIPE_SIGN, - argc, argv); + pipe_default_auth_level = PIPE_AUTH_LEVEL_INTEGRITY; + pipe_default_auth_type = PIPE_AUTH_TYPE_SCHANNEL; + + return cmd_set_ss_level(); } @@ -416,23 +426,23 @@ static struct cmd_set rpcclient_commands[] = { { "GENERAL OPTIONS" }, - { "help", RPC_RTYPE_NTSTATUS, cmd_help, NULL, -1, "Get help on commands", "[command]" }, - { "?", RPC_RTYPE_NTSTATUS, cmd_help, NULL, -1, "Get help on commands", "[command]" }, - { "debuglevel", RPC_RTYPE_NTSTATUS, cmd_debuglevel, NULL, -1, "Set debug level", "level" }, - { "list", RPC_RTYPE_NTSTATUS, cmd_listcommands, NULL, -1, "List available commands on ", "pipe" }, - { "exit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL, -1, "Exit program", "" }, - { "quit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL, -1, "Exit program", "" }, - { "sign", RPC_RTYPE_NTSTATUS, cmd_sign, NULL, -1, "Force RPC pipe connections to be signed", "" }, - { "seal", RPC_RTYPE_NTSTATUS, cmd_seal, NULL, -1, "Force RPC pipe connections to be sealed", "" }, - { "schannel", RPC_RTYPE_NTSTATUS, cmd_schannel, NULL, -1, "Force RPC pipe connections to be sealed with 'schannel' (NETSEC). Assumes valid machine account to this domain controller.", "" }, - { "schannelsign", RPC_RTYPE_NTSTATUS, cmd_schannel_sign, NULL, -1, "Force RPC pipe connections to be signed (not sealed) with 'schannel' (NETSEC). Assumes valid machine account to this domain controller.", "" }, - { "none", RPC_RTYPE_NTSTATUS, cmd_none, NULL, -1, "Force RPC pipe connections to have no special properties", "" }, + { "help", RPC_RTYPE_NTSTATUS, cmd_help, NULL, -1, NULL, "Get help on commands", "[command]" }, + { "?", RPC_RTYPE_NTSTATUS, cmd_help, NULL, -1, NULL, "Get help on commands", "[command]" }, + { "debuglevel", RPC_RTYPE_NTSTATUS, cmd_debuglevel, NULL, -1, NULL, "Set debug level", "level" }, + { "list", RPC_RTYPE_NTSTATUS, cmd_listcommands, NULL, -1, NULL, "List available commands on ", "pipe" }, + { "exit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL, -1, NULL, "Exit program", "" }, + { "quit", RPC_RTYPE_NTSTATUS, cmd_quit, NULL, -1, NULL, "Exit program", "" }, + { "sign", RPC_RTYPE_NTSTATUS, cmd_sign, NULL, -1, NULL, "Force RPC pipe connections to be signed", "" }, + { "seal", RPC_RTYPE_NTSTATUS, cmd_seal, NULL, -1, NULL, "Force RPC pipe connections to be sealed", "" }, + { "schannel", RPC_RTYPE_NTSTATUS, cmd_schannel, NULL, -1, NULL, "Force RPC pipe connections to be sealed with 'schannel'. Assumes valid machine account to this domain controller.", "" }, + { "schannelsign", RPC_RTYPE_NTSTATUS, cmd_schannel_sign, NULL, -1, NULL, "Force RPC pipe connections to be signed (not sealed) with 'schannel'. Assumes valid machine account to this domain controller.", "" }, + { "none", RPC_RTYPE_NTSTATUS, cmd_none, NULL, -1, NULL, "Force RPC pipe connections to have no special properties", "" }, { NULL } }; static struct cmd_set separator_command[] = { - { "---------------", MAX_RPC_RETURN_TYPE, NULL, NULL, -1, "----------------------" }, + { "---------------", MAX_RPC_RETURN_TYPE, NULL, NULL, -1, NULL, "----------------------" }, { NULL } }; @@ -449,6 +459,7 @@ extern struct cmd_set reg_commands[]; extern struct cmd_set ds_commands[]; extern struct cmd_set echo_commands[]; extern struct cmd_set shutdown_commands[]; +extern struct cmd_set test_commands[]; static struct cmd_set *rpcclient_command_list[] = { rpcclient_commands, @@ -462,6 +473,7 @@ static struct cmd_set *rpcclient_command_list[] = { reg_commands, echo_commands, shutdown_commands, + test_commands, NULL }; @@ -492,7 +504,6 @@ static NTSTATUS do_cmd(struct cli_state *cli, { NTSTATUS ntresult; WERROR wresult; - uchar trust_password[16]; TALLOC_CTX *mem_ctx; @@ -505,57 +516,93 @@ static NTSTATUS do_cmd(struct cli_state *cli, /* Open pipe */ - if (cmd_entry->pipe_idx != -1 - && cmd_entry->pipe_idx != cli->pipe_idx) { - if (cli->pipes[cli->pipe_idx].fnum != 0) - cli_nt_session_close(cli); - - if (!cli_nt_session_open(cli, cmd_entry->pipe_idx)) { - DEBUG(0, ("Could not initialise %s\n", - get_pipe_name_from_index(cmd_entry->pipe_idx))); - return NT_STATUS_UNSUCCESSFUL; + if (cmd_entry->pipe_idx != -1 && cmd_entry->rpc_pipe == NULL) { + switch (pipe_default_auth_type) { + case PIPE_AUTH_TYPE_NONE: + cmd_entry->rpc_pipe = cli_rpc_pipe_open_noauth(cli, + cmd_entry->pipe_idx, + &ntresult); + break; + case PIPE_AUTH_TYPE_SPNEGO_NTLMSSP: + cmd_entry->rpc_pipe = cli_rpc_pipe_open_spnego_ntlmssp(cli, + cmd_entry->pipe_idx, + pipe_default_auth_level, + lp_workgroup(), + cmdline_auth_info.username, + cmdline_auth_info.password, + &ntresult); + break; + case PIPE_AUTH_TYPE_NTLMSSP: + cmd_entry->rpc_pipe = cli_rpc_pipe_open_ntlmssp(cli, + cmd_entry->pipe_idx, + pipe_default_auth_level, + lp_workgroup(), + cmdline_auth_info.username, + cmdline_auth_info.password, + &ntresult); + break; + case PIPE_AUTH_TYPE_SCHANNEL: + cmd_entry->rpc_pipe = cli_rpc_pipe_open_schannel(cli, + cmd_entry->pipe_idx, + pipe_default_auth_level, + lp_workgroup(), + &ntresult); + break; + default: + DEBUG(0, ("Could not initialise %s. Invalid auth type %u\n", + cli_get_pipe_name(cmd_entry->pipe_idx), + pipe_default_auth_type )); + return NT_STATUS_UNSUCCESSFUL; + } + if (!cmd_entry->rpc_pipe) { + DEBUG(0, ("Could not initialise %s. Error was %s\n", + cli_get_pipe_name(cmd_entry->pipe_idx), + nt_errstr(ntresult) )); + return ntresult; } - } - - /* some of the DsXXX commands use the netlogon pipe */ - if (lp_client_schannel() && (cmd_entry->pipe_idx == PI_NETLOGON) && !(cli->pipe_auth_flags & AUTH_PIPE_NETSEC)) { - uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; - uint32 sec_channel_type; + if (cmd_entry->pipe_idx == PI_NETLOGON) { + uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint32 sec_channel_type; + uchar trust_password[16]; - if (!secrets_fetch_trust_account_password(lp_workgroup(), - trust_password, - NULL, &sec_channel_type)) { - return NT_STATUS_UNSUCCESSFUL; - } + if (!secrets_fetch_trust_account_password(lp_workgroup(), + trust_password, + NULL, &sec_channel_type)) { + return NT_STATUS_UNSUCCESSFUL; + } - ntresult = cli_nt_setup_creds(cli, sec_channel_type, - trust_password, - &neg_flags, 2); - if (!NT_STATUS_IS_OK(ntresult)) { - ZERO_STRUCT(cli->pipes[cli->pipe_idx].auth_info.sess_key); - printf("nt_setup_creds failed with %s\n", nt_errstr(ntresult)); - return ntresult; + ntresult = rpccli_netlogon_setup_creds(cmd_entry->rpc_pipe, + cli->desthost, + lp_workgroup(), + global_myname(), + trust_password, + sec_channel_type, + &neg_flags); + + if (!NT_STATUS_IS_OK(ntresult)) { + DEBUG(0, ("Could not initialise credentials for %s.\n", + cli_get_pipe_name(cmd_entry->pipe_idx))); + return ntresult; + } } - } - /* Run command */ + /* Run command */ - if ( cmd_entry->returntype == RPC_RTYPE_NTSTATUS ) { - ntresult = cmd_entry->ntfn(cli, mem_ctx, argc, (const char **) argv); - if (!NT_STATUS_IS_OK(ntresult)) { - printf("result was %s\n", nt_errstr(ntresult)); - } - } else { - wresult = cmd_entry->wfn( cli, mem_ctx, argc, (const char **) argv); - /* print out the DOS error */ - if (!W_ERROR_IS_OK(wresult)) { - printf( "result was %s\n", dos_errstr(wresult)); - } - ntresult = W_ERROR_IS_OK(wresult)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL; - } - + if ( cmd_entry->returntype == RPC_RTYPE_NTSTATUS ) { + ntresult = cmd_entry->ntfn(cmd_entry->rpc_pipe, mem_ctx, argc, (const char **) argv); + if (!NT_STATUS_IS_OK(ntresult)) { + printf("result was %s\n", nt_errstr(ntresult)); + } + } else { + wresult = cmd_entry->wfn(cmd_entry->rpc_pipe, mem_ctx, argc, (const char **) argv); + /* print out the DOS error */ + if (!W_ERROR_IS_OK(wresult)) { + printf( "result was %s\n", dos_errstr(wresult)); + } + ntresult = W_ERROR_IS_OK(wresult)?NT_STATUS_OK:NT_STATUS_UNSUCCESSFUL; + } /* Cleanup */ @@ -736,7 +783,9 @@ out_free: return 1; } +#if 0 /* COMMENT OUT FOR TESTING */ memset(cmdline_auth_info.password,'X',sizeof(cmdline_auth_info.password)); +#endif /* Load command lists */ diff --git a/source3/rpcclient/rpcclient.h b/source3/rpcclient/rpcclient.h index e1e61dc43d5..3c86c0be62e 100644 --- a/source3/rpcclient/rpcclient.h +++ b/source3/rpcclient/rpcclient.h @@ -30,11 +30,12 @@ typedef enum { struct cmd_set { const char *name; - RPC_RETURN_TYPE returntype; - NTSTATUS (*ntfn)(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, - const char **argv); - WERROR (*wfn)(struct cli_state *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv); - int pipe_idx; + RPC_RETURN_TYPE returntype; + NTSTATUS (*ntfn)(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, + const char **argv); + WERROR (*wfn)(struct rpc_pipe_client *cli, TALLOC_CTX *mem_ctx, int argc, const char **argv); + int pipe_idx; + struct rpc_pipe_client *rpc_pipe; const char *description; const char *usage; }; diff --git a/source3/sam/idmap_rid.c b/source3/sam/idmap_rid.c index 0ba97946965..4a1ae141b10 100644 --- a/source3/sam/idmap_rid.c +++ b/source3/sam/idmap_rid.c @@ -142,6 +142,7 @@ static NTSTATUS rid_idmap_get_domains(uint32 *num_domains, fstring **domain_name { NTSTATUS status = NT_STATUS_UNSUCCESSFUL; struct cli_state *cli; + struct rpc_pipe_client *pipe_hnd; TALLOC_CTX *mem_ctx; POLICY_HND pol; uint32 des_access = SEC_RIGHTS_MAXIMUM_ALLOWED; @@ -233,18 +234,22 @@ static NTSTATUS rid_idmap_get_domains(uint32 *num_domains, fstring **domain_name } /* query the lsa-pipe */ - if (!cli_nt_session_open (cli, PI_LSARPC)) { + pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &status); + if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("rid_idmap_get_domains: could not setup connection to dc\n")); goto out; } /* query policies */ - status = cli_lsa_open_policy(cli, mem_ctx, False, des_access, &pol); + status = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, False, des_access, + &pol); if (!NT_STATUS_IS_OK(status)) { goto out; } - status = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class, &domain_name, &domain_sid); + status = rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx, &pol, + info_class, &domain_name, + &domain_sid); if (!NT_STATUS_IS_OK(status)) { DEBUG(1, ("rid_idmap_get_domains: cannot retrieve domain-info\n")); goto out; @@ -255,10 +260,10 @@ static NTSTATUS rid_idmap_get_domains(uint32 *num_domains, fstring **domain_name /* scan trusted domains */ DEBUG(10, ("rid_idmap_get_domains: enumerating trusted domains\n")); - status = cli_lsa_enum_trust_dom(cli, mem_ctx, &pol, &enum_ctx, - &trusted_num_domains, - &trusted_domain_names, - &trusted_domain_sids); + status = rpccli_lsa_enum_trust_dom(pipe_hnd, mem_ctx, &pol, &enum_ctx, + &trusted_num_domains, + &trusted_domain_names, + &trusted_domain_sids); if (!NT_STATUS_IS_OK(status) && !NT_STATUS_EQUAL(status, NT_STATUS_NO_MORE_ENTRIES) && @@ -315,8 +320,8 @@ static NTSTATUS rid_idmap_get_domains(uint32 *num_domains, fstring **domain_name status = NT_STATUS_OK; out: - cli_lsa_close(cli, mem_ctx, &pol); - cli_nt_session_close(cli); + rpccli_lsa_close(pipe_hnd, mem_ctx, &pol); + cli_rpc_pipe_close(pipe_hnd); talloc_destroy(mem_ctx); cli_shutdown(cli); diff --git a/source3/sam/idmap_smbldap.c b/source3/sam/idmap_smbldap.c new file mode 100644 index 00000000000..b1aae2b86f7 --- /dev/null +++ b/source3/sam/idmap_smbldap.c @@ -0,0 +1,453 @@ +/* + Unix SMB/CIFS implementation. + + idmap LDAP backend + + Copyright (C) Tim Potter 2000 + Copyright (C) Jim McDonough 2003 + Copyright (C) Simo Sorce 2003 + Copyright (C) Gerald Carter 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" + +#undef DBGC_CLASS +#define DBGC_CLASS DBGC_IDMAP + +struct ldap_connection *ldap_conn = NULL; + +/* number tries while allocating new id */ +#define LDAP_MAX_ALLOC_ID 128 + + +/*********************************************************************** + This function cannot be called to modify a mapping, only set a new one +***********************************************************************/ + +static NTSTATUS ldap_set_mapping(const DOM_SID *sid, unid_t id, int id_type) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + pstring id_str; + const char *type; + fstring sid_string; + struct ldap_message *msg; + struct ldap_message *mod_res = NULL; + char *mod; + + type = (id_type & ID_USERID) ? "uidNumber" : "gidNumber"; + + sid_to_string( sid_string, sid ); + + pstr_sprintf(id_str, "%lu", + ((id_type & ID_USERID) ? + (unsigned long)id.uid : (unsigned long)id.gid)); + + asprintf(&mod, + "dn: sambaSID=%s,%s\n" + "changetype: add\n" + "objectClass: sambaIdmapEntry\n" + "objectClass: sambaSidEntry\n" + "sambaSID: %s\n" + "%s: %lu\n", + sid_string, lp_ldap_idmap_suffix(), sid_string, type, + ((id_type & ID_USERID) ? + (unsigned long)id.uid : (unsigned long)id.gid)); + + msg = ldap_ldif2msg(mod); + + SAFE_FREE(mod); + + if (msg == NULL) + return NT_STATUS_NO_MEMORY; + + mod_res = ldap_transaction(ldap_conn, msg); + + if ((mod_res == NULL) || (mod_res->r.ModifyResponse.resultcode != 0)) + goto out; + + ret = NT_STATUS_OK; + out: + destroy_ldap_message(msg); + destroy_ldap_message(mod_res); + return ret; +} + +/***************************************************************************** + Allocate a new RID +*****************************************************************************/ + +static NTSTATUS ldap_allocate_rid(uint32 *rid, int rid_type) +{ + return NT_STATUS_UNSUCCESSFUL; +} + +/***************************************************************************** + Allocate a new uid or gid +*****************************************************************************/ + +static NTSTATUS ldap_allocate_id(unid_t *id, int id_type) +{ + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + uid_t luid, huid; + gid_t lgid, hgid; + const char *attrs[] = { "uidNumber", "gidNumber" }; + struct ldap_message *idpool_s = NULL; + struct ldap_message *idpool = NULL; + struct ldap_message *mod_msg = NULL; + struct ldap_message *mod_res = NULL; + int value; + const char *id_attrib; + char *mod; + + id_attrib = (id_type & ID_USERID) ? "uidNumber" : "gidNumber"; + + idpool_s = new_ldap_search_message(lp_ldap_suffix(), + LDAP_SEARCH_SCOPE_SUB, + "(objectclass=sambaUnixIdPool)", + 2, attrs); + + if (idpool_s == NULL) + return NT_STATUS_NO_MEMORY; + + idpool = ldap_searchone(ldap_conn, idpool_s, NULL); + + if (idpool == NULL) + goto out; + + if (!ldap_find_single_int(idpool, id_attrib, &value)) + goto out; + + /* this must succeed or else we wouldn't have initialized */ + + lp_idmap_uid( &luid, &huid); + lp_idmap_gid( &lgid, &hgid); + + /* make sure we still have room to grow */ + + if (id_type & ID_USERID) { + id->uid = value; + if (id->uid > huid ) { + DEBUG(0,("ldap_allocate_id: Cannot allocate uid " + "above %lu!\n", (unsigned long)huid)); + goto out; + } + } + else { + id->gid = value; + if (id->gid > hgid ) { + DEBUG(0,("ldap_allocate_id: Cannot allocate gid " + "above %lu!\n", (unsigned long)hgid)); + goto out; + } + } + + asprintf(&mod, + "dn: %s\n" + "changetype: modify\n" + "delete: %s\n" + "%s: %d\n" + "-\n" + "add: %s\n" + "%s: %d\n", + idpool->r.SearchResultEntry.dn, id_attrib, id_attrib, value, + id_attrib, id_attrib, value+1); + + mod_msg = ldap_ldif2msg(mod); + + SAFE_FREE(mod); + + if (mod_msg == NULL) + goto out; + + mod_res = ldap_transaction(ldap_conn, mod_msg); + + if ((mod_res == NULL) || (mod_res->r.ModifyResponse.resultcode != 0)) + goto out; + + ret = NT_STATUS_OK; +out: + destroy_ldap_message(idpool_s); + destroy_ldap_message(idpool); + destroy_ldap_message(mod_msg); + destroy_ldap_message(mod_res); + + return ret; +} + +/***************************************************************************** + get a sid from an id +*****************************************************************************/ + +static NTSTATUS ldap_get_sid_from_id(DOM_SID *sid, unid_t id, int id_type) +{ + pstring filter; + const char *type; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + const char *attr_list[] = { "sambaSID" }; + struct ldap_message *msg; + struct ldap_message *entry = NULL; + char *sid_str; + + type = (id_type & ID_USERID) ? "uidNumber" : "gidNumber"; + + pstr_sprintf(filter, "(&(objectClass=%s)(%s=%lu))", "sambaIdmapEntry", + type, + ((id_type & ID_USERID) ? + (unsigned long)id.uid : (unsigned long)id.gid)); + + msg = new_ldap_search_message(lp_ldap_idmap_suffix(), + LDAP_SEARCH_SCOPE_SUB, + filter, 1, attr_list); + + if (msg == NULL) + return NT_STATUS_NO_MEMORY; + + entry = ldap_searchone(ldap_conn, msg, NULL); + + if (entry == NULL) + goto out; + + if (!ldap_find_single_string(entry, "sambaSID", entry->mem_ctx, + &sid_str)) + goto out; + + if (!string_to_sid(sid, sid_str)) + goto out; + + ret = NT_STATUS_OK; +out: + destroy_ldap_message(msg); + destroy_ldap_message(entry); + + return ret; +} + +/*********************************************************************** + Get an id from a sid +***********************************************************************/ + +static NTSTATUS ldap_get_id_from_sid(unid_t *id, int *id_type, + const DOM_SID *sid) +{ + pstring filter; + const char *type; + NTSTATUS ret = NT_STATUS_UNSUCCESSFUL; + struct ldap_message *msg; + struct ldap_message *entry = NULL; + int i; + + DEBUG(8,("ldap_get_id_from_sid: %s (%s)\n", sid_string_static(sid), + (*id_type & ID_GROUPID ? "group" : "user") )); + + type = ((*id_type) & ID_USERID) ? "uidNumber" : "gidNumber"; + + pstr_sprintf(filter, "(&(objectClass=%s)(%s=%s))", + "sambaIdmapEntry", "sambaSID", sid_string_static(sid)); + + msg = new_ldap_search_message(lp_ldap_idmap_suffix(), + LDAP_SEARCH_SCOPE_SUB, + filter, 1, &type); + + if (msg == NULL) + return NT_STATUS_NO_MEMORY; + + entry = ldap_searchone(ldap_conn, msg, NULL); + + if (entry != NULL) { + int value; + + if (!ldap_find_single_int(entry, type, &value)) + goto out; + + if ((*id_type) & ID_USERID) + id->uid = value; + else + id->gid = value; + + ret = NT_STATUS_OK; + goto out; + } + + if ((*id_type) & ID_QUERY_ONLY) + goto out; + + /* Allocate a new RID */ + + for (i = 0; i < LDAP_MAX_ALLOC_ID; i++) { + ret = ldap_allocate_id(id, *id_type); + if ( NT_STATUS_IS_OK(ret) ) + break; + } + + if ( !NT_STATUS_IS_OK(ret) ) { + DEBUG(0,("Could not allocate id\n")); + goto out; + } + + DEBUG(10,("ldap_get_id_from_sid: Allocated new %cid [%ul]\n", + (*id_type & ID_GROUPID ? 'g' : 'u'), (uint32)id->uid )); + + ret = ldap_set_mapping(sid, *id, *id_type); + +out: + destroy_ldap_message(msg); + destroy_ldap_message(entry); + + return ret; +} + +/********************************************************************** + Verify the sambaUnixIdPool entry in the directory. +**********************************************************************/ +static NTSTATUS verify_idpool(void) +{ + const char *attr_list[3] = { "uidnumber", "gidnumber", "objectclass" }; + BOOL result; + char *mod; + struct ldap_message *msg, *entry, *res; + + uid_t luid, huid; + gid_t lgid, hgid; + + msg = new_ldap_search_message(lp_ldap_suffix(), + LDAP_SEARCH_SCOPE_SUB, + "(objectClass=sambaUnixIdPool)", + 3, attr_list); + + if (msg == NULL) + return NT_STATUS_NO_MEMORY; + + entry = ldap_searchone(ldap_conn, msg, NULL); + + result = (entry != NULL); + + destroy_ldap_message(msg); + destroy_ldap_message(entry); + + if (result) + return NT_STATUS_OK; + + if ( !lp_idmap_uid(&luid, &huid) || !lp_idmap_gid( &lgid, &hgid ) ) { + DEBUG(3,("ldap_idmap_init: idmap uid/gid parameters not " + "specified\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + asprintf(&mod, + "dn: %s\n" + "changetype: modify\n" + "add: objectClass\n" + "objectClass: sambaUnixIdPool\n" + "-\n" + "add: uidNumber\n" + "uidNumber: %lu\n" + "-\n" + "add: gidNumber\n" + "gidNumber: %lu\n", + lp_ldap_idmap_suffix(), + (unsigned long)luid, (unsigned long)lgid); + + msg = ldap_ldif2msg(mod); + + SAFE_FREE(mod); + + if (msg == NULL) + return NT_STATUS_NO_MEMORY; + + res = ldap_transaction(ldap_conn, msg); + + if ((res == NULL) || (res->r.ModifyResponse.resultcode != 0)) { + destroy_ldap_message(msg); + destroy_ldap_message(res); + DEBUG(5, ("Could not add sambaUnixIdPool\n")); + return NT_STATUS_UNSUCCESSFUL; + } + + destroy_ldap_message(msg); + destroy_ldap_message(res); + return NT_STATUS_OK; +} + +/***************************************************************************** + Initialise idmap database. +*****************************************************************************/ + +static NTSTATUS ldap_idmap_init( char *params ) +{ + NTSTATUS nt_status; + char *dn, *pw; + + ldap_conn = new_ldap_connection(); + + if (!fetch_ldap_pw(&dn, &pw)) + return NT_STATUS_UNSUCCESSFUL; + + ldap_conn->auth_dn = talloc_strdup(ldap_conn->mem_ctx, dn); + ldap_conn->simple_pw = talloc_strdup(ldap_conn->mem_ctx, pw); + + SAFE_FREE(dn); + SAFE_FREE(pw); + + if (!ldap_setup_connection(ldap_conn, params, NULL, NULL)) + return NT_STATUS_UNSUCCESSFUL; + + /* see if the idmap suffix and sub entries exists */ + + nt_status = verify_idpool(); + if ( !NT_STATUS_IS_OK(nt_status) ) + return nt_status; + + return NT_STATUS_OK; +} + +/***************************************************************************** + End the LDAP session +*****************************************************************************/ + +static NTSTATUS ldap_idmap_close(void) +{ + + DEBUG(5,("The connection to the LDAP server was closed\n")); + /* maybe free the results here --metze */ + + return NT_STATUS_OK; +} + + +/* This function doesn't make as much sense in an LDAP world since the calling + node doesn't really control the ID ranges */ +static void ldap_idmap_status(void) +{ + DEBUG(0, ("LDAP IDMAP Status not available\n")); +} + +static struct idmap_methods ldap_methods = { + ldap_idmap_init, + ldap_allocate_rid, + ldap_allocate_id, + ldap_get_sid_from_id, + ldap_get_id_from_sid, + ldap_set_mapping, + ldap_idmap_close, + ldap_idmap_status + +}; + +NTSTATUS idmap_smbldap_init(void) +{ + return smb_register_idmap(SMB_IDMAP_INTERFACE_VERSION, "smbldap", &ldap_methods); +} diff --git a/source3/script/installman.sh b/source3/script/installman.sh index 9cd91008392..5564ac02318 100755 --- a/source3/script/installman.sh +++ b/source3/script/installman.sh @@ -13,7 +13,7 @@ if [ $# -ge 4 ] ; then GROFF=$4 # sh cmd line, including options fi -if test ! -d ../docs/manpages; then +if test ! -d docs/manpages; then echo "No manpages present. SVN development version maybe?" exit 0 fi diff --git a/source3/script/installswat.sh b/source3/script/installswat.sh index 2b99b9c57f1..cba3a294f87 100755 --- a/source3/script/installswat.sh +++ b/source3/script/installswat.sh @@ -3,7 +3,7 @@ SWATDIR=`echo $1 | sed 's/\/\//\//g'` SRCDIR=$2/ -BOOKDIR=$SWATDIR/help/using_samba +BOOKDIR=$SWATDIR/using_samba echo Installing SWAT in $SWATDIR echo Installing the Samba Web Administration Tool @@ -14,7 +14,7 @@ echo Installing langs are `cd $SRCDIR../swat/lang/; /bin/echo ??` for ln in $LANGS; do SWATLANGDIR=$SWATDIR/$ln for d in $SWATLANGDIR $SWATLANGDIR/help $SWATLANGDIR/images \ - $SWATLANGDIR/include; do + $SWATLANGDIR/include $SWATLANGDIR/js; do if [ ! -d $d ]; then mkdir -p $d if [ ! -d $d ]; then @@ -28,7 +28,7 @@ done # Install images for ln in $LANGS; do - for f in $SRCDIR../swat/$ln/images/*.gif; do + for f in $SRCDIR../swat/$ln/images/*.png; do if [ ! -f $f ] ; then continue fi @@ -59,7 +59,7 @@ for ln in $LANGS; do # Install "server-side" includes - for f in $SRCDIR../swat/$ln/include/*.html; do + for f in $SRCDIR../swat/$ln/include/*; do if [ ! -f $f ] ; then continue fi @@ -69,13 +69,25 @@ for ln in $LANGS; do chmod 0644 $FNAME done + # Install javascripts + + for f in $SRCDIR../swat/$ln/js/*.js; do + if [ ! -f $f ] ; then + continue + fi + FNAME=$SWATDIR/$ln/js/`basename $f` + echo $FNAME + cp $f $FNAME || echo Cannot install $FNAME. Does $USER have privileges? + chmod 0644 $FNAME + done + done # Install html documentation (if html documentation tree is here) if [ -d $SRCDIR../docs/htmldocs/ ]; then - for dir in htmldocs/manpages htmldocs/Samba3-ByExample htmldocs/Samba3-Developers-Guide htmldocs/Samba3-HOWTO + for dir in htmldocs/ htmldocs/Samba-HOWTO-Collection htmldocs/Samba-Guide htmldocs/Samba-Developers-Guide do if [ ! -d $SRCDIR../docs/$dir ]; then diff --git a/source3/script/mkproto.awk b/source3/script/mkproto.awk index 3940c34700a..73a1c2b3f0a 100644 --- a/source3/script/mkproto.awk +++ b/source3/script/mkproto.awk @@ -128,7 +128,7 @@ END { gotstart = 1; } - if( $0 ~ /^SAM_ACCT_INFO_NODE|^SMB_ACL_T|^ADS_MODLIST|^PyObject|^SORTED_TREE|^REGISTRY_HOOK|^REGISTRY_VALUE|^DEVICEMODE|^PAC_DATA|^NET_USER_INFO_3|^smb_event_id_t/ ) { + if( $0 ~ /^SAM_ACCT_INFO_NODE|^SMB_ACL_T|^ADS_MODLIST|^PyObject|^SORTED_TREE|^REGISTRY_HOOK|^REGISTRY_VALUE|^REGVAL_CTR|^DEVICEMODE|^PAC_DATA|^NET_USER_INFO_3|^smb_event_id_t/ ) { gotstart = 1; } diff --git a/source3/script/tests/functions b/source3/script/tests/functions index 0981d9e29e1..40e185e153f 100644 --- a/source3/script/tests/functions +++ b/source3/script/tests/functions @@ -2,16 +2,13 @@ ## library file for test functions ## - -SMBCONTROL="smbcontrol -t 3" - ## ## start/stop smbd daemon ## check_smbd_running() { ## the smbcontrol ping will return a 0 on success - $SMBCONTROL $CONFIGURATION smbd ping 2>&1 > /dev/null + smbcontrol $CONFIGURATION smbd ping 2>&1 > /dev/null } start_smbd() @@ -22,7 +19,7 @@ start_smbd() sleep 1 - $SMBCONTROL $CONFIGURATION `cat $PIDDIR/smbd.pid` ping 2>&1 > /dev/null || return $? + smbcontrol $CONFIGURATION `cat $PIDDIR/smbd.pid` ping 2>&1 > /dev/null || return $? } stop_smbd() @@ -33,7 +30,7 @@ stop_smbd() ## belt and braces; first kill and then send a shutdown message kill -TERM $smbd_pid - $SMBCONTROL $CONFIGURATION smbd shutdown + smbcontrol $CONFIGURATION smbd shutdown ## check to see if smbd is already running check_smbd_running @@ -43,23 +40,14 @@ stop_smbd() fi } -check_ret_value() -{ - ret=$@ - - if test $ret != 0; then - stop_smbd - exit $ret - fi -} ## -## start/stop nmbd daemon +## start/stop smbd daemon ## check_nmbd_running() { ## the smbcontrol ping will return a 0 on success - $SMBCONTROL $CONFIGURATION nmbd ping 2>&1 > /dev/null + smbcontrol $CONFIGURATION nmbd ping 2>&1 > /dev/null } start_nmbd() diff --git a/source3/script/tests/t_001.sh b/source3/script/tests/t_001.sh index 7db2abe226e..6d54d0e4895 100644 --- a/source3/script/tests/t_001.sh +++ b/source3/script/tests/t_001.sh @@ -22,27 +22,9 @@ chmod 1777 $PREFIX_ABS/tmp start_smbd || exit $? -## share enumeration - smbclient $CONFIGURATION -L localhost -N -p 139 -check_ret_value $? - -testfile=`echo $CONFIGURATION | awk '{print $2}'` -filename=`basename $testfile` -dirname=`dirname $testfile` - - -# file get/put - -smbclient //localhost/test $PASSWORD $CONFIGURATION -c "lcd $dirname; put $filename" -check_ret_value $? - -smbclient //localhost/test $PASSWORD $CONFIGURATION -c "get $filename; rm $filename" -check_ret_value $? - -diff $filename $testfile 2> /dev/null > /dev/null -check_ret_value $? +ret=$? stop_smbd -exit 0 +exit $ret diff --git a/source3/services/services_db.c b/source3/services/services_db.c index 29c5a9f6e69..b59cd5330e5 100644 --- a/source3/services/services_db.c +++ b/source3/services/services_db.c @@ -1,8 +1,10 @@ /* * Unix SMB/CIFS implementation. * Service Control API Implementation - * Copyright (C) Gerald Carter 2005. + * * Copyright (C) Marcin Krzysztof Porwit 2005. + * Largely Rewritten by: + * Copyright (C) Gerald (Jerry) Carter 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 @@ -21,544 +23,431 @@ #include "includes.h" -#if 0 - -/* backend database routines for services.tdb */ - -#define SERVICEDB_VERSION_V1 1 /* Will there be more? */ -#define INTERNAL_SERVICES_LIST "NETLOGON Spooler" - -/* */ -/* scripts will execute from the following libdir, if they are in the enable svcctl= */ -/* these should likely be symbolic links. Note that information about them will be extracted from the files themselves */ -/* using the LSB standard keynames for various information */ - -#define SCVCTL_DATABASE_VERSION_V1 1 -static TDB_CONTEXT *service_tdb; /* used for services tdb file */ - -/* there are two types of services -- internal, and external. - Internal services are "built-in" to samba -- there may be - functions that exist to provide the control and enumeration - functions. There certainly is information returned to be - displayed in the typical management console. - - External services are those that can be specified in the smb.conf - file -- and they conform to the LSB specification as to having - particular keywords in the scripts. Note that these "scripts" are - located in the lib directory, and are likely links to LSB-compliant - init.d scripts, such as those that might come with Suse. Note - that the spec is located http://www.linuxbase.org/spec/ */ - - - -/* Expand this to include what can and can't be done - with a particular internal service. Expand as necessary - to add other infromation like what can be controlled, - etc. */ +/******************************************************************** +********************************************************************/ -typedef struct Internal_service_struct +static SEC_DESC* construct_service_sd( TALLOC_CTX *ctx ) { - const char *filename; /* internal name "index" */ - const char *displayname; - const char *description; - const uint32 statustype; - void *status_fn; - void *control_fn; -} Internal_service_description; - + SEC_ACE ace[4]; + SEC_ACCESS mask; + size_t i = 0; + SEC_DESC *sd; + SEC_ACL *acl; + size_t sd_size; + + /* basic access for Everyone */ + + init_sec_access(&mask, SERVICE_READ_ACCESS ); + init_sec_ace(&ace[i++], &global_sid_World, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + init_sec_access(&mask,SERVICE_EXECUTE_ACCESS ); + init_sec_ace(&ace[i++], &global_sid_Builtin_Power_Users, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + init_sec_access(&mask,SERVICE_ALL_ACCESS ); + init_sec_ace(&ace[i++], &global_sid_Builtin_Server_Operators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + init_sec_ace(&ace[i++], &global_sid_Builtin_Administrators, SEC_ACE_TYPE_ACCESS_ALLOWED, mask, 0); + + /* create the security descriptor */ + + if ( !(acl = make_sec_acl(ctx, NT4_ACL_REVISION, i, ace)) ) + return NULL; -static const Internal_service_description ISD[] = { - { "NETLOGON", "Net Logon", "Provides logon and authentication service to the network", 0x110, NULL, NULL}, - { "Spooler", "Spooler", "Printing Services", 0x0020, NULL, NULL}, - { NULL, NULL, NULL, 0, NULL, NULL} -}; + if ( !(sd = make_sec_desc(ctx, SEC_DESC_REVISION, SEC_DESC_SELF_RELATIVE, NULL, NULL, NULL, acl, &sd_size)) ) + return NULL; + return sd; +} /******************************************************************** - allocate an array of external services and return them. Null return - is okay, make sure &added is also zero! + This is where we do the dirty work of filling in things like the + Display name, Description, etc... ********************************************************************/ -int num_external_services(void) +static void fill_service_values( const char *name, REGVAL_CTR *values ) { - int num_services; - char **svc_list; - pstring keystring, external_services_string; - TDB_DATA key_data; - - - if (!service_tdb) { - DEBUG(8,("enum_external_services: service database is not open!!!\n")); - num_services = 0; - } else { - pstrcpy(keystring,"EXTERNAL_SERVICES"); - key_data = tdb_fetch_bystring(service_tdb, keystring); - - if ((key_data.dptr != NULL) && (key_data.dsize != 0)) { - strncpy(external_services_string,key_data.dptr,key_data.dsize); - external_services_string[key_data.dsize] = 0; - DEBUG(8,("enum_external_services: services list is %s, size is %d\n",external_services_string,key_data.dsize)); - } - } - svc_list = str_list_make(external_services_string,NULL); - - num_services = str_list_count( (const char **)svc_list); + UNISTR2 data, dname, ipath, description; + uint32 dword; + pstring pstr; + + /* These values are hardcoded in all QueryServiceConfig() replies. + I'm just storing them here for cosmetic purposes */ + + dword = SVCCTL_AUTO_START; + regval_ctr_addvalue( values, "Start", REG_DWORD, (char*)&dword, sizeof(uint32)); + + dword = SVCCTL_WIN32_OWN_PROC; + regval_ctr_addvalue( values, "Type", REG_DWORD, (char*)&dword, sizeof(uint32)); - return num_services; + dword = SVCCTL_SVC_ERROR_NORMAL; + regval_ctr_addvalue( values, "ErrorControl", REG_DWORD, (char*)&dword, sizeof(uint32)); + + /* everything runs as LocalSystem */ + + init_unistr2( &data, "LocalSystem", UNI_STR_TERMINATE ); + regval_ctr_addvalue( values, "ObjectName", REG_SZ, (char*)data.buffer, data.uni_str_len*2); + + /* special considerations for internal services and the DisplayName value */ + + if ( strequal(name, "Spooler") ) { + pstr_sprintf( pstr, "%s/%s/smbd",dyn_LIBDIR, SVCCTL_SCRIPT_DIR ); + init_unistr2( &ipath, pstr, UNI_STR_TERMINATE ); + init_unistr2( &description, "Internal service for spooling files to print devices", UNI_STR_TERMINATE ); + init_unistr2( &dname, "Print Spooler", UNI_STR_TERMINATE ); + } + else if ( strequal(name, "NETLOGON") ) { + pstr_sprintf( pstr, "%s/%s/smbd",dyn_LIBDIR, SVCCTL_SCRIPT_DIR ); + init_unistr2( &ipath, pstr, UNI_STR_TERMINATE ); + init_unistr2( &description, "File service providing access to policy and profile data", UNI_STR_TERMINATE ); + init_unistr2( &dname, "Net Logon", UNI_STR_TERMINATE ); + } + else if ( strequal(name, "RemoteRegistry") ) { + pstr_sprintf( pstr, "%s/%s/smbd",dyn_LIBDIR, SVCCTL_SCRIPT_DIR ); + init_unistr2( &ipath, pstr, UNI_STR_TERMINATE ); + init_unistr2( &description, "Internal service providing remote access to the Samba registry", UNI_STR_TERMINATE ); + init_unistr2( &dname, "Remote Registry Service", UNI_STR_TERMINATE ); + } + else { + pstr_sprintf( pstr, "%s/%s/%s",dyn_LIBDIR, SVCCTL_SCRIPT_DIR, name ); + init_unistr2( &ipath, pstr, UNI_STR_TERMINATE ); + init_unistr2( &description, "External Unix Service", UNI_STR_TERMINATE ); + init_unistr2( &dname, name, UNI_STR_TERMINATE ); + } + regval_ctr_addvalue( values, "DisplayName", REG_SZ, (char*)dname.buffer, dname.uni_str_len*2); + regval_ctr_addvalue( values, "ImagePath", REG_SZ, (char*)ipath.buffer, ipath.uni_str_len*2); + regval_ctr_addvalue( values, "Description", REG_SZ, (char*)description.buffer, description.uni_str_len*2); + + return; } - - /******************************************************************** - Gather information on the "external services". These are services - listed in the smb.conf file, and found to exist through checks in - this code. Note that added will be incremented on the basis of the - number of services added. svc_ptr should have enough memory allocated - to accommodate all of the services that exist. - - Typically num_external_services is used to "size" the amount of - memory allocated, but does little/no work. - - enum_external_services() actually examines each of the specified - external services, populates the memory structures, and returns. - - ** note that 'added' may end up with less than the number of services - found in _num_external_services, such as the case when a service is - called out, but the actual service doesn't exist or the file can't be - read for the service information. ********************************************************************/ -WERROR enum_external_services(TALLOC_CTX *tcx,ENUM_SERVICES_STATUS **svc_ptr, int existing_services,int *added) +static void add_new_svc_name( REGISTRY_KEY *key_parent, REGSUBKEY_CTR *subkeys, + const char *name ) { - /* *svc_ptr must have pre-allocated memory */ - int num_services = 0; - int i = 0; - ENUM_SERVICES_STATUS *services=NULL; - char **svc_list,**svcname; - pstring command, keystring, external_services_string; - int ret; - int fd = -1; - Service_info *si; - TDB_DATA key_data; - - *added = num_services; - - if (!service_tdb) { - DEBUG(8,("enum_external_services: service database is not open!!!\n")); - } else { - pstrcpy(keystring,"EXTERNAL_SERVICES"); - key_data = tdb_fetch_bystring(service_tdb, keystring); - if ((key_data.dptr != NULL) && (key_data.dsize != 0)) { - strncpy(external_services_string,key_data.dptr,key_data.dsize); - external_services_string[key_data.dsize] = 0; - DEBUG(8,("enum_external_services: services list is %s, size is %d\n",external_services_string,key_data.dsize)); - } - } - svc_list = str_list_make(external_services_string,NULL); - - num_services = str_list_count( (const char **)svc_list); - - if (0 == num_services) { - DEBUG(8,("enum_external_services: there are no external services\n")); - *added = num_services; - return WERR_OK; + REGISTRY_KEY *key_service, *key_secdesc; + WERROR wresult; + pstring path; + REGVAL_CTR *values; + REGSUBKEY_CTR *svc_subkeys; + SEC_DESC *sd; + prs_struct ps; + + /* add to the list and create the subkey path */ + + regsubkey_ctr_addkey( subkeys, name ); + store_reg_keys( key_parent, subkeys ); + + /* open the new service key */ + + pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name ); + wresult = regkey_open_internal( &key_service, path, get_root_nt_token(), + REG_KEY_ALL ); + if ( !W_ERROR_IS_OK(wresult) ) { + DEBUG(0,("add_new_svc_name: key lookup failed! [%s] (%s)\n", + path, dos_errstr(wresult))); + return; } - DEBUG(8,("enum_external_services: there are [%d] external services\n",num_services)); - si=TALLOC_ARRAY( tcx, Service_info, 1 ); - if (si == NULL) { - DEBUG(8,("enum_external_services: Failed to alloc si\n")); - return WERR_NOMEM; + + /* add the 'Security' key */ + + if ( !(svc_subkeys = TALLOC_ZERO_P( key_service, REGSUBKEY_CTR )) ) { + DEBUG(0,("add_new_svc_name: talloc() failed!\n")); + return; } + + fetch_reg_keys( key_service, svc_subkeys ); + regsubkey_ctr_addkey( svc_subkeys, "Security" ); + store_reg_keys( key_service, svc_subkeys ); -#if 0 -/* *svc_ptr has the pointer to the array if there is one already. NULL if not. */ - if ((existing_services>0) && svc_ptr && *svc_ptr) { /* reallocate vs. allocate */ - DEBUG(8,("enum_external_services: REALLOCing %x to %d services\n", *svc_ptr, existing_services+num_services)); + /* now for the service values */ + + if ( !(values = TALLOC_ZERO_P( key_service, REGVAL_CTR )) ) { + DEBUG(0,("add_new_svc_name: talloc() failed!\n")); + return; + } - services=TALLOC_REALLOC_ARRAY(tcx,*svc_ptr,ENUM_SERVICES_STATUS,existing_services+num_services); - DEBUG(8,("enum_external_services: REALLOCed to %x services\n", services)); + fill_service_values( name, values ); + store_reg_values( key_service, values ); - if (!services) return WERR_NOMEM; - *svc_ptr = services; - } else { - if ( !(services = TALLOC_ARRAY( tcx, ENUM_SERVICES_STATUS, num_services )) ) - return WERR_NOMEM; - } -#endif + /* cleanup the service key*/ + + TALLOC_FREE( key_service ); + + /* now add the security descriptor */ - if (!svc_ptr || !(*svc_ptr)) - return WERR_NOMEM; - services = *svc_ptr; - if (existing_services > 0) { - i+=existing_services; + pstr_sprintf( path, "%s\\%s\\%s", KEY_SERVICES, name, "Security" ); + wresult = regkey_open_internal( &key_secdesc, path, get_root_nt_token(), + REG_KEY_ALL ); + if ( !W_ERROR_IS_OK(wresult) ) { + DEBUG(0,("add_new_svc_name: key lookup failed! [%s] (%s)\n", + path, dos_errstr(wresult))); + return; } - svcname = svc_list; - DEBUG(8,("enum_external_services: enumerating %d external services starting at index %d\n", num_services,existing_services)); - - while (*svcname) { - DEBUG(10,("enum_external_services: Reading information on service %s, index %d\n",*svcname,i)); - /* get_LSB_data(*svcname,si); */ - if (!get_service_info(service_tdb,*svcname, si)) { - DEBUG(1,("enum_external_services: CAN'T FIND INFO FOR SERVICE %s in the services DB\n",*svcname)); - } - - if ((si->filename == NULL) || (*si->filename == 0)) { - init_unistr(&services[i].servicename, *svcname ); - } else { - init_unistr( &services[i].servicename, si->filename ); - /* init_unistr( &services[i].servicename, si->servicename ); */ - } - - if ((si->provides == NULL) || (*si->provides == 0)) { - init_unistr(&services[i].displayname, *svcname ); - } else { - init_unistr( &services[i].displayname, si->provides ); - } - - /* TODO - we could keep the following info in the DB, too... */ - - DEBUG(8,("enum_external_services: Service name [%s] displayname [%s]\n", - si->filename, si->provides)); - services[i].status.type = SVCCTL_WIN32_OWN_PROC; - services[i].status.win32_exit_code = 0x0; - services[i].status.service_exit_code = 0x0; - services[i].status.check_point = 0x0; - services[i].status.wait_hint = 0x0; - - /* TODO - do callout here to get the status */ - - memset(command, 0, sizeof(command)); - slprintf(command, sizeof(command)-1, "%s%s%s %s", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, *svcname, "status"); - - DEBUG(10, ("enum_external_services: status command is [%s]\n", command)); - - /* TODO - wrap in privilege check */ - - ret = smbrun(command, &fd); - DEBUGADD(10, ("returned [%d]\n", ret)); - close(fd); - if(ret != 0) - DEBUG(10, ("enum_external_services: Command returned [%d]\n", ret)); - services[i].status.state = SVCCTL_STOPPED; - if (ret == 0) { - services[i].status.state = SVCCTL_RUNNING; - services[i].status.controls_accepted = SVCCTL_CONTROL_SHUTDOWN | SVCCTL_CONTROL_STOP; - } else { - services[i].status.state = SVCCTL_STOPPED; - services[i].status.controls_accepted = 0; - } - svcname++; - i++; - } + if ( !(values = TALLOC_ZERO_P( key_secdesc, REGVAL_CTR )) ) { + DEBUG(0,("add_new_svc_name: talloc() failed!\n")); + return; + } - DEBUG(10,("enum_external_services: Read services %d\n",num_services)); - *added = num_services; + if ( !(sd = construct_service_sd(key_secdesc)) ) { + DEBUG(0,("add_new_svc_name: Failed to create default sec_desc!\n")); + TALLOC_FREE( key_secdesc ); + return; + } + + /* stream the printer security descriptor */ + + prs_init( &ps, RPC_MAX_PDU_FRAG_LEN, key_secdesc, MARSHALL); + + if ( sec_io_desc("sec_desc", &sd, &ps, 0 ) ) { + uint32 offset = prs_offset( &ps ); + regval_ctr_addvalue( values, "Security", REG_BINARY, prs_data_p(&ps), offset ); + store_reg_values( key_secdesc, values ); + } + + /* finally cleanup the Security key */ + + prs_mem_free( &ps ); + TALLOC_FREE( key_secdesc ); - return WERR_OK; + return; } /******************************************************************** ********************************************************************/ -int num_internal_services(void) +void svcctl_init_keys( void ) { - int num_services; - char **svc_list; - pstring keystring, internal_services_string; - TDB_DATA key_data; - - if (!service_tdb) { - DEBUG(8,("enum_internal_services: service database is not open!!!\n")); - num_services = 0; - } else { - pstrcpy(keystring,"INTERNAL_SERVICES"); - key_data = tdb_fetch_bystring(service_tdb, keystring); - - if ((key_data.dptr != NULL) && (key_data.dsize != 0)) { - strncpy(internal_services_string,key_data.dptr,key_data.dsize); - internal_services_string[key_data.dsize] = 0; - DEBUG(8,("enum_internal_services: services list is %s, size is %d\n",internal_services_string,key_data.dsize)); - } - } - svc_list = str_list_make(internal_services_string,NULL); - - num_services = str_list_count( (const char **)svc_list); - - return num_services; -} - -#if 0 -/********************************************************************* - given a service nice name, find the underlying service name -*********************************************************************/ - -static BOOL convert_service_displayname(TDB_CONTEXT *stdb,pstring service_nicename, pstring servicename,int szsvcname) -{ - pstring keystring; - TDB_DATA key_data; - - if ((stdb == NULL) || (service_nicename==NULL) || (servicename == NULL)) - return False; + const char **service_list = lp_svcctl_list(); + int i; + REGSUBKEY_CTR *subkeys; + REGISTRY_KEY *key = NULL; + WERROR wresult; + BOOL new_services = False; + + /* bad mojo here if the lookup failed. Should not happen */ + + wresult = regkey_open_internal( &key, KEY_SERVICES, get_root_nt_token(), + REG_KEY_ALL ); - pstr_sprintf(keystring,"SERVICE_NICENAME/%s", servicename); + if ( !W_ERROR_IS_OK(wresult) ) { + DEBUG(0,("init_services_keys: key lookup failed! (%s)\n", + dos_errstr(wresult))); + return; + } + + /* lookup the available subkeys */ + + if ( !(subkeys = TALLOC_ZERO_P( key, REGSUBKEY_CTR )) ) { + DEBUG(0,("init_services_keys: talloc() failed!\n")); + return; + } + + fetch_reg_keys( key, subkeys ); + + /* the builting services exist */ + + add_new_svc_name( key, subkeys, "Spooler" ); + add_new_svc_name( key, subkeys, "NETLOGON" ); + add_new_svc_name( key, subkeys, "RemoteRegistry" ); + + for ( i=0; service_list[i]; i++ ) { + + /* only add new services */ + if ( regsubkey_ctr_key_exists( subkeys, service_list[i] ) ) + continue; - DEBUG(5, ("convert_service_displayname: Looking for service name [%s], key [%s]\n", - service_nicename, keystring)); + /* Add the new service key and initialize the appropriate values */ - key_data = tdb_fetch_bystring(stdb,keystring); + add_new_svc_name( key, subkeys, service_list[i] ); - if (key_data.dsize == 0) { - DEBUG(5, ("convert_service_displayname: [%s] Not found, tried key [%s]\n",service_nicename,keystring)); - return False; + new_services = True; } - strncpy(servicename,key_data.dptr,szsvcname); - servicename[(key_data.dsize > szsvcname ? szsvcname : key_data.dsize)] = 0; - DEBUG(5, ("convert_service_displayname: Found service name [%s], name is [%s]\n", - service_nicename,servicename)); + TALLOC_FREE( key ); - return True; -} -#endif + /* initialize the control hooks */ -/******************************************************************************* - Get the INTERNAL services information for the given service name. -*******************************************************************************/ + init_service_op_table(); -static BOOL get_internal_service_data(const Internal_service_description *isd, Service_info *si) -{ - ZERO_STRUCTP( si ); -#if 0 - - pstrcpy( si->servicename, isd->displayname); - pstrcpy( si->servicetype, "INTERNAL"); - pstrcpy( si->filename, isd->filename); - pstrcpy( si->provides, isd->displayname); - pstrcpy( si->description, isd->description); - pstrcpy( si->shortdescription, isd->description); -#endif - - return True; + return; } /******************************************************************** + This is where we do the dirty work of filling in things like the + Display name, Description, etc...Always return a default secdesc + in case of any failure. ********************************************************************/ -BOOL get_service_info(TDB_CONTEXT *stdb,char *service_name, Service_info *si) -{ - - pstring keystring; - TDB_DATA key_data; - - if ((stdb == NULL) || (si == NULL) || (service_name==NULL) || (*service_name == 0)) - return False; - - /* TODO - error handling -- what if the service isn't in the DB? */ - - pstr_sprintf(keystring,"SERVICE/%s/TYPE", service_name); - key_data = tdb_fetch_bystring(stdb,keystring); - strncpy(si->servicetype,key_data.dptr,key_data.dsize); - si->servicetype[key_data.dsize] = 0; - - /* crude check to see if the service exists... */ - DEBUG(3,("Size of the TYPE field is %d\n",key_data.dsize)); - if (key_data.dsize == 0) - return False; - - pstr_sprintf(keystring,"SERVICE/%s/FILENAME", service_name); - key_data = tdb_fetch_bystring(stdb,keystring); - strncpy(si->filename,key_data.dptr,key_data.dsize); - si->filename[key_data.dsize] = 0; - - pstr_sprintf(keystring,"SERVICE/%s/PROVIDES", service_name); - key_data = tdb_fetch_bystring(stdb,keystring); - strncpy(si->provides,key_data.dptr,key_data.dsize); - si->provides[key_data.dsize] = 0; - strncpy(si->servicename,key_data.dptr,key_data.dsize); - si->servicename[key_data.dsize] = 0; - - - pstr_sprintf(keystring,"SERVICE/%s/DEPENDENCIES", service_name); - key_data = tdb_fetch_bystring(stdb,keystring); - strncpy(si->dependencies,key_data.dptr,key_data.dsize); - si->dependencies[key_data.dsize] = 0; - - pstr_sprintf(keystring,"SERVICE/%s/SHOULDSTART", service_name); - key_data = tdb_fetch_bystring(stdb,keystring); - strncpy(si->shouldstart,key_data.dptr,key_data.dsize); - si->shouldstart[key_data.dsize] = 0; - - pstr_sprintf(keystring,"SERVICE/%s/SHOULD_STOP", service_name); - key_data = tdb_fetch_bystring(stdb,keystring); - strncpy(si->shouldstop,key_data.dptr,key_data.dsize); - si->shouldstop[key_data.dsize] = 0; - - pstr_sprintf(keystring,"SERVICE/%s/REQUIREDSTART", service_name); - key_data = tdb_fetch_bystring(stdb,keystring); - strncpy(si->requiredstart,key_data.dptr,key_data.dsize); - si->requiredstart[key_data.dsize] = 0; - - pstr_sprintf(keystring,"SERVICE/%s/REQUIREDSTOP", service_name); - key_data = tdb_fetch_bystring(stdb,keystring); - strncpy(si->requiredstop,key_data.dptr,key_data.dsize); - si->requiredstop[key_data.dsize] = 0; - - pstr_sprintf(keystring,"SERVICE/%s/DESCRIPTION", service_name); - key_data = tdb_fetch_bystring(stdb,keystring); - strncpy(si->description,key_data.dptr,key_data.dsize); - si->description[key_data.dsize] = 0; - - pstr_sprintf(keystring,"SERVICE/%s/SHORTDESC", service_name); - key_data = tdb_fetch_bystring(stdb,keystring); - strncpy(si->shortdescription,key_data.dptr,key_data.dsize); - si->shortdescription[key_data.dsize] = 0; - - return True; -} - -/********************************************************************* -*********************************************************************/ - -BOOL store_service_info(TDB_CONTEXT *stdb,char *service_name, Service_info *si) +SEC_DESC* svcctl_get_secdesc( TALLOC_CTX *ctx, const char *name, NT_USER_TOKEN *token ) { - pstring keystring; - - /* Note -- when we write to the tdb, we "index" on the filename - field, not the nice name. when a service is "opened", it is - opened by the nice (SERVICENAME) name, not the file name. - So there needs to be a mapping from nice name back to the file name. */ - - if ((stdb == NULL) || (si == NULL) || (service_name==NULL) || (*service_name == 0)) - return False; - - - /* Store the nicename */ - - pstr_sprintf(keystring,"SERVICE_NICENAME/%s", si->servicename); - tdb_store_bystring(stdb,keystring,string_tdb_data(service_name),TDB_REPLACE); - - pstr_sprintf(keystring,"SERVICE/%s/TYPE", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->servicetype),TDB_REPLACE); - - pstr_sprintf(keystring,"SERVICE/%s/FILENAME", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->filename),TDB_REPLACE); - - pstr_sprintf(keystring,"SERVICE/%s/PROVIDES", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->provides),TDB_REPLACE); + REGISTRY_KEY *key; + prs_struct ps; + REGVAL_CTR *values; + REGISTRY_VALUE *val; + SEC_DESC *sd = NULL; + SEC_DESC *ret_sd = NULL; + pstring path; + WERROR wresult; + + /* now add the security descriptor */ + + pstr_sprintf( path, "%s\\%s\\%s", KEY_SERVICES, name, "Security" ); + wresult = regkey_open_internal( &key, path, token, REG_KEY_ALL ); + if ( !W_ERROR_IS_OK(wresult) ) { + DEBUG(0,("svcctl_get_secdesc: key lookup failed! [%s] (%s)\n", + path, dos_errstr(wresult))); + return NULL; + } - pstr_sprintf(keystring,"SERVICE/%s/SERVICENAME", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->servicename),TDB_REPLACE); + if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) { + DEBUG(0,("add_new_svc_name: talloc() failed!\n")); + TALLOC_FREE( key ); + return NULL; + } - pstr_sprintf(keystring,"SERVICE/%s/DEPENDENCIES", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->dependencies),TDB_REPLACE); + fetch_reg_values( key, values ); + + if ( !(val = regval_ctr_getvalue( values, "Security" )) ) { + DEBUG(6,("svcctl_get_secdesc: constructing default secdesc for service [%s]\n", + name)); + TALLOC_FREE( key ); + return construct_service_sd( ctx ); + } + - pstr_sprintf(keystring,"SERVICE/%s/SHOULDSTART", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->shouldstart),TDB_REPLACE); + /* stream the printer security descriptor */ + + prs_init( &ps, 0, key, UNMARSHALL); + prs_give_memory( &ps, regval_data_p(val), regval_size(val), False ); + + if ( !sec_io_desc("sec_desc", &sd, &ps, 0 ) ) { + TALLOC_FREE( key ); + return construct_service_sd( ctx ); + } + + ret_sd = dup_sec_desc( ctx, sd ); + + /* finally cleanup the Security key */ + + prs_mem_free( &ps ); + TALLOC_FREE( key ); - pstr_sprintf(keystring,"SERVICE/%s/SHOULDSTOP", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->shouldstop),TDB_REPLACE); + return ret_sd; +} - pstr_sprintf(keystring,"SERVICE/%s/REQUIREDSTART", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->requiredstart),TDB_REPLACE); +/******************************************************************** +********************************************************************/ - pstr_sprintf(keystring,"SERVICE/%s/REQUIREDSTOP", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->requiredstop),TDB_REPLACE); +char* svcctl_lookup_dispname( const char *name, NT_USER_TOKEN *token ) +{ + static fstring display_name; + REGISTRY_KEY *key; + REGVAL_CTR *values; + REGISTRY_VALUE *val; + pstring path; + WERROR wresult; + + /* now add the security descriptor */ + + pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name ); + wresult = regkey_open_internal( &key, path, token, REG_KEY_ALL ); + if ( !W_ERROR_IS_OK(wresult) ) { + DEBUG(0,("svcctl_lookup_dispname: key lookup failed! [%s] (%s)\n", + path, dos_errstr(wresult))); + return NULL; + } - pstr_sprintf(keystring,"SERVICE/%s/DESCRIPTION", service_name); - tdb_store_bystring(stdb,keystring,string_tdb_data(si->description),TDB_REPLACE); + if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) { + DEBUG(0,("svcctl_lookup_dispname: talloc() failed!\n")); + TALLOC_FREE( key ); + return NULL; + } - pstr_sprintf(keystring,"SERVICE/%s/SHORTDESC", service_name); - if (si->shortdescription && *si->shortdescription) - tdb_store_bystring(stdb,keystring,string_tdb_data(si->shortdescription),TDB_REPLACE); + fetch_reg_values( key, values ); + + if ( !(val = regval_ctr_getvalue( values, "DisplayName" )) ) + fstrcpy( display_name, name ); else - tdb_store_bystring(stdb,keystring,string_tdb_data(si->description),TDB_REPLACE); + rpcstr_pull( display_name, regval_data_p(val), sizeof(display_name), regval_size(val), 0 ); - return True; + TALLOC_FREE( key ); + + return display_name; } -/**************************************************************************** - Create/Open the service control manager tdb. This code a clone of init_group_mapping. -****************************************************************************/ +/******************************************************************** +********************************************************************/ -BOOL init_svcctl_db(void) +char* svcctl_lookup_description( const char *name, NT_USER_TOKEN *token ) { - const char *vstring = "INFO/version"; - uint32 vers_id; - char **svc_list; - char **svcname; - pstring keystring; - pstring external_service_list; - pstring internal_service_list; - Service_info si; - const Internal_service_description *isd_ptr; - /* svc_list = str_list_make( "etc/init.d/skeleton etc/init.d/syslog", NULL ); */ - svc_list=(char **)lp_enable_svcctl(); - - if (service_tdb) - return True; - - pstrcpy(external_service_list,""); - - service_tdb = tdb_open_log(lock_path("services.tdb"), 0, TDB_DEFAULT, O_RDWR, 0600); - if (!service_tdb) { - DEBUG(0,("Failed to open service db\n")); - service_tdb = tdb_open_log(lock_path("services.tdb"), 0, TDB_DEFAULT, O_RDWR|O_CREAT, 0600); - if (!service_tdb) return False; - DEBUG(0,("Created new services db\n")); + static fstring description; + REGISTRY_KEY *key; + REGVAL_CTR *values; + REGISTRY_VALUE *val; + pstring path; + WERROR wresult; + + /* now add the security descriptor */ + + pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name ); + wresult = regkey_open_internal( &key, path, token, REG_KEY_ALL ); + if ( !W_ERROR_IS_OK(wresult) ) { + DEBUG(0,("svcctl_lookup_dispname: key lookup failed! [%s] (%s)\n", + path, dos_errstr(wresult))); + return NULL; } - if ((-1 == tdb_fetch_uint32(service_tdb, vstring,&vers_id)) || (vers_id != SERVICEDB_VERSION_V1)) { - /* wrong version of DB, or db was just created */ - tdb_traverse(service_tdb, tdb_traverse_delete_fn, NULL); - tdb_store_uint32(service_tdb, vstring, SERVICEDB_VERSION_V1); + if ( !(values = TALLOC_ZERO_P( key, REGVAL_CTR )) ) { + DEBUG(0,("svcctl_lookup_dispname: talloc() failed!\n")); + TALLOC_FREE( key ); + return NULL; } - tdb_unlock_bystring(service_tdb, vstring); - DEBUG(0,("Initializing services db\n")); + fetch_reg_values( key, values ); + + if ( !(val = regval_ctr_getvalue( values, "Description" )) ) + fstrcpy( description, "Unix Service"); + else + rpcstr_pull( description, regval_data_p(val), sizeof(description), regval_size(val), 0 ); + + TALLOC_FREE( key ); - svcname = svc_list; + return description; +} - /* Get the EXTERNAL services as mentioned by line in smb.conf */ - while (*svcname) { - DEBUG(10,("Reading information on service %s\n",*svcname)); - if (get_LSB_data(*svcname,&si));{ - /* write the information to the TDB */ - store_service_info(service_tdb,*svcname,&si); - /* definitely not efficient to do it this way. */ - pstrcat(external_service_list,"\""); - pstrcat(external_service_list,*svcname); - pstrcat(external_service_list,"\" "); - } - svcname++; +/******************************************************************** +********************************************************************/ + +REGVAL_CTR* svcctl_fetch_regvalues( const char *name, NT_USER_TOKEN *token ) +{ + REGISTRY_KEY *key; + REGVAL_CTR *values; + pstring path; + WERROR wresult; + + /* now add the security descriptor */ + + pstr_sprintf( path, "%s\\%s", KEY_SERVICES, name ); + wresult = regkey_open_internal( &key, path, token, REG_KEY_ALL ); + if ( !W_ERROR_IS_OK(wresult) ) { + DEBUG(0,("svcctl_fetch_regvalues: key lookup failed! [%s] (%s)\n", + path, dos_errstr(wresult))); + return NULL; } - pstrcpy(keystring,"EXTERNAL_SERVICES"); - DEBUG(8,("Storing external service list [%s]\n",external_service_list)); - tdb_store_bystring(service_tdb,keystring,string_tdb_data(external_service_list),TDB_REPLACE); - - /* Get the INTERNAL services */ - - pstrcpy(internal_service_list,""); - isd_ptr = ISD; - - while (isd_ptr && (isd_ptr->filename)) { - DEBUG(10,("Reading information on service %s\n",isd_ptr->filename)); - if (get_internal_service_data(isd_ptr,&si)){ - /* write the information to the TDB */ - store_service_info(service_tdb,(char *)isd_ptr->filename,&si); - /* definitely not efficient to do it this way. */ - pstrcat(internal_service_list,"\""); - pstrcat(internal_service_list,isd_ptr->filename); - pstrcat(internal_service_list,"\" "); - - } - isd_ptr++; + + if ( !(values = TALLOC_ZERO_P( NULL, REGVAL_CTR )) ) { + DEBUG(0,("svcctl_fetch_regvalues: talloc() failed!\n")); + TALLOC_FREE( key ); + return NULL; } - pstrcpy(keystring,"INTERNAL_SERVICES"); - DEBUG(8,("Storing internal service list [%s]\n",internal_service_list)); - tdb_store_bystring(service_tdb,keystring,string_tdb_data(internal_service_list),TDB_REPLACE); + + fetch_reg_values( key, values ); - return True; + TALLOC_FREE( key ); + + return values; } -#endif + diff --git a/source3/services/svc_netlogon.c b/source3/services/svc_netlogon.c new file mode 100644 index 00000000000..2aa5a31cde3 --- /dev/null +++ b/source3/services/svc_netlogon.c @@ -0,0 +1,66 @@ +/* + * Unix SMB/CIFS implementation. + * Service Control API Implementation + * Copyright (C) Gerald Carter 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" + +/* Implementation for internal netlogon service */ + +/********************************************************************* +*********************************************************************/ + +static WERROR netlogon_stop( const char *service, SERVICE_STATUS *service_status ) +{ + return WERR_ACCESS_DENIED; +} + +/********************************************************************* +*********************************************************************/ + +static WERROR netlogon_start( const char *service ) +{ + return WERR_ACCESS_DENIED; +} + +/********************************************************************* +*********************************************************************/ + +static WERROR netlogon_status( const char *service, SERVICE_STATUS *service_status ) +{ + ZERO_STRUCTP( service_status ); + + service_status->type = 0x20; + if ( lp_servicenumber("NETLOGON") != -1 ) + service_status->state = SVCCTL_RUNNING; + else + service_status->state = SVCCTL_STOPPED; + + return WERR_OK; +} + +/********************************************************************* +*********************************************************************/ + +/* struct for svcctl control to manipulate netlogon service */ + +SERVICE_CONTROL_OPS netlogon_svc_ops = { + netlogon_stop, + netlogon_start, + netlogon_status +}; diff --git a/source3/services/svc_rcinit.c b/source3/services/svc_rcinit.c index c856ae2a995..5801d076c49 100644 --- a/source3/services/svc_rcinit.c +++ b/source3/services/svc_rcinit.c @@ -171,24 +171,78 @@ BOOL get_LSB_data(char *fname,Service_info *si ) /********************************************************************* *********************************************************************/ -static WERROR rcinit_stop( SERVICE_STATUS *service_status ) +static WERROR rcinit_stop( const char *service, SERVICE_STATUS *status ) { - return WERR_OK; + pstring command; + int ret, fd; + + pstr_sprintf( command, "%s/%s/%s stop", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, service ); + + /* we've already performed the access check when the service was opened */ + + become_root(); + ret = smbrun( command , &fd ); + unbecome_root(); + + DEBUGADD(5, ("rcinit_start: [%s] returned [%d]\n", command, ret)); + close(fd); + + ZERO_STRUCTP( status ); + status->type = 0x0020; + status->state = (ret == 0 ) ? 0x0001 : 0x0004; + status->controls_accepted = 0x0005; + + return ( ret == 0 ) ? WERR_OK : WERR_ACCESS_DENIED; } /********************************************************************* *********************************************************************/ -static WERROR rcinit_start( void ) +static WERROR rcinit_start( const char *service ) { - return WERR_OK; + pstring command; + int ret, fd; + + pstr_sprintf( command, "%s/%s/%s start", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, service ); + + /* we've already performed the access check when the service was opened */ + + become_root(); + ret = smbrun( command , &fd ); + unbecome_root(); + + DEBUGADD(5, ("rcinit_start: [%s] returned [%d]\n", command, ret)); + close(fd); + + return ( ret == 0 ) ? WERR_OK : WERR_ACCESS_DENIED; } /********************************************************************* *********************************************************************/ -static WERROR rcinit_status( SERVICE_STATUS *service_status ) +static WERROR rcinit_status( const char *service, SERVICE_STATUS *status ) { + pstring command; + int ret, fd; + + pstr_sprintf( command, "%s/%s/%s status", dyn_LIBDIR, SVCCTL_SCRIPT_DIR, service ); + + /* we've already performed the access check when the service was opened */ + /* assume as return code of 0 means that the service is ok. Anything else + is STOPPED */ + + become_root(); + ret = smbrun( command , &fd ); + unbecome_root(); + + DEBUGADD(5, ("rcinit_start: [%s] returned [%d]\n", command, ret)); + close(fd); + + ZERO_STRUCTP( status ); + status->type = 0x0020; + status->state = (ret == 0 ) ? 0x0004 : 0x0001; + status->controls_accepted = 0x0005; + return WERR_OK; } diff --git a/source3/services/svc_spoolss.c b/source3/services/svc_spoolss.c index 5f8fa73ced4..13a1dbb1bdf 100644 --- a/source3/services/svc_spoolss.c +++ b/source3/services/svc_spoolss.c @@ -25,7 +25,7 @@ /********************************************************************* *********************************************************************/ -static WERROR spoolss_stop( SERVICE_STATUS *service_status ) +static WERROR spoolss_stop( const char *service, SERVICE_STATUS *service_status ) { ZERO_STRUCTP( service_status ); @@ -43,7 +43,7 @@ static WERROR spoolss_stop( SERVICE_STATUS *service_status ) /********************************************************************* *********************************************************************/ -static WERROR spoolss_start( void ) +static WERROR spoolss_start( const char *service ) { /* see if the smb.conf will support this anyways */ @@ -58,8 +58,10 @@ static WERROR spoolss_start( void ) /********************************************************************* *********************************************************************/ -static WERROR spoolss_status( SERVICE_STATUS *service_status ) +static WERROR spoolss_status( const char *service, SERVICE_STATUS *service_status ) { + ZERO_STRUCTP( service_status ); + service_status->type = 0x110; service_status->state = lp_get_spoolss_state(); service_status->controls_accepted = SVCCTL_ACCEPT_STOP; diff --git a/source3/services/svc_winreg.c b/source3/services/svc_winreg.c new file mode 100644 index 00000000000..1bccee246e2 --- /dev/null +++ b/source3/services/svc_winreg.c @@ -0,0 +1,63 @@ +/* + * Unix SMB/CIFS implementation. + * Service Control API Implementation + * Copyright (C) Gerald Carter 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" + +/* Implementation for internal winreg service */ + +/********************************************************************* +*********************************************************************/ + +static WERROR winreg_stop( const char *service, SERVICE_STATUS *service_status ) +{ + return WERR_ACCESS_DENIED; +} + +/********************************************************************* +*********************************************************************/ + +static WERROR winreg_start( const char *service ) +{ + return WERR_ACCESS_DENIED; +} + +/********************************************************************* +*********************************************************************/ + +static WERROR winreg_status( const char *service, SERVICE_STATUS *service_status ) +{ + ZERO_STRUCTP( service_status ); + + service_status->type = 0x20; + service_status->state = SVCCTL_RUNNING; + + return WERR_OK; +} + +/********************************************************************* +*********************************************************************/ + +/* struct for svcctl control to manipulate winreg service */ + +SERVICE_CONTROL_OPS winreg_svc_ops = { + winreg_stop, + winreg_start, + winreg_status +}; diff --git a/source3/smbd/blocking.c b/source3/smbd/blocking.c index 72d021d4e64..805e45f6ea3 100644 --- a/source3/smbd/blocking.c +++ b/source3/smbd/blocking.c @@ -80,7 +80,8 @@ static BOOL in_chained_smb(void) return (chain_size != 0); } -static void received_unlock_msg(int msg_type, pid_t src, void *buf, size_t len); +static void received_unlock_msg(int msg_type, struct process_id src, + void *buf, size_t len); /**************************************************************************** Function to push a blocking lock request onto the lock queue. @@ -127,7 +128,7 @@ BOOL push_blocking_lock_request( char *inbuf, int length, int lock_timeout, /* Add a pending lock record for this. */ status = brl_lock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, - lock_pid, sys_getpid(), blr->fsp->conn->cnum, + lock_pid, procid_self(), blr->fsp->conn->cnum, offset, count, PENDING_LOCK, &my_lock_ctx); if (!NT_STATUS_IS_OK(status)) { @@ -351,8 +352,8 @@ static BOOL process_lockread(blocking_lock_record *blr) SSVAL(p,0,nread); p += 2; set_message_end(outbuf, p+nread); - DEBUG(3, ( "process_lockread file = %s, fnum=%d num=%d nread=%d\n", - fsp->fsp_name, fsp->fnum, (int)numtoread, (int)nread ) ); + DEBUG(3, ( "process_lockread file = %s, fnum=%d num=%lu nread=%ld\n", + fsp->fsp_name, fsp->fnum, (unsigned long)numtoread, (long)nread ) ); send_blocking_reply(outbuf,outsize); return True; @@ -526,7 +527,7 @@ void remove_pending_lock_requests_by_fid(files_struct *fsp) file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, - blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, + blr->lock_pid, procid_self(), blr->fsp->conn->cnum, blr->offset, blr->count, True, NULL, NULL); free_blocking_lock_record(blr); @@ -552,7 +553,7 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); brl_unlock(blr->fsp->dev, blr->fsp->inode, blr->fsp->fnum, - blr->lock_pid, sys_getpid(), blr->fsp->conn->cnum, + blr->lock_pid, procid_self(), blr->fsp->conn->cnum, blr->offset, blr->count, True, NULL, NULL); free_blocking_lock_record(blr); } @@ -563,7 +564,8 @@ file %s fnum = %d\n", blr->com_type, fsp->fsp_name, fsp->fnum )); Set a flag as an unlock request affects one of our pending locks. *****************************************************************************/ -static void received_unlock_msg(int msg_type, pid_t src, void *buf, size_t len) +static void received_unlock_msg(int msg_type, struct process_id src, + void *buf, size_t len) { DEBUG(10,("received_unlock_msg\n")); process_blocking_lock_queue(time(NULL)); @@ -641,7 +643,7 @@ void process_blocking_lock_queue(time_t t) fsp->fnum, fsp->fsp_name )); brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, + blr->lock_pid, procid_self(), conn->cnum, blr->offset, blr->count, True, NULL, NULL); blocking_lock_reply_error(blr,NT_STATUS_FILE_LOCK_CONFLICT); @@ -658,7 +660,7 @@ void process_blocking_lock_queue(time_t t) blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, + blr->lock_pid, procid_self(), conn->cnum, blr->offset, blr->count, True, NULL, NULL); free_blocking_lock_record(blr); @@ -673,7 +675,7 @@ void process_blocking_lock_queue(time_t t) blocking_lock_reply_error(blr,NT_STATUS_ACCESS_DENIED); brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, + blr->lock_pid, procid_self(), conn->cnum, blr->offset, blr->count, True, NULL, NULL); free_blocking_lock_record(blr); @@ -690,7 +692,7 @@ void process_blocking_lock_queue(time_t t) if(blocking_lock_record_process(blr)) { brl_unlock(fsp->dev, fsp->inode, fsp->fnum, - blr->lock_pid, sys_getpid(), conn->cnum, + blr->lock_pid, procid_self(), conn->cnum, blr->offset, blr->count, True, NULL, NULL); free_blocking_lock_record(blr); diff --git a/source3/smbd/change_trust_pw.c b/source3/smbd/change_trust_pw.c index 1178400e4db..738d12151db 100644 --- a/source3/smbd/change_trust_pw.c +++ b/source3/smbd/change_trust_pw.c @@ -33,7 +33,8 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; struct in_addr pdc_ip; fstring dc_name; - struct cli_state *cli; + struct cli_state *cli = NULL; + struct rpc_pipe_client *netlogon_pipe = NULL; DEBUG(5,("change_trust_account_password: Attempting to change trust account password in domain %s....\n", domain)); @@ -71,20 +72,18 @@ NTSTATUS change_trust_account_password( const char *domain, const char *remote_m * Now start the NT Domain stuff :-). */ - if(cli_nt_session_open(cli, PI_NETLOGON) == False) { + /* Shouldn't we open this with schannel ? JRA. */ + + netlogon_pipe = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, &nt_status); + if (!netlogon_pipe) { DEBUG(0,("modify_trust_password: unable to open the domain client session to machine %s. Error was : %s.\n", - dc_name, cli_errstr(cli))); - cli_nt_session_close(cli); - cli_ulogoff(cli); + dc_name, nt_errstr(nt_status))); cli_shutdown(cli); - nt_status = NT_STATUS_UNSUCCESSFUL; goto failed; } - nt_status = trust_pw_find_change_and_store_it(cli, cli->mem_ctx, domain); + nt_status = trust_pw_find_change_and_store_it(netlogon_pipe, cli->mem_ctx, domain); - cli_nt_session_close(cli); - cli_ulogoff(cli); cli_shutdown(cli); failed: diff --git a/source3/smbd/chgpasswd.c b/source3/smbd/chgpasswd.c index 374c57a083a..c1168583ae7 100644 --- a/source3/smbd/chgpasswd.c +++ b/source3/smbd/chgpasswd.c @@ -946,7 +946,7 @@ static BOOL check_passwd_history(SAM_ACCOUNT *sampass, const char *plaintext) int i; uint32 pwHisLen, curr_pwHisLen; - account_policy_get(AP_PASSWORD_HISTORY, &pwHisLen); + pdb_get_account_policy(AP_PASSWORD_HISTORY, &pwHisLen); if (pwHisLen == 0) { return False; } @@ -1017,7 +1017,7 @@ NTSTATUS change_oem_password(SAM_ACCOUNT *hnd, char *old_passwd, char *new_passw return NT_STATUS_ACCOUNT_RESTRICTION; } - if (account_policy_get(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) { + if (pdb_get_account_policy(AP_MIN_PASSWORD_LEN, &min_len) && (str_charnum(new_passwd) < min_len)) { DEBUG(1, ("user %s cannot change password - password too short\n", username)); DEBUGADD(1, (" account policy min password len = %d\n", min_len)); diff --git a/source3/smbd/close.c b/source3/smbd/close.c index afc645ca062..becca003b64 100644 --- a/source3/smbd/close.c +++ b/source3/smbd/close.c @@ -110,31 +110,30 @@ static int close_filestruct(files_struct *fsp) If any deferred opens are waiting on this close, notify them. ****************************************************************************/ -static void notify_deferred_opens(files_struct *fsp) +static void notify_deferred_opens(struct share_mode_lock *lck) { - deferred_open_entry *de_array = NULL; - int num_de_entries, i; - pid_t mypid = sys_getpid(); - - if (!lp_defer_sharing_violations()) { - return; - } - - num_de_entries = get_deferred_opens(fsp->conn, fsp->dev, fsp->inode, &de_array); - for (i = 0; i < num_de_entries; i++) { - deferred_open_entry *entry = &de_array[i]; - if (entry->pid == mypid) { - /* - * We need to notify ourself to retry the open. - * Do this by finding the queued SMB record, moving it - * to the head of the queue and changing the wait time to zero. - */ - schedule_sharing_violation_open_smb_message(entry->mid); - } else { - send_deferred_open_retry_message(entry); - } - } - SAFE_FREE(de_array); + int i; + + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *e = &lck->share_modes[i]; + + if (!is_deferred_open_entry(e)) { + continue; + } + + if (procid_is_me(&e->pid)) { + /* + * We need to notify ourself to retry the open. Do + * this by finding the queued SMB record, moving it to + * the head of the queue and changing the wait time to + * zero. + */ + schedule_deferred_open_smb_message(e->op_mid); + } else { + message_send_pid(e->pid, MSG_SMB_OPEN_RETRY, + e, sizeof(*e), True); + } + } } /**************************************************************************** @@ -148,13 +147,12 @@ static void notify_deferred_opens(files_struct *fsp) static int close_normal_file(files_struct *fsp, BOOL normal_close) { - share_mode_entry *share_entry = NULL; - size_t share_entry_count = 0; BOOL delete_file = False; connection_struct *conn = fsp->conn; int saved_errno = 0; int err = 0; int err1 = 0; + struct share_mode_lock *lck; remove_pending_lock_requests_by_fid(fsp); @@ -194,23 +192,34 @@ static int close_normal_file(files_struct *fsp, BOOL normal_close) * This prevents race conditions with the file being created. JRA. */ - lock_share_entry_fsp(fsp); - - share_entry_count = del_share_mode(fsp, &share_entry, - &delete_file); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, fsp->fsp_name); - DEBUG(10,("close_normal_file: share_entry_count = %lu for file %s\n", - (unsigned long)share_entry_count, fsp->fsp_name )); + if (lck == NULL) { + DEBUG(0, ("Could not get share mode lock\n")); + return EINVAL; + } - if (share_entry_count != 0) { - /* We're not the last ones -- don't delete */ - delete_file = False; + if (!del_share_mode(lck, fsp)) { + DEBUG(0, ("Could not delete share entry\n")); } - SAFE_FREE(share_entry); + delete_file = lck->delete_on_close; + + if (delete_file) { + int i; + /* See if others still have the file open. If this is the + * case, then don't delete */ + for (i=0; inum_share_modes; i++) { + if (is_valid_share_mode_entry(&lck->share_modes[i])) { + delete_file = False; + break; + } + } + } /* Notify any deferred opens waiting on this close. */ - notify_deferred_opens(fsp); + notify_deferred_opens(lck); + reply_to_oplock_break_requests(fsp); /* * NT can set delete_on_close of the last open @@ -234,7 +243,7 @@ with error %s\n", fsp->fsp_name, strerror(errno) )); process_pending_change_notify_queue((time_t)0); } - unlock_share_entry_fsp(fsp); + talloc_free(lck); if(fsp->oplock_type) release_file_oplock(fsp); @@ -296,7 +305,7 @@ static int close_directory(files_struct *fsp, BOOL normal_close) */ if (normal_close && - get_delete_on_close_flag(fsp->dev, fsp->inode)) { + get_delete_on_close_flag(fsp->dev, fsp->inode, fsp->fsp_name)) { BOOL ok = rmdir_internals(fsp->conn, fsp->fsp_name); DEBUG(5,("close_directory: %s. Delete on close was set - deleting directory %s.\n", fsp->fsp_name, ok ? "succeeded" : "failed" )); diff --git a/source3/smbd/conn.c b/source3/smbd/conn.c index b69868ecec1..bb000bac30e 100644 --- a/source3/smbd/conn.c +++ b/source3/smbd/conn.c @@ -287,7 +287,7 @@ the message contains just a share name and all instances of that share are unmounted the special sharename '*' forces unmount of all shares ****************************************************************************/ -void msg_force_tdis(int msg_type, pid_t pid, void *buf, size_t len) +void msg_force_tdis(int msg_type, struct process_id pid, void *buf, size_t len) { connection_struct *conn, *next; fstring sharename; diff --git a/source3/smbd/connection.c b/source3/smbd/connection.c index 32e2f058fc2..07d3181144f 100644 --- a/source3/smbd/connection.c +++ b/source3/smbd/connection.c @@ -38,7 +38,7 @@ TDB_CONTEXT *conn_tdb_ctx(void) static void make_conn_key(connection_struct *conn, const char *name, TDB_DATA *pkbuf, struct connections_key *pkey) { ZERO_STRUCTP(pkey); - pkey->pid = sys_getpid(); + pkey->pid = procid_self(); pkey->cnum = conn?conn->cnum:-1; fstrcpy(pkey->name, name); #ifdef DEVELOPER @@ -107,8 +107,8 @@ static int count_fn( TDB_CONTEXT *the_tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *u /* If the pid was not found delete the entry from connections.tdb */ if (cs->Clear && !process_exists(crec.pid) && (errno == ESRCH)) { - DEBUG(2,("pid %u doesn't exist - deleting connections %d [%s]\n", - (unsigned int)crec.pid, crec.cnum, crec.name)); + DEBUG(2,("pid %s doesn't exist - deleting connections %d [%s]\n", + procid_str_static(&crec.pid), crec.cnum, crec.name)); if (tdb_delete(the_tdb, kbuf) != 0) DEBUG(0,("count_fn: tdb_delete failed with error %s\n", tdb_errorstr(tdb) )); return 0; @@ -174,7 +174,7 @@ BOOL claim_connection(connection_struct *conn, const char *name,int max_connecti /* fill in the crec */ ZERO_STRUCT(crec); crec.magic = 0x280267; - crec.pid = sys_getpid(); + crec.pid = procid_self(); crec.cnum = conn?conn->cnum:-1; if (conn) { crec.uid = conn->uid; diff --git a/source3/smbd/error.c b/source3/smbd/error.c index 090a2f6d813..3cdcae5c7f5 100644 --- a/source3/smbd/error.c +++ b/source3/smbd/error.c @@ -41,23 +41,22 @@ void set_saved_error_triple(int eclass, int ecode, NTSTATUS status) override_ERR_ntstatus = status; } +void set_saved_ntstatus(NTSTATUS status) +{ + uint8 tmp_eclass; /* Hmmm. override_ERR_class is not uint8... */ + override_ERR_ntstatus = status; + ntstatus_to_dos(status, &tmp_eclass, &override_ERR_code); + override_ERR_class = tmp_eclass; + +} + /**************************************************************************** Return the current settings of the error triple. Return True if any are set. ****************************************************************************/ -BOOL get_saved_error_triple(int *peclass, int *pecode, NTSTATUS *pstatus) +NTSTATUS get_saved_ntstatus(void) { - if (peclass) { - *peclass = override_ERR_class; - } - if (pecode) { - *pecode = override_ERR_code; - } - if (pstatus) { - *pstatus = override_ERR_ntstatus; - } - - return (override_ERR_class || !NT_STATUS_IS_OK(override_ERR_ntstatus)); + return override_ERR_ntstatus; } /**************************************************************************** diff --git a/source3/smbd/files.c b/source3/smbd/files.c index 65986e96127..181e17b11fb 100644 --- a/source3/smbd/files.c +++ b/source3/smbd/files.c @@ -65,7 +65,7 @@ files_struct *file_new(connection_struct *conn) { int i; static int first_file; - files_struct *fsp, *next; + files_struct *fsp; /* we want to give out file handles differently on each new connection because of a common bug in MS clients where they try to @@ -76,32 +76,21 @@ files_struct *file_new(connection_struct *conn) first_file = (sys_getpid() ^ (int)time(NULL)) % real_max_open_files; } + /* TODO: Port the id-tree implementation from Samba4 */ + i = bitmap_find(file_bmap, first_file); if (i == -1) { - /* - * Before we give up, go through the open files - * and see if there are any files opened with a - * batch oplock. If so break the oplock and then - * re-use that entry (if it becomes closed). - * This may help as NT/95 clients tend to keep - * files batch oplocked for quite a long time - * after they have finished with them. - */ - for (fsp=Files;fsp;fsp=next) { - next=fsp->next; - if (attempt_close_oplocked_file(fsp)) { - return file_new(conn); - } - } - DEBUG(0,("ERROR! Out of file structures\n")); - set_saved_error_triple(ERRSRV, ERRnofids, NT_STATUS_TOO_MANY_OPENED_FILES); + /* TODO: We have to unconditionally return a DOS error here, + * W2k3 even returns ERRDOS/ERRnofids for ntcreate&x with + * NTSTATUS negotiated */ + set_saved_ntstatus(NT_STATUS_TOO_MANY_OPENED_FILES); return NULL; } fsp = SMB_MALLOC_P(files_struct); if (!fsp) { - set_saved_error_triple(ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY); + set_saved_ntstatus(NT_STATUS_NO_MEMORY); return NULL; } @@ -110,7 +99,7 @@ files_struct *file_new(connection_struct *conn) fsp->fh = SMB_MALLOC_P(struct fd_handle); if (!fsp->fh) { SAFE_FREE(fsp); - set_saved_error_triple(ERRDOS, ERRnomem, NT_STATUS_NO_MEMORY); + set_saved_ntstatus(NT_STATUS_NO_MEMORY); return NULL; } @@ -293,7 +282,9 @@ files_struct *file_find_dif(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_i DLIST_PROMOTE(Files, fsp); } /* Paranoia check. */ - if (fsp->fh->fd == -1 && fsp->oplock_type != NO_OPLOCK) { + if ((fsp->fh->fd == -1) && + (fsp->oplock_type != NO_OPLOCK) && + (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) { DEBUG(0,("file_find_dif: file %s dev = %x, inode = %.0f, file_id = %u \ oplock_type = %u is a stat open with oplock type !\n", fsp->fsp_name, (unsigned int)fsp->dev, (double)fsp->inode, (unsigned int)fsp->file_id, diff --git a/source3/smbd/mangle_hash2.c b/source3/smbd/mangle_hash2.c index 613dda9a16b..335ba8e2ef9 100644 --- a/source3/smbd/mangle_hash2.c +++ b/source3/smbd/mangle_hash2.c @@ -212,7 +212,7 @@ static BOOL is_mangled_component(const char *name, size_t len) { unsigned int i; - M_DEBUG(10,("is_mangled_component %s (len %u) ?\n", name, (unsigned int)len)); + M_DEBUG(10,("is_mangled_component %s (len %lu) ?\n", name, (unsigned long)len)); /* check the length */ if (len > 12 || len < 8) @@ -250,7 +250,7 @@ static BOOL is_mangled_component(const char *name, size_t len) } } - M_DEBUG(10,("is_mangled_component %s (len %u) -> yes\n", name, (unsigned int)len)); + M_DEBUG(10,("is_mangled_component %s (len %lu) -> yes\n", name, (unsigned long)len)); return True; } diff --git a/source3/smbd/message.c b/source3/smbd/message.c index 5af7d3e451e..e975da3e153 100644 --- a/source3/smbd/message.c +++ b/source3/smbd/message.c @@ -43,6 +43,7 @@ static void msg_deliver(void) int fd; char *msg; int len; + ssize_t sz; if (! (*lp_msg_command())) { @@ -70,14 +71,20 @@ static void msg_deliver(void) if (msgbuf[i] == '\r' && i < (msgpos-1) && msgbuf[i+1] == '\n') { i++; continue; } - write(fd, &msgbuf[i++], 1); + sz = write(fd, &msgbuf[i++], 1); + if ( sz != 1 ) { + DEBUG(0,("Write error to fd %d: %ld(%d)\n",fd, (long)sz, errno )); + } } } else { for (i = 0; i < len;) { if (msg[i] == '\r' && i < (len-1) && msg[i+1] == '\n') { i++; continue; } - write(fd, &msg[i++],1); + sz = write(fd, &msg[i++],1); + if ( sz != 1 ) { + DEBUG(0,("Write error to fd %d: %ld(%d)\n",fd, (long)sz, errno )); + } } SAFE_FREE(msg); } diff --git a/source3/smbd/nttrans.c b/source3/smbd/nttrans.c index f9b70de0ace..3db55bad14d 100644 --- a/source3/smbd/nttrans.c +++ b/source3/smbd/nttrans.c @@ -24,7 +24,6 @@ extern int max_send; extern enum protocol_types Protocol; extern int smb_read_error; -extern int global_oplock_break; extern struct current_user current_user; static const char *known_nt_pipes[] = { @@ -43,6 +42,7 @@ static const char *known_nt_pipes[] = { "\\rpcecho", "\\svcctl", "\\eventlog", + "\\unixinfo", NULL }; @@ -861,7 +861,7 @@ create_options = 0x%x root_dir_fid = 0x%x\n", } else { SCVAL(p,0, EXCLUSIVE_OPLOCK_RETURN); } - } else if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { + } else if (fsp->oplock_type == LEVEL_II_OPLOCK) { SCVAL(p,0, LEVEL_II_OPLOCK_RETURN); } else { SCVAL(p,0,NO_OPLOCK_RETURN); @@ -1666,11 +1666,11 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new &info); if (!fsp1) { - get_saved_error_triple(NULL, NULL, &status); + status = get_saved_ntstatus(); if (NT_STATUS_IS_OK(status)) { status = NT_STATUS_ACCESS_DENIED; } - set_saved_error_triple(0, 0, NT_STATUS_OK); + set_saved_ntstatus(NT_STATUS_OK); return status; } @@ -1684,11 +1684,11 @@ static NTSTATUS copy_internals(connection_struct *conn, char *oldname, char *new &info); if (!fsp2) { - get_saved_error_triple(NULL, NULL, &status); + status = get_saved_ntstatus(); if (NT_STATUS_IS_OK(status)) { status = NT_STATUS_ACCESS_DENIED; } - set_saved_error_triple(0, 0, NT_STATUS_OK); + set_saved_ntstatus(NT_STATUS_OK); close_file(fsp1,False); return status; } @@ -1989,7 +1989,7 @@ static int call_nt_transact_query_security_desc(connection_struct *conn, char *i return(UNIXERROR(ERRDOS,ERRnoaccess)); } - DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %d.\n",(int)sd_size)); + DEBUG(3,("call_nt_transact_query_security_desc: sd_size = %lu.\n",(unsigned long)sd_size)); SIVAL(params,0,(uint32)sd_size); @@ -2743,21 +2743,6 @@ int reply_nttrans(connection_struct *conn, uint32 num_params_sofar, num_data_sofar; START_PROFILE(SMBnttrans); - if(global_oplock_break && - ((function_code == NT_TRANSACT_CREATE) || - (function_code == NT_TRANSACT_RENAME))) { - /* - * Queue this open message as we are the process of an oplock break. - */ - - DEBUG(2,("reply_nttrans: queueing message code 0x%x \ -due to being in oplock break state.\n", (unsigned int)function_code )); - - push_oplock_pending_smb_message( inbuf, length); - END_PROFILE(SMBnttrans); - return -1; - } - if (IS_IPC(conn) && (function_code != NT_TRANSACT_CREATE)) { END_PROFILE(SMBnttrans); return ERROR_DOS(ERRSRV,ERRaccess); diff --git a/source3/smbd/open.c b/source3/smbd/open.c index ed847826d52..56d31c69409 100644 --- a/source3/smbd/open.c +++ b/source3/smbd/open.c @@ -24,11 +24,11 @@ extern struct current_user current_user; extern userdom_struct current_user_info; -extern uint16 global_oplock_port; extern uint16 global_smbpid; extern BOOL global_client_failed_oplock_break; -struct dev_inode_bundle { +struct deferred_open_record { + BOOL delayed_for_oplocks; SMB_DEV_T dev; SMB_INO_T inode; }; @@ -208,7 +208,6 @@ static BOOL open_file(files_struct *fsp, BOOL file_existed = VALID_STAT(*psbuf); fsp->fh->fd = -1; - fsp->oplock_type = NO_OPLOCK; errno = EPERM; /* Check permissions */ @@ -283,8 +282,7 @@ static BOOL open_file(files_struct *fsp, /* Don't create files with Microsoft wildcard characters. */ if ((local_flags & O_CREAT) && !file_existed && ms_has_wild(fname)) { - set_saved_error_triple(ERRDOS, ERRinvalidname, - NT_STATUS_OBJECT_NAME_INVALID); + set_saved_ntstatus(NT_STATUS_OBJECT_NAME_INVALID); return False; } @@ -354,7 +352,6 @@ static BOOL open_file(files_struct *fsp, } fsp->print_file = False; fsp->modified = False; - fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; fsp->is_directory = False; fsp->is_stat = False; @@ -397,7 +394,7 @@ static BOOL is_executable(const char *fname) Returns True if conflict, False if not. ****************************************************************************/ -static BOOL share_conflict(share_mode_entry *entry, +static BOOL share_conflict(struct share_mode_entry *entry, uint32 access_mask, uint32 share_access) { @@ -445,7 +442,6 @@ static BOOL share_conflict(share_mode_entry *entry, DEBUG(10,("share_conflict: check %d conflict am = 0x%x, right = 0x%x, \ sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (unsigned int)(sa), \ (unsigned int)(share) )); \ - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); \ return True; \ } #else @@ -454,7 +450,6 @@ sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (u DEBUG(10,("share_conflict: check %d conflict am = 0x%x, right = 0x%x, \ sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (unsigned int)(sa), \ (unsigned int)(share) )); \ - set_saved_error_triple(ERRDOS, ERRbadshare, NT_STATUS_SHARING_VIOLATION); \ return True; \ } #endif @@ -480,11 +475,23 @@ sa = 0x%x, share = 0x%x\n", (num), (unsigned int)(am), (unsigned int)(right), (u #if defined(DEVELOPER) static void validate_my_share_entries(int num, - share_mode_entry *share_entry) + struct share_mode_entry *share_entry) { files_struct *fsp; - if (share_entry->pid != sys_getpid()) { + if (!procid_is_me(&share_entry->pid)) { + return; + } + + if (is_deferred_open_entry(share_entry) && + !open_was_deferred(share_entry->op_mid)) { + pstring str; + DEBUG(0, ("Got a deferred entry without a request: " + "PANIC: %s\n", share_mode_str(num, share_entry))); + smb_panic(str); + } + + if (!is_valid_share_mode_entry(share_entry)) { return; } @@ -497,7 +504,26 @@ static void validate_my_share_entries(int num, "share entry with an open file\n"); } + if (is_deferred_open_entry(share_entry) || + is_unused_share_mode_entry(share_entry)) { + goto panic; + } + + if ((share_entry->op_type == NO_OPLOCK) && + (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK)) { + /* Someone has already written to it, but I haven't yet + * noticed */ + return; + } + if (((uint16)fsp->oplock_type) != share_entry->op_type) { + goto panic; + } + + return; + + panic: + { pstring str; DEBUG(0,("validate_my_share_entries: PANIC : %s\n", share_mode_str(num, share_entry) )); @@ -510,375 +536,217 @@ static void validate_my_share_entries(int num, } #endif -struct share_mode_entry_list { - struct share_mode_entry_list *next, *prev; - share_mode_entry entry; -}; - -static void free_broken_entry_list(struct share_mode_entry_list *broken_entry_list) +static BOOL is_stat_open(uint32 access_mask) { - while (broken_entry_list) { - struct share_mode_entry_list *broken_entry = broken_entry_list; - DLIST_REMOVE(broken_entry_list, broken_entry); - SAFE_FREE(broken_entry); - } -} - -static BOOL cause_oplock_break(int request, int existing, uint32 access_mask) -{ - if ((access_mask == DELETE_ACCESS) && - (request == NO_OPLOCK)) { - /* This is a delete request */ - return (BATCH_OPLOCK_TYPE(existing) != 0); - } - - if (EXCLUSIVE_OPLOCK_TYPE(existing) && (request != NO_OPLOCK)) { - return True; - } - - if ((existing != NO_OPLOCK) && (request == NO_OPLOCK)) { - return True; - } - - return False; + return (access_mask && + ((access_mask & ~(SYNCHRONIZE_ACCESS| FILE_READ_ATTRIBUTES| + FILE_WRITE_ATTRIBUTES))==0) && + ((access_mask & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES| + FILE_WRITE_ATTRIBUTES)) != 0)); } /**************************************************************************** - Deal with open deny mode and oplock break processing. + Deal with share modes Invarient: Share mode must be locked on entry and exit. Returns -1 on error, or number of share modes on success (may be zero). ****************************************************************************/ -static int open_mode_check(connection_struct *conn, - const char *fname, - SMB_DEV_T dev, - SMB_INO_T inode, - uint32 access_mask, - uint32 share_access, - uint32 create_options, - int *p_oplock_request, - BOOL *p_all_current_opens_are_level_II) +static NTSTATUS open_mode_check(connection_struct *conn, + const char *fname, + struct share_mode_lock *lck, + uint32 access_mask, + uint32 share_access, + uint32 create_options, + BOOL *file_existed) { int i; - int num_share_modes; - int oplock_contention_count = 0; - share_mode_entry *old_shares = NULL; - BOOL broke_oplock; - BOOL delete_on_close; - num_share_modes = get_share_modes(dev, inode, &old_shares, &delete_on_close); - - if(num_share_modes == 0) { - SAFE_FREE(old_shares); - return 0; + if(lck->num_share_modes == 0) { + return NT_STATUS_OK; } + + *file_existed = True; - if (access_mask && - ((access_mask & ~(SYNCHRONIZE_ACCESS| FILE_READ_ATTRIBUTES| - FILE_WRITE_ATTRIBUTES))==0) && - ((access_mask & (SYNCHRONIZE_ACCESS|FILE_READ_ATTRIBUTES| - FILE_WRITE_ATTRIBUTES)) != 0)) { + if (is_stat_open(access_mask)) { /* Stat open that doesn't trigger oplock breaks or share mode * checks... ! JRA. */ - SAFE_FREE(old_shares); - return num_share_modes; + return NT_STATUS_OK; } /* A delete on close prohibits everything */ - if (delete_on_close) { - SAFE_FREE(old_shares); - errno = EACCES; - return -1; + if (lck->delete_on_close) { + return NT_STATUS_DELETE_PENDING; } /* * Check if the share modes will give us access. */ - do { - struct share_mode_entry_list *broken_entry_list = NULL; - struct share_mode_entry_list *broken_entry = NULL; - - broke_oplock = False; - *p_all_current_opens_are_level_II = True; - - for(i = 0; i < num_share_modes; i++) { - share_mode_entry *share_entry = &old_shares[i]; - BOOL opb_ret; - #if defined(DEVELOPER) - validate_my_share_entries(i, share_entry); + for(i = 0; i < lck->num_share_modes; i++) { + validate_my_share_entries(i, &lck->share_modes[i]); + } #endif - /* - * By observation of NetBench, oplocks are broken - * *before* share modes are checked. This allows a - * file to be closed by the client if the share mode - * would deny access and the client has an oplock. - * Check if someone has an oplock on this file. If so - * we must break it before continuing. - */ + if (!lp_share_modes(SNUM(conn))) { + return NT_STATUS_OK; + } - if (!cause_oplock_break(*p_oplock_request, - share_entry->op_type, - access_mask)) { - if (!LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { - *p_all_current_opens_are_level_II = False; - } - continue; - } + /* Now we check the share modes, after any oplock breaks. */ + for(i = 0; i < lck->num_share_modes; i++) { - /* This is an oplock break */ - - DEBUG(5,("open_mode_check: oplock_request = %d, " - "breaking oplock (%x) on file %s, " - "dev = %x, inode = %.0f\n", - *p_oplock_request, share_entry->op_type, - fname, (unsigned int)dev, (double)inode)); - - /* Ensure the reply for the open uses the correct - * sequence number. */ - /* This isn't a real deferred packet as it's response - * will also increment the sequence. - */ - srv_defer_sign_response(get_current_mid()); - - /* Oplock break - unlock to request it. */ - unlock_share_entry(conn, dev, inode); - - opb_ret = request_oplock_break(share_entry); - - /* Now relock. */ - lock_share_entry(conn, dev, inode); - - if (!opb_ret) { - DEBUG(0,("open_mode_check: FAILED when breaking " - "oplock (%x) on file %s, dev = %x, " - "inode = %.0f\n", - old_shares[i].op_type, fname, - (unsigned int)dev, (double)inode)); - SAFE_FREE(old_shares); - set_saved_error_triple(ERRDOS, ERRbadshare, - NT_STATUS_SHARING_VIOLATION); - return -1; - } - - broken_entry = SMB_MALLOC_P(struct share_mode_entry_list); - if (!broken_entry) { - smb_panic("open_mode_check: malloc fail.\n"); - } - broken_entry->entry = *share_entry; - DLIST_ADD(broken_entry_list, broken_entry); - broke_oplock = True; - - } /* end for */ - - if (broke_oplock) { - /* Update the current open table. */ - SAFE_FREE(old_shares); - num_share_modes = get_share_modes(dev, inode, - &old_shares, - &delete_on_close); + if (!is_valid_share_mode_entry(&lck->share_modes[i])) { + continue; } - if (lp_share_modes(SNUM(conn))) { - /* Now we check the share modes, after any oplock breaks. */ - for(i = 0; i < num_share_modes; i++) { - share_mode_entry *share_entry = &old_shares[i]; - - /* someone else has a share lock on it, check to see - * if we can too */ - if (share_conflict(share_entry, access_mask, - share_access)) { - SAFE_FREE(old_shares); - free_broken_entry_list(broken_entry_list); - errno = EACCES; - return -1; - } - } + /* someone else has a share lock on it, check to see if we can + * too */ + if (share_conflict(&lck->share_modes[i], + access_mask, share_access)) { + return NT_STATUS_SHARING_VIOLATION; } - - for(broken_entry = broken_entry_list; broken_entry; - broken_entry = broken_entry->next) { - oplock_contention_count++; - - /* Paranoia check that this is no longer an exlusive entry. */ - for(i = 0; i < num_share_modes; i++) { - share_mode_entry *share_entry = &old_shares[i]; - - if (!(share_modes_identical(&broken_entry->entry, - share_entry) && - EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type))) { - continue; - } - - /* - * This should not happen. The target left this oplock - * as exlusive.... The process *must* be dead.... - */ - - DEBUG(0,("open_mode_check: exlusive oplock left by " - "process %d after break ! For file %s, " - "dev = %x, inode = %.0f. Deleting it to " - "continue...\n", - (int)broken_entry->entry.pid, fname, - (unsigned int)dev, (double)inode)); - - if (process_exists(broken_entry->entry.pid)) { - DEBUG(0,("open_mode_check: Existent process " - "%lu left active oplock.\n", - (unsigned long)broken_entry->entry.pid )); - } - - if (del_share_entry(dev, inode, &broken_entry->entry, - NULL, &delete_on_close) == -1) { - free_broken_entry_list(broken_entry_list); - errno = EACCES; - set_saved_error_triple(ERRDOS, ERRbadshare, - NT_STATUS_SHARING_VIOLATION); - return -1; - } - - /* - * We must reload the share modes after deleting the - * other process's entry. - */ - - SAFE_FREE(old_shares); - num_share_modes = get_share_modes(dev, inode, - &old_shares, - &delete_on_close); - break; - } /* end for paranoia... */ - } /* end for broken_entry */ - free_broken_entry_list(broken_entry_list); - } while(broke_oplock); - - /* - * Refuse to grant an oplock in case the contention limit is - * reached when going through the lock list multiple times. - */ - - if(oplock_contention_count >= lp_oplock_contention_limit(SNUM(conn))) { - *p_oplock_request = 0; - DEBUG(4,("open_mode_check: oplock contention = %d. Not granting oplock.\n", - oplock_contention_count )); } - SAFE_FREE(old_shares); - return num_share_modes; + return NT_STATUS_OK; } -/**************************************************************************** - Delete the record for a handled deferred open entry. -****************************************************************************/ +static BOOL is_delete_request(files_struct *fsp) { + return ((fsp->access_mask == DELETE_ACCESS) && + (fsp->oplock_type == NO_OPLOCK)); +} -static void delete_defered_open_entry_record(connection_struct *conn, - SMB_DEV_T dev, - SMB_INO_T inode) +/* + * 1) No files open at all: Grant whatever the client wants. + * + * 2) Exclusive (or batch) oplock around: If the requested access is a delete + * request, break if the oplock around is a batch oplock. If it's another + * requested access type, break. + * + * 3) Only level2 around: Grant level2 and do nothing else. + */ + +static BOOL delay_for_oplocks(struct share_mode_lock *lck, files_struct *fsp) { - uint16 mid = get_current_mid(); - pid_t mypid = sys_getpid(); - deferred_open_entry *de_array = NULL; - int num_de_entries, i; + int i, num_level2; + struct share_mode_entry *exclusive = NULL; + BOOL delay_it = False; + BOOL have_level2 = False; - if (!lp_defer_sharing_violations()) { - return; + if (is_stat_open(fsp->access_mask)) { + fsp->oplock_type = NO_OPLOCK; + return False; } - num_de_entries = get_deferred_opens(conn, dev, inode, &de_array); - for (i = 0; i < num_de_entries; i++) { - deferred_open_entry *entry = &de_array[i]; - if (entry->pid == mypid && entry->mid == mid && entry->dev == dev && - entry->inode == inode) { + num_level2 = 0; - /* Remove the deferred open entry from the array. */ - delete_deferred_open_entry(entry); - SAFE_FREE(de_array); - return; + if (lck->num_share_modes == 0) { + /* No files open at all: Directly grant whatever the client + * wants. */ + + if (fsp->oplock_type == NO_OPLOCK) { + /* Store a level2 oplock, but don't tell the client */ + fsp->oplock_type = FAKE_LEVEL_II_OPLOCK; + } + return False; + } + + for (i=0; inum_share_modes; i++) { + + if (!is_valid_share_mode_entry(&lck->share_modes[i])) { + continue; + } + + if (EXCLUSIVE_OPLOCK_TYPE(lck->share_modes[i].op_type)) { + SMB_ASSERT(exclusive == NULL); + exclusive = &lck->share_modes[i]; + } + + if (lck->share_modes[i].op_type == LEVEL_II_OPLOCK) { + have_level2 = True; } } - SAFE_FREE(de_array); + + if (exclusive != NULL) { /* Found an exclusive oplock */ + SMB_ASSERT(!have_level2); + delay_it = is_delete_request(fsp) ? + BATCH_OPLOCK_TYPE(exclusive->op_type) : True; + } + + if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { + /* We can at most grant level2 */ + fsp->oplock_type = LEVEL_II_OPLOCK; + } + + if ((fsp->oplock_type == NO_OPLOCK) && have_level2) { + /* Store a level2 oplock, but don't tell the client */ + fsp->oplock_type = FAKE_LEVEL_II_OPLOCK; + } + + if (delay_it) { + DEBUG(10, ("Sending break request to PID %s\n", + procid_str_static(&exclusive->pid))); + exclusive->op_mid = get_current_mid(); + if (!message_send_pid(exclusive->pid, MSG_SMB_BREAK_REQUEST, + exclusive, sizeof(*exclusive), True)) { + DEBUG(3, ("Could not send oplock break message\n")); + } + file_free(fsp); + } + + return delay_it; +} + +static BOOL request_timed_out(struct timeval request_time, + struct timeval timeout) +{ + struct timeval now, end_time; + GetTimeOfDay(&now); + end_time = timeval_sum(&request_time, &timeout); + return (timeval_compare(&end_time, &now) < 0); } /**************************************************************************** Handle the 1 second delay in returning a SHARING_VIOLATION error. ****************************************************************************/ -static void defer_open_sharing_error(connection_struct *conn, - struct timeval *ptv, - const char *fname, - SMB_DEV_T dev, - SMB_INO_T inode) +static void defer_open(struct share_mode_lock *lck, + struct timeval request_time, + struct timeval timeout, + struct deferred_open_record *state) { uint16 mid = get_current_mid(); - pid_t mypid = sys_getpid(); - deferred_open_entry *de_array = NULL; - int num_de_entries, i; - struct dev_inode_bundle dib; + int i; - if (!lp_defer_sharing_violations()) { - return; - } + /* Paranoia check */ - dib.dev = dev; - dib.inode = inode; + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *e = &lck->share_modes[i]; - num_de_entries = get_deferred_opens(conn, dev, inode, &de_array); - for (i = 0; i < num_de_entries; i++) { - deferred_open_entry *entry = &de_array[i]; - if (entry->pid == mypid && entry->mid == mid) { - /* - * Check if a 1 second timeout has expired. - */ - if (usec_time_diff(ptv, &entry->time) > - SHARING_VIOLATION_USEC_WAIT) { - DEBUG(10,("defer_open_sharing_error: Deleting " - "deferred open entry for mid %u, " - "file %s\n", - (unsigned int)mid, fname )); - - /* Expired, return a real error. */ - /* Remove the deferred open entry from the array. */ - - delete_deferred_open_entry(entry); - SAFE_FREE(de_array); - return; - } - /* - * If the timeout hasn't expired yet and we still have - * a sharing violation, just leave the entry in the - * deferred open array alone. We do need to reschedule - * this open call though (with the original created - * time). - */ - DEBUG(10,("defer_open_sharing_error: time [%u.%06u] " - "updating deferred open entry for mid %u, file %s\n", - (unsigned int)entry->time.tv_sec, - (unsigned int)entry->time.tv_usec, - (unsigned int)mid, fname )); - - push_sharing_violation_open_smb_message(&entry->time, - (char *)&dib, - sizeof(dib)); - SAFE_FREE(de_array); - return; + if (!is_deferred_open_entry(e)) { + continue; + } + + if (procid_is_me(&e->pid) && (e->op_mid == mid)) { + DEBUG(0, ("Trying to defer an already deferred " + "request: mid=%d, exiting\n", mid)); + exit_server("exiting"); } } + /* End paranoia check */ + DEBUG(10,("defer_open_sharing_error: time [%u.%06u] adding deferred " - "open entry for mid %u, file %s\n", - (unsigned int)ptv->tv_sec, (unsigned int)ptv->tv_usec, - (unsigned int)mid, fname )); + "open entry for mid %u\n", + (unsigned int)request_time.tv_sec, + (unsigned int)request_time.tv_usec, + (unsigned int)mid)); - if (!push_sharing_violation_open_smb_message(ptv, (char *)&dib, sizeof(dib))) { - SAFE_FREE(de_array); - return; - } - if (!add_deferred_open(mid, ptv, dev, inode, global_oplock_port, fname)) { - remove_sharing_violation_open_smb_message(mid); + if (!push_deferred_smb_message(mid, request_time, timeout, + (char *)state, sizeof(*state))) { + exit_server("push_deferred_smb_message failed\n"); } + add_deferred_open(lck, mid, request_time, state->dev, state->inode); /* * Push the MID of this packet on the signing queue. @@ -888,8 +756,6 @@ static void defer_open_sharing_error(connection_struct *conn, */ srv_defer_sign_response(mid); - - SAFE_FREE(de_array); } /**************************************************************************** @@ -1196,8 +1062,6 @@ files_struct *open_file_ntcreate(connection_struct *conn, BOOL internal_only_open = False; SMB_DEV_T dev = 0; SMB_INO_T inode = 0; - int num_share_modes = 0; - BOOL all_current_opens_are_level_II = False; BOOL fsp_open = False; files_struct *fsp = NULL; mode_t new_unx_mode = (mode_t)0; @@ -1205,8 +1069,11 @@ files_struct *open_file_ntcreate(connection_struct *conn, int info; uint32 existing_dos_attributes = 0; struct pending_message_list *pml = NULL; - uint16 port = 0; uint16 mid = get_current_mid(); + BOOL delayed_for_oplocks = False; + struct timeval request_time = timeval_zero(); + struct share_mode_lock *lck = NULL; + NTSTATUS status; if (conn->printer) { /* @@ -1241,9 +1108,11 @@ files_struct *open_file_ntcreate(connection_struct *conn, } if ((pml = get_open_deferred_message(mid)) != NULL) { - struct dev_inode_bundle dib; + struct deferred_open_record *state = + (struct deferred_open_record *)pml->private_data.data; - memcpy(&dib, pml->private_data.data, sizeof(dib)); + request_time = pml->request_time; + delayed_for_oplocks = state->delayed_for_oplocks; /* There could be a race condition where the dev/inode pair has changed since we deferred the message. If so, just @@ -1255,24 +1124,18 @@ files_struct *open_file_ntcreate(connection_struct *conn, notified of a close and we don't want to trigger another spurious oplock break. */ - if (!file_existed || dib.dev != psbuf->st_dev || - dib.inode != psbuf->st_ino || pml->msg_time.tv_sec || - pml->msg_time.tv_usec) { - /* Ensure we don't reprocess this message. */ - remove_sharing_violation_open_smb_message(mid); - - /* Now remove the deferred open entry under lock. */ - lock_share_entry(conn, dib.dev, dib.inode); - delete_defered_open_entry_record(conn, dib.dev, - dib.inode); - unlock_share_entry(conn, dib.dev, dib.inode); - - set_saved_error_triple(ERRDOS, ERRbadshare, - NT_STATUS_SHARING_VIOLATION); - return NULL; + /* Now remove the deferred open entry under lock. */ + lck = get_share_mode_lock(NULL, state->dev, state->inode, + fname); + if (lck == NULL) { + DEBUG(0, ("could not get share mode lock\n")); + } else { + del_deferred_open_entry(lck, mid); + talloc_destroy(lck); } + /* Ensure we don't reprocess this message. */ - remove_sharing_violation_open_smb_message(mid); + remove_deferred_open_smb_message(mid); } if (!check_name(fname,conn)) { @@ -1285,7 +1148,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, } /* ignore any oplock requests if oplocks are disabled */ - if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break) { + if (!lp_oplocks(SNUM(conn)) || global_client_failed_oplock_break || + IS_VETO_OPLOCK_PATH(conn, fname)) { oplock_request = 0; } @@ -1325,7 +1189,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: FILE_OPEN " "requested for file %s and file " "doesn't exist.\n", fname )); - set_saved_error_triple(ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND); + set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); errno = ENOENT; return NULL; } @@ -1338,7 +1202,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: FILE_OVERWRITE " "requested for file %s and file " "doesn't exist.\n", fname )); - set_saved_error_triple(ERRDOS, ERRbadfile, NT_STATUS_OBJECT_NAME_NOT_FOUND); + set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); errno = ENOENT; return NULL; } @@ -1369,8 +1233,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, break; default: - set_saved_error_triple(ERRDOS, ERRinvalidparam, - NT_STATUS_INVALID_PARAMETER); + set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER); return NULL; } @@ -1447,8 +1310,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, DEBUG(5,("open_file_ntcreate: write access requested for " "file %s on read only %s\n", fname, !CAN_WRITE(conn) ? "share" : "file" )); - set_saved_error_triple(ERRDOS, ERRnoaccess, - NT_STATUS_ACCESS_DENIED); + set_saved_ntstatus(NT_STATUS_ACCESS_DENIED); errno = EACCES; return NULL; } @@ -1458,45 +1320,96 @@ files_struct *open_file_ntcreate(connection_struct *conn, return NULL; } + fsp->dev = psbuf->st_dev; + fsp->inode = psbuf->st_ino; + fsp->share_access = share_access; + fsp->fh->private_options = create_options; + fsp->access_mask = access_mask; + fsp->oplock_type = oplock_request; + + if (timeval_is_zero(&request_time)) { + request_time = fsp->open_time; + } + if (file_existed) { dev = psbuf->st_dev; inode = psbuf->st_ino; - lock_share_entry(conn, dev, inode); - - num_share_modes = open_mode_check(conn, fname, dev, inode, - access_mask, share_access, - create_options, - &oplock_request, - &all_current_opens_are_level_II); - if(num_share_modes == -1) { - - if (!internal_only_open) { - NTSTATUS status; - get_saved_error_triple(NULL, NULL, &status); - if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { - /* Check if this can be done with the - * deny_dos and fcb calls. */ - if (create_options & - (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS| - NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { - files_struct *fsp_dup; - fsp_dup = fcb_or_dos_open(conn, fname, dev, - inode, access_mask, - share_access, - create_options); - - if (fsp_dup) { - unlock_share_entry(conn, dev, inode); - file_free(fsp); - if (pinfo) { - *pinfo = FILE_WAS_OPENED; - } - conn->num_files_open++; - return fsp_dup; - } + lck = get_share_mode_lock(NULL, dev, inode, fname); + + if (lck == NULL) { + DEBUG(0, ("Could not get share mode lock\n")); + set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); + return NULL; + } + + if (delay_for_oplocks(lck, fsp)) { + struct deferred_open_record state; + struct timeval timeout; + + if (delayed_for_oplocks) { + DEBUG(0, ("Trying to delay for oplocks " + "twice\n")); + exit_server("exiting"); + } + + timeout = timeval_set(OPLOCK_BREAK_TIMEOUT*2, 0); + + /* Normally the smbd we asked should respond within + * OPLOCK_BREAK_TIMEOUT seconds regardless of whether + * the client did, give twice the timeout as a safety + * measure here in case the other smbd is stuck + * somewhere else. */ + + state.delayed_for_oplocks = True; + state.dev = dev; + state.inode = inode; + + if (!request_timed_out(request_time, timeout)) { + defer_open(lck, request_time, timeout, + &state); + } + + talloc_free(lck); + return NULL; + } + + status = open_mode_check(conn, fname, lck, + access_mask, share_access, + create_options, &file_existed); + + if (NT_STATUS_EQUAL(status, NT_STATUS_DELETE_PENDING)) { + /* DELETE_PENDING is not deferred for a second */ + set_saved_ntstatus(status); + talloc_free(lck); + file_free(fsp); + return NULL; + } + + if (!NT_STATUS_IS_OK(status)) { + + SMB_ASSERT(NT_STATUS_EQUAL(status, NT_STATUS_SHARING_VIOLATION)); + + /* Check if this can be done with the deny_dos and fcb + * calls. */ + if (create_options & + (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS| + NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { + files_struct *fsp_dup; + fsp_dup = fcb_or_dos_open(conn, fname, dev, + inode, access_mask, + share_access, + create_options); + + if (fsp_dup) { + talloc_free(lck); + file_free(fsp); + if (pinfo) { + *pinfo = FILE_WAS_OPENED; } + conn->num_files_open++; + return fsp_dup; } } @@ -1527,8 +1440,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, if (!fsp_open && errno) { /* Default error. */ - set_saved_error_triple(ERRDOS, ERRnoaccess, - NT_STATUS_ACCESS_DENIED); + set_saved_ntstatus(NT_STATUS_ACCESS_DENIED); } /* @@ -1536,27 +1448,32 @@ files_struct *open_file_ntcreate(connection_struct *conn, * cope with the braindead 1 second delay. */ - if (!internal_only_open) { - NTSTATUS status; - get_saved_error_triple(NULL, NULL, &status); - if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { - /* The fsp->open_time here represents - * the current time of day. */ - defer_open_sharing_error(conn, - &fsp->open_time, - fname, dev, inode); + if (!internal_only_open && + lp_defer_sharing_violations()) { + struct timeval timeout; + struct deferred_open_record state; + + timeout = timeval_set(0, SHARING_VIOLATION_USEC_WAIT); + + state.delayed_for_oplocks = False; + state.dev = dev; + state.inode = inode; + + if (!request_timed_out(request_time, + timeout)) { + defer_open(lck, request_time, timeout, + &state); } } - unlock_share_entry(conn, dev, inode); + talloc_free(lck); if (fsp_open) { fd_close(conn, fsp); /* * We have detected a sharing violation here * so return the correct error code */ - set_saved_error_triple(ERRDOS, ERRbadshare, - NT_STATUS_SHARING_VIOLATION); + set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); } file_free(fsp); return NULL; @@ -1567,23 +1484,28 @@ files_struct *open_file_ntcreate(connection_struct *conn, */ } + SMB_ASSERT(!file_existed || (lck != NULL)); + /* * Ensure we pay attention to default ACLs on directories if required. */ if ((flags2 & O_CREAT) && lp_inherit_acls(SNUM(conn)) && - (def_acl = directory_has_default_acl(conn, parent_dirname(fname)))) { + (def_acl = directory_has_default_acl(conn, + parent_dirname(fname)))) { unx_mode = 0777; } DEBUG(4,("calling open_file with flags=0x%X flags2=0x%X mode=0%o\n", - (unsigned int)flags,(unsigned int)flags2,(unsigned int)unx_mode)); + (unsigned int)flags, (unsigned int)flags2, + (unsigned int)unx_mode)); /* * open_file strips any O_TRUNC flags itself. */ - fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode,access_mask); + fsp_open = open_file(fsp,conn,fname,psbuf,flags|flags2,unx_mode, + access_mask); if (!fsp_open && (flags2 & O_EXCL) && (errno == EEXIST)) { /* @@ -1602,22 +1524,23 @@ files_struct *open_file_ntcreate(connection_struct *conn, } if (!fsp_open) { - if(file_existed) { - unlock_share_entry(conn, dev, inode); + if (lck != NULL) { + talloc_free(lck); } file_free(fsp); return NULL; } - /* - * Deal with the race condition where two smbd's detect the file - * doesn't exist and do the create at the same time. One of them will - * win and set a share mode, the other (ie. this one) should check if - * the requested share mode for this create is allowed. - */ - if (!file_existed) { + /* + * Deal with the race condition where two smbd's detect the + * file doesn't exist and do the create at the same time. One + * of them will win and set a share mode, the other (ie. this + * one) should check if the requested share mode for this + * create is allowed. + */ + /* * Now the file exists and fsp is successfully opened, * fsp->dev and fsp->inode are valid and should replace the @@ -1628,70 +1551,41 @@ files_struct *open_file_ntcreate(connection_struct *conn, dev = fsp->dev; inode = fsp->inode; - lock_share_entry_fsp(fsp); - - num_share_modes = open_mode_check(conn, fname, dev, inode, - access_mask, share_access, - create_options, - &oplock_request, - &all_current_opens_are_level_II); - - if(num_share_modes == -1) { - NTSTATUS status; - get_saved_error_triple(NULL, NULL, &status); - if (NT_STATUS_EQUAL(status,NT_STATUS_SHARING_VIOLATION)) { - /* Check if this can be done with the deny_dos - * and fcb calls. */ - if (create_options & - (NTCREATEX_OPTIONS_PRIVATE_DENY_DOS| - NTCREATEX_OPTIONS_PRIVATE_DENY_FCB)) { - files_struct *fsp_dup; - fsp_dup = fcb_or_dos_open(conn, fname, dev, inode, - access_mask, share_access, - create_options); - if (fsp_dup) { - unlock_share_entry(conn, dev, inode); - fd_close(conn, fsp); - file_free(fsp); - if (pinfo) { - *pinfo = FILE_WAS_OPENED; - } - conn->num_files_open++; - return fsp_dup; - } - } - - /* - * If we're returning a share violation, - * ensure we cope with the braindead 1 second - * delay. - */ - - /* The fsp->open_time here represents the - * current time of day. */ - defer_open_sharing_error(conn, &fsp->open_time, - fname, dev, inode); - } + lck = get_share_mode_lock(NULL, dev, inode, fname); - unlock_share_entry_fsp(fsp); - fd_close(conn,fsp); + if (lck == NULL) { + DEBUG(0, ("Coult not get share mode lock\n")); + fd_close(conn, fsp); file_free(fsp); - /* - * We have detected a sharing violation here, so - * return the correct code. - */ - set_saved_error_triple(ERRDOS, ERRbadshare, - NT_STATUS_SHARING_VIOLATION); + set_saved_ntstatus(NT_STATUS_SHARING_VIOLATION); return NULL; } - /* - * If there are any share modes set then the file *did* - * exist. Ensure we return the correct value for action. - */ + status = open_mode_check(conn, fname, lck, + access_mask, share_access, + create_options, &file_existed); + + if (!NT_STATUS_IS_OK(status)) { + struct deferred_open_record state; - if (num_share_modes > 0) { - file_existed = True; + fd_close(conn, fsp); + file_free(fsp); + + state.delayed_for_oplocks = False; + state.dev = dev; + state.inode = inode; + + /* Do it all over again immediately. In the second + * round we will find that the file existed and handle + * the DELETE_PENDING and FCB cases correctly. No need + * to duplicate the code here. Essentially this is a + * "goto top of this function", but don't tell + * anybody... */ + + defer_open(lck, request_time, timeval_zero(), + &state); + talloc_free(lck); + return NULL; } /* @@ -1699,6 +1593,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, */ } + SMB_ASSERT(lck != NULL); + /* note that we ignore failure for the following. It is basically a hack for NFS, and NFS will never set one of these only read them. Nobody but Samba can ever set a deny @@ -1725,7 +1621,7 @@ files_struct *open_file_ntcreate(connection_struct *conn, */ if ((SMB_VFS_FTRUNCATE(fsp,fsp->fh->fd,0) == -1) || (SMB_VFS_FSTAT(fsp,fsp->fh->fd,psbuf)==-1)) { - unlock_share_entry_fsp(fsp); + talloc_free(lck); fd_close(conn,fsp); file_free(fsp); return NULL; @@ -1761,20 +1657,14 @@ files_struct *open_file_ntcreate(connection_struct *conn, * file structs. */ - if(oplock_request && (num_share_modes == 0) && - !IS_VETO_OPLOCK_PATH(conn,fname) && - set_file_oplock(fsp, oplock_request) ) { - port = global_oplock_port; - } else if (oplock_request && all_current_opens_are_level_II) { - port = global_oplock_port; - oplock_request = LEVEL_II_OPLOCK; - set_file_oplock(fsp, oplock_request); - } else { - port = 0; - oplock_request = 0; + if ((fsp->oplock_type != NO_OPLOCK) && + (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK)) { + if (!set_file_oplock(fsp, fsp->oplock_type)) { + /* Could not get the kernel oplock */ + fsp->oplock_type = NO_OPLOCK; + } } - - set_share_mode(fsp, port, oplock_request); + set_share_mode(lck, fsp, 0, fsp->oplock_type); if (create_options & FILE_DELETE_ON_CLOSE) { uint32 dosattr= existing_dos_attributes; @@ -1788,19 +1678,16 @@ files_struct *open_file_ntcreate(connection_struct *conn, result = can_set_delete_on_close(fsp, True, dosattr); if (!NT_STATUS_IS_OK(result)) { - uint8 u_e_c; - uint32 u_e_code; - BOOL dummy_del_on_close; /* Remember to delete the mode we just added. */ - del_share_mode(fsp, NULL, &dummy_del_on_close); - unlock_share_entry_fsp(fsp); + del_share_mode(lck, fsp); + talloc_free(lck); fd_close(conn,fsp); file_free(fsp); - ntstatus_to_dos(result, &u_e_c, &u_e_code); - set_saved_error_triple(u_e_c, u_e_code, result); + set_saved_ntstatus(result); return NULL; } - set_delete_on_close(fsp, True); + lck->delete_on_close = True; + lck->modified = True; } if (info == FILE_WAS_OVERWRITTEN || info == FILE_WAS_CREATED || @@ -1860,8 +1747,8 @@ files_struct *open_file_ntcreate(connection_struct *conn, /* If this is a successful open, we must remove any deferred open * records. */ - delete_defered_open_entry_record(conn, fsp->dev, fsp->inode); - unlock_share_entry_fsp(fsp); + del_deferred_open_entry(lck, mid); + talloc_free(lck); conn->num_files_open++; @@ -1945,17 +1832,13 @@ files_struct *open_directory(connection_struct *conn, if (is_ntfs_stream_name(fname)) { DEBUG(0,("open_directory: %s is a stream name!\n", fname )); - /* NB. Is the DOS error ERRbadpath or ERRbaddirectory ? */ - set_saved_error_triple(ERRDOS, ERRbadpath, - NT_STATUS_NOT_A_DIRECTORY); + set_saved_ntstatus(NT_STATUS_NOT_A_DIRECTORY); return NULL; } if (dir_existed && !S_ISDIR(psbuf->st_mode)) { DEBUG(0,("open_directory: %s is not a directory !\n", fname )); - /* NB. Is the DOS error ERRbadpath or ERRbaddirectory ? */ - set_saved_error_triple(ERRDOS, ERRbadpath, - NT_STATUS_NOT_A_DIRECTORY); + set_saved_ntstatus(NT_STATUS_NOT_A_DIRECTORY); return NULL; } @@ -1967,8 +1850,7 @@ files_struct *open_directory(connection_struct *conn, DEBUG(5,("open_directory: FILE_OPEN requested " "for directory %s and it doesn't " "exist.\n", fname )); - set_saved_error_triple(ERRDOS, ERRbadfile, - NT_STATUS_OBJECT_NAME_NOT_FOUND); + set_saved_ntstatus(NT_STATUS_OBJECT_NAME_NOT_FOUND); return NULL; } info = FILE_WAS_OPENED; @@ -2008,8 +1890,7 @@ files_struct *open_directory(connection_struct *conn, "0x%x for directory %s\n", (unsigned int)create_disposition, fname)); file_free(fsp); - set_saved_error_triple(ERRDOS, ERRinvalidparam, - NT_STATUS_INVALID_PARAMETER); + set_saved_ntstatus(NT_STATUS_INVALID_PARAMETER); return NULL; } diff --git a/source3/smbd/oplock.c b/source3/smbd/oplock.c index c0c9e989a99..385f998b1ce 100644 --- a/source3/smbd/oplock.c +++ b/source3/smbd/oplock.c @@ -3,6 +3,7 @@ oplock processing Copyright (C) Andrew Tridgell 1992-1998 Copyright (C) Jeremy Allison 1998 - 2001 + 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 @@ -21,25 +22,17 @@ #include "includes.h" -/* Oplock ipc UDP socket. */ -static int oplock_sock = -1; -uint16 global_oplock_port = 0; - /* Current number of oplocks we have outstanding. */ static int32 exclusive_oplocks_open = 0; static int32 level_II_oplocks_open = 0; BOOL global_client_failed_oplock_break = False; -BOOL global_oplock_break = False; extern struct timeval smb_last_time; extern uint32 global_client_caps; -extern struct current_user current_user; extern int smb_read_error; static struct kernel_oplocks *koplocks; -static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, BOOL local); - /**************************************************************************** Get the number of current exclusive oplocks. ****************************************************************************/ @@ -58,9 +51,6 @@ BOOL oplock_message_waiting(fd_set *fds) if (koplocks && koplocks->msg_waiting(fds)) return True; - if (FD_ISSET(oplock_sock, fds)) - return True; - return False; } @@ -75,13 +65,9 @@ BOOL oplock_message_waiting(fd_set *fds) ****************************************************************************/ -BOOL receive_local_message( char *buffer, int buffer_len, int timeout) +void process_kernel_oplocks(void) { - struct sockaddr_in from; - socklen_t fromlen = sizeof(from); - int32 msg_len = 0; fd_set fds; - int selrtn = -1; FD_ZERO(&fds); smb_read_error = 0; @@ -92,110 +78,29 @@ BOOL receive_local_message( char *buffer, int buffer_len, int timeout) * already been eaten. JRA. */ - if (koplocks && koplocks->msg_waiting(&fds)) { - return koplocks->receive_message(&fds, buffer, buffer_len); + if (!koplocks) { + return; } - while (timeout > 0 && selrtn == -1) { - struct timeval to; - int maxfd = oplock_sock; - time_t starttime = time(NULL); - - FD_ZERO(&fds); - maxfd = setup_oplock_select_set(&fds); + while (koplocks->msg_waiting(&fds)) { + files_struct *fsp; + struct kernel_oplock_message msg; - to.tv_sec = timeout / 1000; - to.tv_usec = (timeout % 1000) * 1000; - - DEBUG(5,("receive_local_message: doing select with timeout of %d ms\n", timeout)); - - selrtn = sys_select(maxfd+1,&fds,NULL,NULL,&to); - - if (selrtn == -1 && errno == EINTR) { - - /* could be a kernel oplock interrupt */ - if (koplocks && koplocks->msg_waiting(&fds)) { - return koplocks->receive_message(&fds, buffer, buffer_len); - } + fsp = koplocks->receive_message(&fds); - /* - * Linux 2.0.x seems to have a bug in that - * it can return -1, EINTR with a timeout of zero. - * Make sure we bail out here with a read timeout - * if we got EINTR on a timeout of 1 or less. - */ - - if (timeout <= 1) { - smb_read_error = READ_TIMEOUT; - return False; - } - - /* Not a kernel interrupt - could be a SIGUSR1 message. We must restart. */ - /* We need to decrement the timeout here. */ - timeout -= ((time(NULL) - starttime)*1000); - if (timeout < 0) - timeout = 1; - - DEBUG(5,("receive_local_message: EINTR : new timeout %d ms\n", timeout)); - continue; + if (fsp == NULL) { + DEBUG(3, ("Kernel oplock message announced, but none " + "received\n")); + return; } - /* Check if error */ - if(selrtn == -1) { - /* something is wrong. Maybe the socket is dead? */ - smb_read_error = READ_ERROR; - return False; - } - - /* Did we timeout ? */ - if (selrtn == 0) { - smb_read_error = READ_TIMEOUT; - return False; - } - } - - if (koplocks && koplocks->msg_waiting(&fds)) { - return koplocks->receive_message(&fds, buffer, buffer_len); + msg.dev = fsp->dev; + msg.inode = fsp->inode; + msg.file_id = fsp->file_id; + message_send_pid(pid_to_procid(sys_getpid()), + MSG_SMB_KERNEL_BREAK, + &msg, sizeof(msg), True); } - - if (!FD_ISSET(oplock_sock, &fds)) - return False; - - /* - * From here down we deal with the smbd <--> smbd - * oplock break protocol only. - */ - - /* - * Read a loopback udp message. - */ - msg_len = sys_recvfrom(oplock_sock, &buffer[OPBRK_CMD_HEADER_LEN], - buffer_len - OPBRK_CMD_HEADER_LEN, 0, (struct sockaddr *)&from, &fromlen); - - if(msg_len < 0) { - DEBUG(0,("receive_local_message. Error in recvfrom. (%s).\n",strerror(errno))); - return False; - } - - /* Validate message length. */ - if(msg_len > (buffer_len - OPBRK_CMD_HEADER_LEN)) { - DEBUG(0,("receive_local_message: invalid msg_len (%d) max can be %d\n", msg_len, - buffer_len - OPBRK_CMD_HEADER_LEN)); - return False; - } - - /* Validate message from address (must be localhost). */ - if(from.sin_addr.s_addr != htonl(INADDR_LOOPBACK)) { - DEBUG(0,("receive_local_message: invalid 'from' address \ -(was %lx should be 127.0.0.1)\n", (long)from.sin_addr.s_addr)); - return False; - } - - /* Setup the message header */ - SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,msg_len); - SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,ntohs(from.sin_port)); - - return True; } /**************************************************************************** @@ -229,13 +134,19 @@ tv_sec = %x, tv_usec = %x\n", void release_file_oplock(files_struct *fsp) { - if ((fsp->oplock_type != NO_OPLOCK) && koplocks) + if ((fsp->oplock_type != NO_OPLOCK) && + (fsp->oplock_type != FAKE_LEVEL_II_OPLOCK) && + koplocks) { koplocks->release_oplock(fsp); + } if (fsp->oplock_type == LEVEL_II_OPLOCK) level_II_oplocks_open--; - else if (fsp->oplock_type) + else if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) exclusive_oplocks_open--; + + SMB_ASSERT(exclusive_oplocks_open>=0); + SMB_ASSERT(level_II_oplocks_open>=0); fsp->oplock_type = NO_OPLOCK; fsp->sent_oplock_break = NO_BREAK_SENT; @@ -263,45 +174,58 @@ static void downgrade_file_oplock(files_struct *fsp) to none even if a "break-to-level II" was sent. ****************************************************************************/ -BOOL remove_oplock(files_struct *fsp, BOOL break_to_none) +BOOL remove_oplock(files_struct *fsp) { SMB_DEV_T dev = fsp->dev; SMB_INO_T inode = fsp->inode; - BOOL ret = True; + BOOL ret; + struct share_mode_lock *lck; /* Remove the oplock flag from the sharemode. */ - if (lock_share_entry_fsp(fsp) == False) { - DEBUG(0,("remove_oplock: failed to lock share entry for file %s\n", - fsp->fsp_name )); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); + if (lck == NULL) { + DEBUG(0,("remove_oplock: failed to lock share entry for " + "file %s\n", fsp->fsp_name )); return False; } + ret = remove_share_oplock(lck, fsp); + if (!ret) { + DEBUG(0,("remove_oplock: failed to remove share oplock for " + "file %s fnum %d, dev = %x, inode = %.0f\n", + fsp->fsp_name, fsp->fnum, (unsigned int)dev, + (double)inode)); + } + release_file_oplock(fsp); + talloc_free(lck); + return ret; +} - if (fsp->sent_oplock_break == BREAK_TO_NONE_SENT || break_to_none) { - /* - * Deal with a reply when a break-to-none was sent. - */ - - if(remove_share_oplock(fsp)==False) { - DEBUG(0,("remove_oplock: failed to remove share oplock for file %s fnum %d, \ -dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode)); - ret = False; - } +/* + * Deal with a reply when a break-to-level II was sent. + */ +BOOL downgrade_oplock(files_struct *fsp) +{ + SMB_DEV_T dev = fsp->dev; + SMB_INO_T inode = fsp->inode; + BOOL ret; + struct share_mode_lock *lck; - release_file_oplock(fsp); - } else { - /* - * Deal with a reply when a break-to-level II was sent. - */ - if(downgrade_share_oplock(fsp)==False) { - DEBUG(0,("remove_oplock: failed to downgrade share oplock for file %s fnum %d, \ -dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double)inode)); - ret = False; - } - - downgrade_file_oplock(fsp); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); + if (lck == NULL) { + DEBUG(0,("downgrade_oplock: failed to lock share entry for " + "file %s\n", fsp->fsp_name )); + return False; } - - unlock_share_entry_fsp(fsp); + ret = downgrade_share_oplock(lck, fsp); + if (!ret) { + DEBUG(0,("downgrade_oplock: failed to downgrade share oplock " + "for file %s fnum %d, dev = %x, inode = %.0f\n", + fsp->fsp_name, fsp->fnum, (unsigned int)dev, + (double)inode)); + } + + downgrade_file_oplock(fsp); + talloc_free(lck); return ret; } @@ -313,12 +237,7 @@ dev = %x, inode = %.0f\n", fsp->fsp_name, fsp->fnum, (unsigned int)dev, (double) int setup_oplock_select_set( fd_set *fds) { - int maxfd = oplock_sock; - - if(oplock_sock == -1) - return 0; - - FD_SET(oplock_sock,fds); + int maxfd = 0; if (koplocks && koplocks->notification_fd != -1) { FD_SET(koplocks->notification_fd, fds); @@ -329,197 +248,31 @@ int setup_oplock_select_set( fd_set *fds) } /**************************************************************************** - Process an oplock break message - whether it came from the UDP socket - or from the kernel. + Set up an oplock break message. ****************************************************************************/ -BOOL process_local_message(char *buffer, int buf_size) +static char *new_break_smb_message(TALLOC_CTX *mem_ctx, + files_struct *fsp, uint8_t cmd) { - int32 msg_len; - uint16 from_port; - char *msg_start; - pid_t remotepid; - SMB_DEV_T dev; - SMB_INO_T inode; - unsigned long file_id; - uint16 break_cmd_type; - struct sockaddr_in toaddr; - - msg_len = IVAL(buffer,OPBRK_CMD_LEN_OFFSET); - from_port = SVAL(buffer,OPBRK_CMD_PORT_OFFSET); - - msg_start = &buffer[OPBRK_CMD_HEADER_LEN]; - - DEBUG(5,("process_local_message: Got a message of length %d from port (%d)\n", - msg_len, from_port)); - - /* - * Pull the info out of the requesting packet. - */ - - break_cmd_type = SVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET); - - switch(break_cmd_type) { - case KERNEL_OPLOCK_BREAK_CMD: - if (!koplocks) { - DEBUG(0,("unexpected kernel oplock break!\n")); - break; - } - if (!koplocks->parse_message(msg_start, msg_len, &inode, &dev, &file_id)) { - DEBUG(0,("kernel oplock break parse failure!\n")); - return False; - } - break; - - case OPLOCK_BREAK_CMD: - case LEVEL_II_OPLOCK_BREAK_CMD: - case ASYNC_LEVEL_II_OPLOCK_BREAK_CMD: - - /* Ensure that the msg length is correct. */ - if(msg_len != OPLOCK_BREAK_MSG_LEN) { - DEBUG(0,("process_local_message: incorrect length for OPLOCK_BREAK_CMD (was %d, should be %d).\n", - (int)msg_len, (int)OPLOCK_BREAK_MSG_LEN)); - return False; - } - - memcpy((char *)&remotepid, msg_start+OPLOCK_BREAK_PID_OFFSET,sizeof(remotepid)); - memcpy((char *)&inode, msg_start+OPLOCK_BREAK_INODE_OFFSET,sizeof(inode)); - memcpy((char *)&dev, msg_start+OPLOCK_BREAK_DEV_OFFSET,sizeof(dev)); - memcpy((char *)&file_id, msg_start+OPLOCK_BREAK_FILEID_OFFSET,sizeof(file_id)); - - DEBUG(5,("process_local_message: (%s) oplock break request from \ -pid %d, port %d, dev = %x, inode = %.0f, file_id = %lu\n", - (break_cmd_type == OPLOCK_BREAK_CMD) ? "exclusive" : "level II", - (int)remotepid, from_port, (unsigned int)dev, (double)inode, file_id)); - break; - - case RETRY_DEFERRED_OPEN_CMD: - - /* Request to retry and open that would return SHARING_VIOLATION. */ - if (msg_len != DEFERRED_OPEN_MSG_LEN) { - DEBUG(0,("process_local_message: incorrect length for RETRY_DEFERRED_OPEN_CMD (was %d, should be %d).\n", - (int)msg_len, (int)DEFERRED_OPEN_MSG_LEN)); - return False; - } - { - uint16 mid; - - memcpy((char *)&remotepid, msg_start+DEFERRED_OPEN_PID_OFFSET,sizeof(remotepid)); - memcpy((char *)&inode, msg_start+DEFERRED_OPEN_INODE_OFFSET,sizeof(inode)); - memcpy((char *)&dev, msg_start+DEFERRED_OPEN_DEV_OFFSET,sizeof(dev)); - memcpy((char *)&mid, msg_start+DEFERRED_OPEN_MID_OFFSET,sizeof(mid)); - - DEBUG(5,("process_local_message: RETRY_DEFERRED_OPEN from \ -pid %d, port %d, dev = %x, inode = %.0f, mid = %u\n", - (int)remotepid, from_port, (unsigned int)dev, (double)inode, (unsigned int)mid)); - - schedule_sharing_violation_open_smb_message(mid); - } - return True; - - /* - * Keep this as a debug case - eventually we can remove it. - */ - case 0x8001: - DEBUG(0,("process_local_message: Received unsolicited break \ -reply - dumping info.\n")); - - if(msg_len != OPLOCK_BREAK_MSG_LEN) { - DEBUG(0,("process_local_message: ubr: incorrect length for reply \ -(was %d, should be %d).\n", (int)msg_len, (int)OPLOCK_BREAK_MSG_LEN)); - return False; - } - - memcpy((char *)&inode, msg_start+OPLOCK_BREAK_INODE_OFFSET,sizeof(inode)); - memcpy((char *)&remotepid, msg_start+OPLOCK_BREAK_PID_OFFSET,sizeof(remotepid)); - memcpy((char *)&dev, msg_start+OPLOCK_BREAK_DEV_OFFSET,sizeof(dev)); - memcpy((char *)&file_id, msg_start+OPLOCK_BREAK_FILEID_OFFSET,sizeof(file_id)); + char *result = TALLOC_ARRAY(mem_ctx, char, smb_size + 8*2 + 0); - DEBUG(0,("process_local_message: unsolicited oplock break reply from \ -pid %d, port %d, dev = %x, inode = %.0f, file_id = %lu\n", - (int)remotepid, from_port, (unsigned int)dev, (double)inode, file_id)); - - return False; - - default: - DEBUG(0,("process_local_message: unknown UDP message command code (%x) - ignoring.\n", - (unsigned int)SVAL(msg_start,0))); - return False; - } - - /* - * Now actually process the break request. - */ - - if ((exclusive_oplocks_open == 0) && - (level_II_oplocks_open == 0)) { - /* - * If we have no record of any currently open oplocks, - * it's not an error, as a close command may have - * just been issued on the file that was oplocked. - * Just log a message and return success in this case. - */ - DEBUG(3,("process_local_message: oplock break requested with " - "no outstanding oplocks. Returning success.\n")); - - } else { - if (!oplock_break(dev, inode, file_id, False)) { - DEBUG(0,("process_local_message: oplock break failed.\n")); - return False; - } - } - - /* - * Do the appropriate reply - none in the kernel or async level II - * case. - */ - - if (!((break_cmd_type == OPLOCK_BREAK_CMD) || - (break_cmd_type == LEVEL_II_OPLOCK_BREAK_CMD))) { - return True; - } - - /* Send the message back after OR'ing in the 'REPLY' bit. */ - SSVAL(msg_start,OPBRK_MESSAGE_CMD_OFFSET,break_cmd_type | CMD_REPLY); - - memset((char *)&toaddr,'\0',sizeof(toaddr)); - toaddr.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - toaddr.sin_port = htons(from_port); - toaddr.sin_family = AF_INET; - - if(sys_sendto( oplock_sock, msg_start, OPLOCK_BREAK_MSG_LEN, 0, - (struct sockaddr *)&toaddr, sizeof(toaddr)) < 0) { - DEBUG(0,("process_local_message: sendto process %d failed. " - "Errno was %s\n", (int)remotepid, strerror(errno))); - return False; + if (result == NULL) { + DEBUG(0, ("talloc failed\n")); + return NULL; } - DEBUG(5,("process_local_message: oplock break reply sent to pid %d, " - "port %d, for file dev = %x, inode = %.0f, file_id = %lu\n", - (int)remotepid, from_port, (unsigned int)dev, - (double)inode, file_id)); - - return True; -} - -/**************************************************************************** - Set up an oplock break message. -****************************************************************************/ - -static void prepare_break_message(char *outbuf, files_struct *fsp, BOOL level2) -{ - memset(outbuf,'\0',smb_size); - set_message(outbuf,8,0,True); - - SCVAL(outbuf,smb_com,SMBlockingX); - SSVAL(outbuf,smb_tid,fsp->conn->cnum); - SSVAL(outbuf,smb_pid,0xFFFF); - SSVAL(outbuf,smb_uid,0); - SSVAL(outbuf,smb_mid,0xFFFF); - SCVAL(outbuf,smb_vwv0,0xFF); - SSVAL(outbuf,smb_vwv2,fsp->fnum); - SCVAL(outbuf,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE); - SCVAL(outbuf,smb_vwv3+1,level2 ? OPLOCKLEVEL_II : OPLOCKLEVEL_NONE); + memset(result,'\0',smb_size); + set_message(result,8,0,True); + SCVAL(result,smb_com,SMBlockingX); + SSVAL(result,smb_tid,fsp->conn->cnum); + SSVAL(result,smb_pid,0xFFFF); + SSVAL(result,smb_uid,0); + SSVAL(result,smb_mid,0xFFFF); + SCVAL(result,smb_vwv0,0xFF); + SSVAL(result,smb_vwv2,fsp->fnum); + SCVAL(result,smb_vwv3,LOCKING_ANDX_OPLOCK_RELEASE); + SCVAL(result,smb_vwv3+1,cmd); + return result; } /**************************************************************************** @@ -602,639 +355,266 @@ static files_struct *initial_break_processing(SMB_DEV_T dev, SMB_INO_T inode, un return fsp; } -/**************************************************************************** - Process a level II oplock break directly. - We must call this function with the share mode entry locked. -****************************************************************************/ - -static BOOL oplock_break_level2(files_struct *fsp, BOOL local_request) +static void oplock_timeout_handler(struct timed_event *te, + const struct timeval *now, + void *private_data) { - char outbuf[128]; - SMB_DEV_T dev = fsp->dev; - SMB_INO_T inode = fsp->inode; - - /* - * We can have a level II oplock even if the client is not - * level II oplock aware. In this case just remove the - * flags and don't send the break-to-none message to - * the client. - */ - - if (global_client_caps & CAP_LEVEL_II_OPLOCKS) { - BOOL sign_state; - - /* - * If we are sending an oplock break due to an SMB sent - * by our own client we ensure that we wait at leat - * lp_oplock_break_wait_time() milliseconds before sending - * the packet. Sending the packet sooner can break Win9x - * and has reported to cause problems on NT. JRA. - */ - - if (local_request) { - wait_before_sending_break(); - } - - /* Prepare the SMBlockingX message. */ - prepare_break_message( outbuf, fsp, False); - - /* Save the server smb signing state. */ - sign_state = srv_oplock_set_signing(False); - - show_msg(outbuf); - if (!send_smb(smbd_server_fd(), outbuf)) - exit_server("oplock_break_level2: send_smb failed."); + files_struct *fsp = private_data; - /* Restore the sign state to what it was. */ - srv_oplock_set_signing(sign_state); - } - - /* - * Now we must update the shared memory structure to tell - * everyone else we no longer have a level II oplock on - * this open file. We must call this function with the share mode - * entry locked so we can change the entry directly. - */ - - if(remove_share_oplock(fsp)==False) { - DEBUG(0,("oplock_break_level2: unable to remove level II oplock for file %s\n", fsp->fsp_name )); - } - - release_file_oplock(fsp); - - if(level_II_oplocks_open < 0) { - DEBUG(0,("oplock_break_level2: level_II_oplocks_open < 0 (%d). PANIC ERROR\n", - level_II_oplocks_open)); - abort(); - } - - if( DEBUGLVL( 3 ) ) { - dbgtext( "oplock_break_level2: returning success for " ); - dbgtext( "dev = %x, inode = %.0f, file_id = %lu\n", (unsigned int)dev, (double)inode, fsp->file_id ); - dbgtext( "Current level II oplocks_open = %d\n", level_II_oplocks_open ); - } - - return True; + DEBUG(0, ("Oplock break failed -- replying anyway\n")); + global_client_failed_oplock_break = True; + remove_oplock(fsp); + reply_to_oplock_break_requests(fsp); } -/**************************************************************************** - Process an oplock break directly. - This is always called with the share mode lock *NOT* held. -****************************************************************************/ - -static BOOL oplock_break(SMB_DEV_T dev, SMB_INO_T inode, unsigned long file_id, BOOL local_request) +static void process_oplock_break_message(int msg_type, struct process_id src, + void *buf, size_t len) { - char *inbuf = NULL; - char *saved_inbuf = NULL; - char *outbuf = NULL; - char *saved_outbuf = NULL; - files_struct *fsp = NULL; - time_t start_time; - BOOL shutdown_server = False; - BOOL oplock_timeout = False; + struct share_mode_entry *msg = buf; + files_struct *fsp; + char *break_msg; + BOOL break_to_level2 = False; BOOL sign_state; - connection_struct *saved_user_conn; - connection_struct *saved_fsp_conn; - int saved_vuid; - pstring saved_dir; - int timeout = (OPLOCK_BREAK_TIMEOUT * 1000); - pstring file_name; - BOOL using_levelII; - - if((fsp = initial_break_processing(dev, inode, file_id)) == NULL) - return True; - /* - * Deal with a level II oplock going break to none separately. - */ - - if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { - BOOL ret; - /* We must always call oplock_break_level2() with - the share mode entry locked. */ - if (lock_share_entry_fsp(fsp) == False) { - DEBUG(0,("oplock_break: unable to lock share entry for file %s\n", fsp->fsp_name )); - return False; - } - ret = oplock_break_level2(fsp, local_request); - unlock_share_entry_fsp(fsp); - return ret; + if (buf == NULL) { + DEBUG(0, ("Got NULL buffer\n")); + return; } - /* Mark the oplock break as sent - we don't want to send twice! */ - if (fsp->sent_oplock_break) { - if( DEBUGLVL( 0 ) ) { - dbgtext( "oplock_break: ERROR: oplock_break already sent for " ); - dbgtext( "file %s ", fsp->fsp_name); - dbgtext( "(dev = %x, inode = %.0f, file_id = %lu)\n", (unsigned int)dev, (double)inode, fsp->file_id ); - } - - /* - * We have to fail the open here as we cannot send another oplock break on - * this file whilst we are awaiting a response from the client - neither - * can we allow another open to succeed while we are waiting for the client. - */ - return False; + if (len != sizeof(*msg)) { + DEBUG(0, ("Got invalid msg len %d\n", (int)len)); + return; } - if(global_oplock_break) { - DEBUG(0,("ABORT : ABORT : recursion in oplock_break !!!!!\n")); - abort(); - } + DEBUG(10, ("Got oplock break message from pid %d: %d/%d/%d\n", + (int)procid_to_pid(&src), (int)msg->dev, (int)msg->inode, + (int)msg->share_file_id)); - /* - * Now comes the horrid part. We must send an oplock break to the client, - * and then process incoming messages until we get a close or oplock release. - * At this point we know we need a new inbuf/outbuf buffer pair. - * We cannot use these staticaly as we may recurse into here due to - * messages crossing on the wire. - */ + fsp = initial_break_processing(msg->dev, msg->inode, + msg->share_file_id); - if((inbuf = NewInBuffer(&saved_inbuf))==NULL) { - DEBUG(0,("oplock_break: malloc fail for input buffer.\n")); - return False; + if (fsp == NULL) { + /* We hit race here. Break messages are sent, and before we + * get to process this message, we have closed the file. Reply + * with 'ok, oplock broken' */ + DEBUG(3, ("Did not find fsp\n")); + message_send_pid(src, MSG_SMB_BREAK_RESPONSE, + msg, sizeof(*msg), True); + return; } - if((outbuf = NewOutBuffer(&saved_outbuf))==NULL) { - DEBUG(0,("oplock_break: malloc fail for output buffer.\n")); - /* Free must be done before set.. */ - free_InBuffer(inbuf); - set_InBuffer(saved_inbuf); - return False; + if (fsp->sent_oplock_break != NO_BREAK_SENT) { + /* Remember we have to inform the requesting PID when the + * client replies */ + msg->pid = src; + ADD_TO_ARRAY(NULL, struct share_mode_entry, *msg, + &fsp->pending_break_messages, + &fsp->num_pending_break_messages); + return; } - /* - * If we are sending an oplock break due to an SMB sent - * by our own client we ensure that we wait at leat - * lp_oplock_break_wait_time() milliseconds before sending - * the packet. Sending the packet sooner can break Win9x - * and has reported to cause problems on NT. JRA. - */ - - if (local_request) { - wait_before_sending_break(); + if (EXCLUSIVE_OPLOCK_TYPE(msg->op_type) && + !EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { + DEBUG(3, ("Already downgraded oplock on %.0f/%.0f: %s\n", + (double)fsp->dev, (double)fsp->inode, + fsp->fsp_name)); + message_send_pid(src, MSG_SMB_BREAK_RESPONSE, + msg, sizeof(*msg), True); + return; } - /* Prepare the SMBlockingX message. */ + if ((msg_type == MSG_SMB_BREAK_REQUEST) && + (global_client_caps & CAP_LEVEL_II_OPLOCKS) && + !koplocks && /* NOTE: we force levelII off for kernel oplocks - + * this will change when it is supported */ + lp_level2_oplocks(SNUM(fsp->conn))) { + break_to_level2 = True; + } - if ((global_client_caps & CAP_LEVEL_II_OPLOCKS) && - !koplocks && /* NOTE: we force levelII off for kernel oplocks - this will change when it is supported */ - lp_level2_oplocks(SNUM(fsp->conn))) { - using_levelII = True; - } else { - using_levelII = False; + break_msg = new_break_smb_message(NULL, fsp, break_to_level2 ? + OPLOCKLEVEL_II : OPLOCKLEVEL_NONE); + if (break_msg == NULL) { + exit_server("Could not talloc break_msg\n"); } - prepare_break_message( outbuf, fsp, using_levelII); - /* Remember if we just sent a break to level II on this file. */ - fsp->sent_oplock_break = using_levelII? LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT; + /* Need to wait before sending a break message to a file of our own */ + if (procid_to_pid(&src) == sys_getpid()) { + wait_before_sending_break(); + } /* Save the server smb signing state. */ sign_state = srv_oplock_set_signing(False); - show_msg(outbuf); - if (!send_smb(smbd_server_fd(), outbuf)) { - srv_oplock_set_signing(sign_state); + show_msg(break_msg); + if (!send_smb(smbd_server_fd(), break_msg)) { exit_server("oplock_break: send_smb failed."); } /* Restore the sign state to what it was. */ srv_oplock_set_signing(sign_state); - /* We need this in case a readraw crosses on the wire. */ - global_oplock_break = True; - - /* Process incoming messages. */ - - /* - * JRA - If we don't get a break from the client in OPLOCK_BREAK_TIMEOUT - * seconds we should just die.... - */ - - start_time = time(NULL); + talloc_free(break_msg); - /* - * Save the information we need to re-become the - * user, then unbecome the user whilst we're doing this. - */ - saved_user_conn = current_user.conn; - saved_vuid = current_user.vuid; - saved_fsp_conn = fsp->conn; - /* - * Initialize saved_dir to something sensible: vfs_GetWd may not work well - * for root: the directory may be NFS-mounted and exported with root_squash - * (so has no root access). - */ - pstrcpy(saved_dir,saved_fsp_conn->connectpath); - vfs_GetWd(saved_fsp_conn,saved_dir); - /* Save the chain fnum. */ - file_chain_save(); - - pstrcpy(file_name, fsp->fsp_name); - - change_to_root_user(); - - /* - * From Charles Hoch . If the break processing - * code closes the file (as it often does), then the fsp pointer here - * points to free()'d memory. We *must* revalidate fsp each time - * around the loop. With async I/O, write calls may steal the global InBuffer, - * so ensure we're using the correct one each time around the loop. - */ - - while((fsp = initial_break_processing(dev, inode, file_id)) && - OPEN_FSP(fsp) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - - inbuf = get_InBuffer(); - outbuf = get_OutBuffer(); - - if(receive_smb(smbd_server_fd(),inbuf, timeout) == False) { - /* - * Die if we got an error. - */ - - if (smb_read_error == READ_EOF) { - DEBUG( 0, ( "oplock_break: end of file from client\n" ) ); - shutdown_server = True; - } else if (smb_read_error == READ_ERROR) { - DEBUG( 0, ("oplock_break: receive_smb error (%s)\n", strerror(errno)) ); - shutdown_server = True; - } else if (smb_read_error == READ_BAD_SIG) { - DEBUG( 0, ("oplock_break: bad signature from client\n" )); - shutdown_server = True; - } else if (smb_read_error == READ_TIMEOUT) { - DEBUG( 0, ( "oplock_break: receive_smb timed out after %d seconds.\n", OPLOCK_BREAK_TIMEOUT ) ); - oplock_timeout = True; - } - - DEBUGADD( 0, ( "oplock_break failed for file %s ", file_name ) ); - DEBUGADD( 0, ( "(dev = %x, inode = %.0f, file_id = %lu).\n", - (unsigned int)dev, (double)inode, file_id)); + if (msg_type == MSG_SMB_BREAK_REQUEST) { + fsp->sent_oplock_break = break_to_level2 ? + LEVEL_II_BREAK_SENT:BREAK_TO_NONE_SENT; + } else { + /* Async level2 request, don't send a reply */ + fsp->sent_oplock_break = ASYNC_LEVEL_II_BREAK_SENT; + } + msg->pid = src; + ADD_TO_ARRAY(NULL, struct share_mode_entry, *msg, + &fsp->pending_break_messages, + &fsp->num_pending_break_messages); - break; - } + if (fsp->oplock_timeout != NULL) { + DEBUG(0, ("Logic problem -- have an oplock event hanging " + "around\n")); + } - /* - * There are certain SMB requests that we shouldn't allow - * to recurse. opens, renames and deletes are the obvious - * ones. This is handled in the switch_message() function. - * If global_oplock_break is set they will push the packet onto - * the pending smb queue and return -1 (no reply). - * JRA. - */ + fsp->oplock_timeout = + add_timed_event(NULL, + timeval_current_ofs(OPLOCK_BREAK_TIMEOUT, 0), + "oplock_timeout_handler", + oplock_timeout_handler, fsp); - process_smb(inbuf, outbuf); + if (fsp->oplock_timeout == NULL) { + DEBUG(0, ("Could not add oplock timeout handler\n")); + } +} - /* - * Die if we go over the time limit. - */ +static void process_kernel_oplock_break(int msg_type, struct process_id src, + void *buf, size_t len) +{ + struct kernel_oplock_message *msg = buf; + files_struct *fsp; + char *break_msg; + BOOL sign_state; - if((time(NULL) - start_time) > OPLOCK_BREAK_TIMEOUT) { - if( DEBUGLVL( 0 ) ) { - dbgtext( "oplock_break: no break received from client " ); - dbgtext( "within %d seconds.\n", OPLOCK_BREAK_TIMEOUT ); - dbgtext( "oplock_break failed for file %s ", fsp->fsp_name ); - dbgtext( "(dev = %x, inode = %.0f, file_id = %lu).\n", - (unsigned int)dev, (double)inode, file_id ); - } - oplock_timeout = True; - break; - } + if (buf == NULL) { + DEBUG(0, ("Got NULL buffer\n")); + return; } - /* - * Go back to being the user who requested the oplock - * break. - */ - if((saved_user_conn != NULL) && (saved_vuid != UID_FIELD_INVALID) && !change_to_user(saved_user_conn, saved_vuid)) { - DEBUG( 0, ( "oplock_break: unable to re-become user!" ) ); - DEBUGADD( 0, ( "Shutting down server\n" ) ); - close(oplock_sock); - exit_server("unable to re-become user"); + if (len != sizeof(*msg)) { + DEBUG(0, ("Got invalid msg len %d\n", (int)len)); + return; } - /* Including the directory. */ - vfs_ChDir(saved_fsp_conn,saved_dir); - - /* Restore the chain fnum. */ - file_chain_restore(); + DEBUG(10, ("Got kernel oplock break message from pid %d: %d/%d/%d\n", + (int)procid_to_pid(&src), (int)msg->dev, (int)msg->inode, + (int)msg->file_id)); - /* Free the buffers we've been using to recurse. */ - /* Free must be done before set.. */ - free_InBuffer(inbuf); - free_OutBuffer(outbuf); + fsp = initial_break_processing(msg->dev, msg->inode, msg->file_id); - /* Restore the global In/Out buffers. */ - set_InBuffer(saved_inbuf); - set_OutBuffer(saved_outbuf); - - /* We need this in case a readraw crossed on the wire. */ - if(global_oplock_break) - global_oplock_break = False; - - /* - * If the client timed out then clear the oplock (or go to level II) - * and continue. This seems to be what NT does and is better than dropping - * the connection. - */ - - if(oplock_timeout && (fsp = initial_break_processing(dev, inode, file_id)) && - OPEN_FSP(fsp) && EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - DEBUG(0,("oplock_break: client failure in oplock break in file %s\n", fsp->fsp_name)); - remove_oplock(fsp,True); -#if FASCIST_OPLOCK_BACKOFF - global_client_failed_oplock_break = True; /* Never grant this client an oplock again. */ -#endif + if (fsp == NULL) { + DEBUG(3, ("Got a kernel oplock break message for a file " + "I don't know about\n")); + return; } - /* - * If the client had an error we must die. - */ - - if(shutdown_server) { - DEBUG( 0, ( "oplock_break: client failure in break - " ) ); - DEBUGADD( 0, ( "shutting down this smbd.\n" ) ); - close(oplock_sock); - exit_server("oplock break failure"); + if (fsp->sent_oplock_break != NO_BREAK_SENT) { + /* This is ok, kernel oplocks come in completely async */ + DEBUG(3, ("Got a kernel oplock request while waiting for a " + "break reply\n")); + return; } - /* Santity check - remove this later. JRA */ - if(exclusive_oplocks_open < 0) { - DEBUG(0,("oplock_break: exclusive_oplocks_open < 0 (%d). PANIC ERROR\n", exclusive_oplocks_open)); - abort(); + break_msg = new_break_smb_message(NULL, fsp, OPLOCKLEVEL_NONE); + if (break_msg == NULL) { + exit_server("Could not talloc break_msg\n"); } - /* We know we have no saved errors here. */ - set_saved_error_triple(0, 0, NT_STATUS_OK); + /* Save the server smb signing state. */ + sign_state = srv_oplock_set_signing(False); - if( DEBUGLVL( 3 ) ) { - dbgtext( "oplock_break: returning success for " ); - dbgtext( "dev = %x, inode = %.0f, file_id = %lu\n", (unsigned int)dev, (double)inode, file_id ); - dbgtext( "Current exclusive_oplocks_open = %d\n", exclusive_oplocks_open ); + show_msg(break_msg); + if (!send_smb(smbd_server_fd(), break_msg)) { + exit_server("oplock_break: send_smb failed."); } - return True; -} - -/**************************************************************************** - Send an oplock break message to another smbd process. If the oplock is held - by the local smbd then call the oplock break function directly. - This function is called with no share locks held. -****************************************************************************/ + /* Restore the sign state to what it was. */ + srv_oplock_set_signing(sign_state); -BOOL request_oplock_break(share_mode_entry *share_entry) -{ - char op_break_msg[OPLOCK_BREAK_MSG_LEN]; - struct sockaddr_in addr_out; - pid_t pid = sys_getpid(); - time_t start_time; - int time_left; - SMB_DEV_T dev = share_entry->dev; - SMB_INO_T inode = share_entry->inode; - unsigned long file_id = share_entry->share_file_id; - uint16 break_cmd_type; - - if(pid == share_entry->pid) { - /* We are breaking our own oplock, make sure it's us. */ - if(share_entry->op_port != global_oplock_port) { - DEBUG(0,("request_oplock_break: corrupt share mode entry - pid = %d, port = %d \ -should be %d\n", (int)pid, share_entry->op_port, global_oplock_port)); - return False; - } + talloc_free(break_msg); - DEBUG(5,("request_oplock_break: breaking our own oplock\n")); + fsp->sent_oplock_break = BREAK_TO_NONE_SENT; +} -#if 1 /* JRA PARANOIA TEST.... */ - { - files_struct *fsp = file_find_dif(dev, inode, file_id); - if (!fsp) { - DEBUG(0,("request_oplock_break: PANIC : breaking our own oplock requested for \ -dev = %x, inode = %.0f, file_id = %lu and no fsp found !\n", - (unsigned int)dev, (double)inode, file_id )); - smb_panic("request_oplock_break: no fsp found for our own oplock\n"); - } - } -#endif /* END JRA PARANOIA TEST... */ +void reply_to_oplock_break_requests(files_struct *fsp) +{ + int i; - /* Call oplock break direct. */ - return oplock_break(dev, inode, file_id, True); + for (i=0; inum_pending_break_messages; i++) { + struct share_mode_entry *msg = &fsp->pending_break_messages[i]; + message_send_pid(msg->pid, MSG_SMB_BREAK_RESPONSE, + msg, sizeof(*msg), True); } - /* We need to send a OPLOCK_BREAK_CMD message to the port in the share mode entry. */ - - if (LEVEL_II_OPLOCK_TYPE(share_entry->op_type)) { - break_cmd_type = LEVEL_II_OPLOCK_BREAK_CMD; - } else { - break_cmd_type = OPLOCK_BREAK_CMD; + SAFE_FREE(fsp->pending_break_messages); + fsp->num_pending_break_messages = 0; + if (fsp->oplock_timeout != NULL) { + talloc_free(fsp->oplock_timeout); + fsp->oplock_timeout = NULL; } + return; +} - SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,break_cmd_type); - memcpy(op_break_msg+OPLOCK_BREAK_PID_OFFSET,(char *)&pid,sizeof(pid)); - memcpy(op_break_msg+OPLOCK_BREAK_DEV_OFFSET,(char *)&dev,sizeof(dev)); - memcpy(op_break_msg+OPLOCK_BREAK_INODE_OFFSET,(char *)&inode,sizeof(inode)); - memcpy(op_break_msg+OPLOCK_BREAK_FILEID_OFFSET,(char *)&file_id,sizeof(file_id)); - - /* Set the address and port. */ - memset((char *)&addr_out,'\0',sizeof(addr_out)); - addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr_out.sin_port = htons( share_entry->op_port ); - addr_out.sin_family = AF_INET; - - if( DEBUGLVL( 3 ) ) { - dbgtext( "request_oplock_break: sending a synchronous oplock break message to " ); - dbgtext( "pid %d on port %d ", (int)share_entry->pid, share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", - (unsigned int)dev, (double)inode, file_id ); - } +static void process_oplock_break_response(int msg_type, struct process_id src, + void *buf, size_t len) +{ + struct share_mode_entry *msg = buf; - if(sys_sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, - (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) { - if( DEBUGLVL( 0 ) ) { - dbgtext( "request_oplock_break: failed when sending a oplock " ); - dbgtext( "break message to pid %d ", (int)share_entry->pid ); - dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", - (unsigned int)dev, (double)inode, file_id ); - dbgtext( "Error was %s\n", strerror(errno) ); - } - return False; + if (buf == NULL) { + DEBUG(0, ("Got NULL buffer\n")); + return; } - /* - * Now we must await the oplock broken message coming back - * from the target smbd process. Timeout if it fails to - * return in (OPLOCK_BREAK_TIMEOUT + OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR) seconds. - * While we get messages that aren't ours, loop. - */ - - start_time = time(NULL); - time_left = OPLOCK_BREAK_TIMEOUT+OPLOCK_BREAK_TIMEOUT_FUDGEFACTOR; - - while(time_left >= 0) { - char op_break_reply[OPBRK_CMD_HEADER_LEN+OPLOCK_BREAK_MSG_LEN]; - uint16 reply_from_port; - char *reply_msg_start; - - if(receive_local_message(op_break_reply, sizeof(op_break_reply), - time_left ? time_left * 1000 : 1) == False) { - if(smb_read_error == READ_TIMEOUT) { - if( DEBUGLVL( 0 ) ) { - dbgtext( "request_oplock_break: no response received to oplock " ); - dbgtext( "break request to pid %d ", (int)share_entry->pid ); - dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", - (unsigned int)dev, (double)inode, file_id ); - } - - /* - * This is a hack to make handling of failing clients more robust. - * If a oplock break response message is not received in the timeout - * period we may assume that the smbd servicing that client holding - * the oplock has died and the client changes were lost anyway, so - * we should continue to try and open the file. - */ - break; - } else { - if( DEBUGLVL( 0 ) ) { - dbgtext( "request_oplock_break: error in response received " ); - dbgtext( "to oplock break request to pid %d ", (int)share_entry->pid ); - dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", - (unsigned int)dev, (double)inode, file_id ); - dbgtext( "Error was (%s).\n", strerror(errno) ); - } - } - return False; - } - - reply_from_port = SVAL(op_break_reply,OPBRK_CMD_PORT_OFFSET); - reply_msg_start = &op_break_reply[OPBRK_CMD_HEADER_LEN]; - - /* - * Test to see if this is the reply we are awaiting (ie. the one we sent with the CMD_REPLY flag OR'ed in). - */ - if((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & CMD_REPLY) && - ((SVAL(reply_msg_start,OPBRK_MESSAGE_CMD_OFFSET) & ~CMD_REPLY) == break_cmd_type) && - (reply_from_port == share_entry->op_port) && - (memcmp(&reply_msg_start[OPLOCK_BREAK_PID_OFFSET], &op_break_msg[OPLOCK_BREAK_PID_OFFSET], - OPLOCK_BREAK_MSG_LEN - OPLOCK_BREAK_PID_OFFSET) == 0)) { - - /* - * This is the reply we've been waiting for. - */ - break; - } else { - /* - * This is another message - a break request. - * Note that both kernel oplock break requests - * and UDP inter-smbd oplock break requests will - * be processed here. - * - * Process it to prevent potential deadlock. - * Note that the code in switch_message() prevents - * us from recursing into here as any SMB requests - * we might process that would cause another oplock - * break request to be made will be queued. - * JRA. - */ - - process_local_message(op_break_reply, sizeof(op_break_reply)); - } - - time_left -= (time(NULL) - start_time); + if (len != sizeof(*msg)) { + DEBUG(0, ("Got invalid msg len %d\n", (int)len)); + return; } - DEBUG(3,("request_oplock_break: broke oplock.\n")); + DEBUG(10, ("Got oplock break response from pid %d: %d/%d/%d mid %d\n", + (int)procid_to_pid(&src), (int)msg->dev, (int)msg->inode, + (int)msg->share_file_id, (int)msg->op_mid)); - return True; + /* Here's the hack from open.c, store the mid in the 'port' field */ + schedule_deferred_open_smb_message(msg->op_mid); } -/**************************************************************************** - Attempt to break an oplock on a file (if oplocked). - Returns True if the file was closed as a result of - the oplock break, False otherwise. - Used as a last ditch attempt to free a space in the - file table when we have run out. -****************************************************************************/ - -BOOL attempt_close_oplocked_file(files_struct *fsp) +static void process_open_retry_message(int msg_type, struct process_id src, + void *buf, size_t len) { - DEBUG(5,("attempt_close_oplocked_file: checking file %s.\n", fsp->fsp_name)); - - if (EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type) && !fsp->sent_oplock_break && (fsp->fh->fd != -1)) { - /* Try and break the oplock. */ - if (oplock_break(fsp->dev, fsp->inode, fsp->file_id, True)) { - if(file_find_fsp(fsp) == NULL) /* Did the oplock break close the file ? */ - return True; - } + struct share_mode_entry *msg = buf; + + if (buf == NULL) { + DEBUG(0, ("Got NULL buffer\n")); + return; } - return False; -} - -/**************************************************************************** - Send an asynchronous oplock break message to another smbd process. -****************************************************************************/ - -static BOOL request_remote_level2_async_oplock_break(share_mode_entry *share_entry) -{ - char op_break_msg[OPLOCK_BREAK_MSG_LEN]; - struct sockaddr_in addr_out; - pid_t pid = sys_getpid(); - SMB_DEV_T dev = share_entry->dev; - SMB_INO_T inode = share_entry->inode; - unsigned long file_id = share_entry->share_file_id; - - /* We need to send a ASYNC_LEVEL_II_OPLOCK_BREAK_CMD message to the port in the share mode entry. */ - - SSVAL(op_break_msg,OPBRK_MESSAGE_CMD_OFFSET,ASYNC_LEVEL_II_OPLOCK_BREAK_CMD); - memcpy(op_break_msg+OPLOCK_BREAK_PID_OFFSET,(char *)&pid,sizeof(pid)); - memcpy(op_break_msg+OPLOCK_BREAK_DEV_OFFSET,(char *)&dev,sizeof(dev)); - memcpy(op_break_msg+OPLOCK_BREAK_INODE_OFFSET,(char *)&inode,sizeof(inode)); - memcpy(op_break_msg+OPLOCK_BREAK_FILEID_OFFSET,(char *)&file_id,sizeof(file_id)); - - /* Set the address and port. */ - memset((char *)&addr_out,'\0',sizeof(addr_out)); - addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr_out.sin_port = htons( share_entry->op_port ); - addr_out.sin_family = AF_INET; - - if( DEBUGLVL( 3 ) ) { - dbgtext( "request_remote_level2_async_oplock_break: sending an asynchronous oplock break message to "); - dbgtext( "pid %d on port %d ", (int)share_entry->pid, share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", - (unsigned int)dev, (double)inode, file_id ); + if (len != sizeof(*msg)) { + DEBUG(0, ("Got invalid msg len %d\n", (int)len)); + return; } - if(sys_sendto(oplock_sock,op_break_msg,OPLOCK_BREAK_MSG_LEN,0, - (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) { - if( DEBUGLVL( 0 ) ) { - dbgtext( "request_remote_level2_async_oplock_break: failed when sending a oplock " ); - dbgtext( "break message to pid %d ", (int)share_entry->pid ); - dbgtext( "on port %d ", share_entry->op_port ); - dbgtext( "for dev = %x, inode = %.0f, file_id = %lu\n", - (unsigned int)dev, (double)inode, file_id ); - dbgtext( "Error was %s\n", strerror(errno) ); - } - return False; - } + DEBUG(10, ("Got open retry msg from pid %d: %d/%d mid %d\n", + (int)procid_to_pid(&src), (int)msg->dev, (int)msg->inode, + (int)msg->op_mid)); - DEBUG(3,("request_remote_level2_async_oplock_break: sent async break message to level II entry.\n")); - return True; + schedule_deferred_open_smb_message(msg->op_mid); } /**************************************************************************** This function is called on any file modification or lock request. If a file - is level 2 oplocked then it must tell all other level 2 holders to break to none. + is level 2 oplocked then it must tell all other level 2 holders to break to + none. ****************************************************************************/ void release_level_2_oplocks_on_change(files_struct *fsp) { - share_mode_entry *share_list = NULL; - pid_t pid = sys_getpid(); - int num_share_modes = 0; int i; - BOOL dummy; + struct share_mode_lock *lck; /* * If this file is level II oplocked then we need @@ -1247,125 +627,71 @@ void release_level_2_oplocks_on_change(files_struct *fsp) if (!LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) return; - if (lock_share_entry_fsp(fsp) == False) { - DEBUG(0,("release_level_2_oplocks_on_change: failed to lock share mode entry for file %s.\n", fsp->fsp_name )); + lck = get_share_mode_lock(NULL, fsp->dev, fsp->inode, NULL); + if (lck == NULL) { + DEBUG(0,("release_level_2_oplocks_on_change: failed to lock " + "share mode entry for file %s.\n", fsp->fsp_name )); } - num_share_modes = get_share_modes(fsp->dev, fsp->inode, &share_list, - &dummy); - DEBUG(10,("release_level_2_oplocks_on_change: num_share_modes = %d\n", - num_share_modes )); + lck->num_share_modes )); + + if (fsp->oplock_type == FAKE_LEVEL_II_OPLOCK) { + /* See if someone else has already downgraded us, then we + don't have to do anything */ + for (i=0; inum_share_modes; i++) { + struct share_mode_entry *e = &lck->share_modes[i]; + if ((e->op_type == NO_OPLOCK) && + (e->share_file_id == fsp->file_id) && + (e->dev == fsp->dev) && + (e->inode == fsp->inode) && + (procid_is_me(&e->pid))) { + /* We're done */ + fsp->oplock_type = NO_OPLOCK; + talloc_free(lck); + return; + } + } + } - for(i = 0; i < num_share_modes; i++) { - share_mode_entry *share_entry = &share_list[i]; + for(i = 0; i < lck->num_share_modes; i++) { + struct share_mode_entry *share_entry = &lck->share_modes[i]; /* - * As there could have been multiple writes waiting at the lock_share_entry - * gate we may not be the first to enter. Hence the state of the op_types - * in the share mode entries may be partly NO_OPLOCK and partly LEVEL_II - * oplock. It will do no harm to re-send break messages to those smbd's - * that are still waiting their turn to remove their LEVEL_II state, and - * also no harm to ignore existing NO_OPLOCK states. JRA. + * As there could have been multiple writes waiting at the + * lock_share_entry gate we may not be the first to + * enter. Hence the state of the op_types in the share mode + * entries may be partly NO_OPLOCK and partly LEVEL_II + * oplock. It will do no harm to re-send break messages to + * those smbd's that are still waiting their turn to remove + * their LEVEL_II state, and also no harm to ignore existing + * NO_OPLOCK states. JRA. */ - DEBUG(10,("release_level_2_oplocks_on_change: share_entry[%i]->op_type == %d\n", - i, share_entry->op_type )); + DEBUG(10,("release_level_2_oplocks_on_change: " + "share_entry[%i]->op_type == %d\n", + i, share_entry->op_type )); - if (share_entry->op_type == NO_OPLOCK) + if ((share_entry->op_type == NO_OPLOCK) || + (share_entry->op_type == FAKE_LEVEL_II_OPLOCK)) { continue; + } /* Paranoia .... */ if (EXCLUSIVE_OPLOCK_TYPE(share_entry->op_type)) { - DEBUG(0,("release_level_2_oplocks_on_change: PANIC. share mode entry %d is an exlusive oplock !\n", i )); - unlock_share_entry(fsp->conn, fsp->dev, fsp->inode); + DEBUG(0,("release_level_2_oplocks_on_change: PANIC. " + "share mode entry %d is an exlusive " + "oplock !\n", i )); + talloc_free(lck); abort(); } - /* - * Check if this is a file we have open (including the - * file we've been called to do write_file on. If so - * then break it directly without releasing the lock. - */ - - if (pid == share_entry->pid) { - files_struct *new_fsp = file_find_dif(share_entry->dev, share_entry->inode, share_entry->share_file_id); - - /* Paranoia check... */ - if(new_fsp == NULL) { - DEBUG(0,("release_level_2_oplocks_on_change: PANIC. share mode entry %d is not a local file !\n", i )); - unlock_share_entry(fsp->conn, fsp->dev, fsp->inode); - abort(); - } - - DEBUG(10,("release_level_2_oplocks_on_change: breaking our own oplock.\n")); - - oplock_break_level2(new_fsp, True); - - } else { - - /* - * This is a remote file and so we send an asynchronous - * message. - */ - - DEBUG(10,("release_level_2_oplocks_on_change: breaking remote oplock (async).\n")); - request_remote_level2_async_oplock_break(share_entry); - } - } - - SAFE_FREE(share_list); - unlock_share_entry_fsp(fsp); - - /* Paranoia check... */ - if (LEVEL_II_OPLOCK_TYPE(fsp->oplock_type)) { - DEBUG(0,("release_level_2_oplocks_on_change: PANIC. File %s still has a level II oplock.\n", fsp->fsp_name)); - smb_panic("release_level_2_oplocks_on_change"); - } -} - -/**************************************************************************** - Send a 'retry your open' message to a process with a deferred open entry. -****************************************************************************/ - -BOOL send_deferred_open_retry_message(deferred_open_entry *entry) -{ - char de_msg[DEFERRED_OPEN_MSG_LEN]; - struct sockaddr_in addr_out; - pid_t pid = sys_getpid(); - - memset(de_msg, '\0', DEFERRED_OPEN_MSG_LEN); - SSVAL(de_msg,DEFERRED_OPEN_CMD_OFFSET,RETRY_DEFERRED_OPEN_CMD); - memcpy(de_msg+DEFERRED_OPEN_PID_OFFSET,(char *)&pid,sizeof(pid)); - memcpy(de_msg+DEFERRED_OPEN_DEV_OFFSET,(char *)&entry->dev,sizeof(entry->dev)); - memcpy(de_msg+DEFERRED_OPEN_INODE_OFFSET,(char *)&entry->inode,sizeof(entry->inode)); - memcpy(de_msg+DEFERRED_OPEN_MID_OFFSET,(char *)&entry->mid,sizeof(entry->mid)); - - /* Set the address and port. */ - memset((char *)&addr_out,'\0',sizeof(addr_out)); - addr_out.sin_addr.s_addr = htonl(INADDR_LOOPBACK); - addr_out.sin_port = htons( entry->port ); - addr_out.sin_family = AF_INET; - - if( DEBUGLVL( 3 ) ) { - dbgtext( "send_deferred_open_retry_message: sending a message to "); - dbgtext( "pid %d on port %d ", (int)entry->pid, entry->port ); - dbgtext( "for dev = %x, inode = %.0f, mid = %u\n", - (unsigned int)entry->dev, (double)entry->inode, (unsigned int)entry->mid ); + message_send_pid(share_entry->pid, MSG_SMB_ASYNC_LEVEL2_BREAK, + share_entry, sizeof(*share_entry), True); } - if(sys_sendto(oplock_sock,de_msg,DEFERRED_OPEN_MSG_LEN,0, - (struct sockaddr *)&addr_out,sizeof(addr_out)) < 0) { - if( DEBUGLVL( 0 ) ) { - dbgtext( "send_deferred_open_retry_message: failed sending a message to "); - dbgtext( "pid %d on port %d ", (int)entry->pid, entry->port ); - dbgtext( "for dev = %x, inode = %.0f, mid = %u\n", - (unsigned int)entry->dev, (double)entry->inode, (unsigned int)entry->mid ); - dbgtext( "Error was %s\n", strerror(errno) ); - } - return False; - } - return True; + remove_all_share_oplocks(lck, fsp); + talloc_free(lck); } /**************************************************************************** @@ -1374,30 +700,18 @@ BOOL send_deferred_open_retry_message(deferred_open_entry *entry) BOOL init_oplocks(void) { - struct sockaddr_in sock_name; - socklen_t len = sizeof(sock_name); - DEBUG(3,("open_oplock_ipc: opening loopback UDP socket.\n")); - /* Open a lookback UDP socket on a random port. */ - oplock_sock = open_socket_in(SOCK_DGRAM, 0, 0, htonl(INADDR_LOOPBACK),False); - if (oplock_sock == -1) { - DEBUG(0,("open_oplock_ipc: Failed to get local UDP socket for \ -address %lx. Error was %s\n", (long)htonl(INADDR_LOOPBACK), strerror(errno))); - global_oplock_port = 0; - return(False); - } - - /* Find out the transient UDP port we have been allocated. */ - if(getsockname(oplock_sock, (struct sockaddr *)&sock_name, &len)<0) { - DEBUG(0,("open_oplock_ipc: Failed to get local UDP port. Error was %s\n", - strerror(errno))); - close(oplock_sock); - oplock_sock = -1; - global_oplock_port = 0; - return False; - } - global_oplock_port = ntohs(sock_name.sin_port); + message_register(MSG_SMB_BREAK_REQUEST, + process_oplock_break_message); + message_register(MSG_SMB_ASYNC_LEVEL2_BREAK, + process_oplock_break_message); + message_register(MSG_SMB_BREAK_RESPONSE, + process_oplock_break_response); + message_register(MSG_SMB_KERNEL_BREAK, + process_kernel_oplock_break); + message_register(MSG_SMB_OPEN_RETRY, + process_open_retry_message); if (lp_kernel_oplocks()) { #if HAVE_KERNEL_OPLOCKS_IRIX @@ -1407,8 +721,5 @@ address %lx. Error was %s\n", (long)htonl(INADDR_LOOPBACK), strerror(errno))); #endif } - DEBUG(3,("open_oplock ipc: pid = %d, global_oplock_port = %u\n", - (int)sys_getpid(), global_oplock_port)); - return True; } diff --git a/source3/smbd/oplock_irix.c b/source3/smbd/oplock_irix.c index f4405a021e1..f49aa297e45 100644 --- a/source3/smbd/oplock_irix.c +++ b/source3/smbd/oplock_irix.c @@ -86,7 +86,7 @@ Disabling kernel oplock support.\n", strerror(errno) )); * oplock break protocol. ****************************************************************************/ -static BOOL irix_oplock_receive_message(fd_set *fds, char *buffer, int buffer_len) +static files_struct *irix_oplock_receive_message(fd_set *fds) { extern int smb_read_error; oplock_stat_t os; @@ -102,7 +102,7 @@ static BOOL irix_oplock_receive_message(fd_set *fds, char *buffer, int buffer_le DEBUG(0,("irix_oplock_receive_message: read of kernel notification failed. \ Error was %s.\n", strerror(errno) )); smb_read_error = READ_ERROR; - return False; + return NULL; } /* @@ -122,7 +122,7 @@ Error was %s.\n", strerror(errno) )); return True; } smb_read_error = READ_ERROR; - return False; + return NULL; } /* @@ -138,24 +138,8 @@ Error was %s.\n", strerror(errno) )); DEBUG(5,("irix_oplock_receive_message: kernel oplock break request received for \ dev = %x, inode = %.0f\n, file_id = %ul", (unsigned int)fsp->dev, (double)fsp->inode, fsp->file_id )); - - /* - * Create a kernel oplock break message. - */ - - /* Setup the message header */ - SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,KERNEL_OPLOCK_BREAK_MSG_LEN); - SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,0); - - buffer += OPBRK_CMD_HEADER_LEN; - - SSVAL(buffer,OPBRK_MESSAGE_CMD_OFFSET,KERNEL_OPLOCK_BREAK_CMD); - - memcpy(buffer + KERNEL_OPLOCK_BREAK_DEV_OFFSET, (char *)&fsp->dev, sizeof(fsp->dev)); - memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&fsp->inode, sizeof(fsp->inode)); - memcpy(buffer + KERNEL_OPLOCK_BREAK_FILEID_OFFSET, (char *)&fsp->file_id, sizeof(fsp->file_id)); - - return True; + + return fsp; } /**************************************************************************** @@ -214,30 +198,6 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, } } -/**************************************************************************** - Parse a kernel oplock message. -****************************************************************************/ - -static BOOL irix_kernel_oplock_parse(char *msg_start, int msg_len, - SMB_INO_T *inode, SMB_DEV_T *dev, unsigned long *file_id) -{ - /* Ensure that the msg length is correct. */ - if(msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN) { - DEBUG(0,("incorrect length for KERNEL_OPLOCK_BREAK_CMD (was %d, should be %d).\n", - msg_len, KERNEL_OPLOCK_BREAK_MSG_LEN)); - return False; - } - - memcpy((char *)inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(*inode)); - memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev)); - memcpy((char *)file_id, msg_start+KERNEL_OPLOCK_BREAK_FILEID_OFFSET, sizeof(*file_id)); - - DEBUG(5,("kernel oplock break request for file dev = %x, inode = %.0f, file_id = %ul\n", - (unsigned int)*dev, (double)*inode, *file_id)); - - return True; -} - /**************************************************************************** Set *maxfd to include oplock read pipe. ****************************************************************************/ @@ -274,7 +234,6 @@ struct kernel_oplocks *irix_init_kernel_oplocks(void) koplocks.receive_message = irix_oplock_receive_message; koplocks.set_oplock = irix_set_kernel_oplock; koplocks.release_oplock = irix_release_kernel_oplock; - koplocks.parse_message = irix_kernel_oplock_parse; koplocks.msg_waiting = irix_oplock_msg_waiting; koplocks.notification_fd = oplock_pipe_read; diff --git a/source3/smbd/oplock_linux.c b/source3/smbd/oplock_linux.c index 477832c6e8e..ab0c08f7fcc 100644 --- a/source3/smbd/oplock_linux.c +++ b/source3/smbd/oplock_linux.c @@ -128,10 +128,10 @@ static int linux_setlease(int fd, int leasetype) * oplock break protocol. ****************************************************************************/ -static BOOL linux_oplock_receive_message(fd_set *fds, char *buffer, int buffer_len) +static files_struct *linux_oplock_receive_message(fd_set *fds) { int fd; - struct files_struct *fsp; + files_struct *fsp; BlockSignals(True, RT_SIGNAL_LEASE); fd = fd_pending_array[0]; @@ -145,32 +145,7 @@ static BOOL linux_oplock_receive_message(fd_set *fds, char *buffer, int buffer_l /* now we can receive more signals */ BlockSignals(False, RT_SIGNAL_LEASE); - if (fsp == NULL) { - DEBUG(0,("Invalid file descriptor %d in kernel oplock break!\n", (int)fd)); - return False; - } - - DEBUG(3,("linux_oplock_receive_message: kernel oplock break request received for \ -dev = %x, inode = %.0f fd = %d, fileid = %lu \n", (unsigned int)fsp->dev, (double)fsp->inode, - fd, fsp->file_id)); - - /* - * Create a kernel oplock break message. - */ - - /* Setup the message header */ - SIVAL(buffer,OPBRK_CMD_LEN_OFFSET,KERNEL_OPLOCK_BREAK_MSG_LEN); - SSVAL(buffer,OPBRK_CMD_PORT_OFFSET,0); - - buffer += OPBRK_CMD_HEADER_LEN; - - SSVAL(buffer,OPBRK_MESSAGE_CMD_OFFSET,KERNEL_OPLOCK_BREAK_CMD); - - memcpy(buffer + KERNEL_OPLOCK_BREAK_DEV_OFFSET, (char *)&fsp->dev, sizeof(fsp->dev)); - memcpy(buffer + KERNEL_OPLOCK_BREAK_INODE_OFFSET, (char *)&fsp->inode, sizeof(fsp->inode)); - memcpy(buffer + KERNEL_OPLOCK_BREAK_FILEID_OFFSET, (char *)&fsp->file_id, sizeof(fsp->file_id)); - - return True; + return fsp; } /**************************************************************************** @@ -223,30 +198,6 @@ oplock state of %x.\n", fsp->fsp_name, (unsigned int)fsp->dev, } } -/**************************************************************************** - Parse a kernel oplock message. -****************************************************************************/ - -static BOOL linux_kernel_oplock_parse(char *msg_start, int msg_len, SMB_INO_T *inode, - SMB_DEV_T *dev, unsigned long *file_id) -{ - /* Ensure that the msg length is correct. */ - if (msg_len != KERNEL_OPLOCK_BREAK_MSG_LEN) { - DEBUG(0,("incorrect length for KERNEL_OPLOCK_BREAK_CMD (was %d, should be %lu).\n", - msg_len, (unsigned long)KERNEL_OPLOCK_BREAK_MSG_LEN)); - return False; - } - - memcpy((char *)inode, msg_start+KERNEL_OPLOCK_BREAK_INODE_OFFSET, sizeof(*inode)); - memcpy((char *)dev, msg_start+KERNEL_OPLOCK_BREAK_DEV_OFFSET, sizeof(*dev)); - memcpy((char *)file_id, msg_start+KERNEL_OPLOCK_BREAK_FILEID_OFFSET, sizeof(*file_id)); - - DEBUG(3,("kernel oplock break request for file dev = %x, inode = %.0f, file_id = %lu\n", - (unsigned int)*dev, (double)*inode, *file_id)); - - return True; -} - /**************************************************************************** See if a oplock message is waiting. ****************************************************************************/ @@ -299,7 +250,6 @@ struct kernel_oplocks *linux_init_kernel_oplocks(void) koplocks.receive_message = linux_oplock_receive_message; koplocks.set_oplock = linux_set_kernel_oplock; koplocks.release_oplock = linux_release_kernel_oplock; - koplocks.parse_message = linux_kernel_oplock_parse; koplocks.msg_waiting = linux_oplock_msg_waiting; koplocks.notification_fd = -1; diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 8f9cc528821..0b7b94cce21 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -2,6 +2,7 @@ Unix SMB/CIFS implementation. process incoming packets - main loop 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 @@ -44,12 +45,11 @@ int max_send = BUFFER_SIZE; int max_recv = BUFFER_SIZE; extern int last_message; -extern int global_oplock_break; extern userdom_struct current_user_info; extern int smb_read_error; SIG_ATOMIC_T reload_after_sighup = 0; SIG_ATOMIC_T got_sig_term = 0; -BOOL global_machine_password_needs_changing = False; +extern BOOL global_machine_password_needs_changing; extern int max_send; /**************************************************************************** @@ -66,106 +66,72 @@ uint16 get_current_mid(void) for processing. ****************************************************************************/ -static struct pending_message_list *smb_oplock_queue; -static struct pending_message_list *smb_sharing_violation_queue; - -enum q_type { OPLOCK_QUEUE, SHARE_VIOLATION_QUEUE }; - -/**************************************************************************** - Free up a message. -****************************************************************************/ - -static void free_queued_message(struct pending_message_list *msg) -{ - data_blob_free(&msg->buf); - data_blob_free(&msg->private_data); - SAFE_FREE(msg); -} +static struct pending_message_list *deferred_open_queue; /**************************************************************************** Function to push a message onto the tail of a linked list of smb messages ready for processing. ****************************************************************************/ -static BOOL push_queued_message(enum q_type qt, char *buf, int msg_len, struct timeval *ptv, char *private_data, size_t private_len) +static BOOL push_queued_message(char *buf, int msg_len, + struct timeval request_time, + struct timeval end_time, + char *private_data, size_t private_len) { struct pending_message_list *tmp_msg; - struct pending_message_list *msg = SMB_MALLOC_P(struct pending_message_list); + struct pending_message_list *msg; + + msg = TALLOC_ZERO_P(NULL, struct pending_message_list); if(msg == NULL) { DEBUG(0,("push_message: malloc fail (1)\n")); return False; } - memset(msg,'\0',sizeof(*msg)); - - msg->buf = data_blob(buf, msg_len); + msg->buf = data_blob_talloc(msg, buf, msg_len); if(msg->buf.data == NULL) { DEBUG(0,("push_message: malloc fail (2)\n")); - SAFE_FREE(msg); + talloc_free(msg); return False; } - if (ptv) { - msg->msg_time = *ptv; - } + msg->request_time = request_time; + msg->end_time = end_time; if (private_data) { - msg->private_data = data_blob(private_data, private_len); + msg->private_data = data_blob_talloc(msg, private_data, + private_len); if (msg->private_data.data == NULL) { DEBUG(0,("push_message: malloc fail (3)\n")); - data_blob_free(&msg->buf); - SAFE_FREE(msg); + talloc_free(msg); return False; } } - if (qt == OPLOCK_QUEUE) { - DLIST_ADD_END(smb_oplock_queue, msg, tmp_msg); - } else { - DLIST_ADD_END(smb_sharing_violation_queue, msg, tmp_msg); - } + DLIST_ADD_END(deferred_open_queue, msg, tmp_msg); - DEBUG(10,("push_message: pushed message length %u on queue %s\n", - (unsigned int)msg_len, - qt == OPLOCK_QUEUE ? "smb_oplock_queue" : "smb_sharing_violation_queue" )); + DEBUG(10,("push_message: pushed message length %u on " + "deferred_open_queue\n", (unsigned int)msg_len)); return True; } -/**************************************************************************** - Function to push an oplock smb message onto a linked list of local smb messages ready - for processing. -****************************************************************************/ - -BOOL push_oplock_pending_smb_message(char *buf, int msg_len) -{ - BOOL ret = push_queued_message(OPLOCK_QUEUE, buf, msg_len, NULL, NULL, 0); - if (ret) { - /* Push the MID of this packet on the signing queue. */ - srv_defer_sign_response(SVAL(buf,smb_mid)); - } - return ret; -} - /**************************************************************************** Function to delete a sharing violation open message by mid. ****************************************************************************/ -void remove_sharing_violation_open_smb_message(uint16 mid) +void remove_deferred_open_smb_message(uint16 mid) { struct pending_message_list *pml; - if (!lp_defer_sharing_violations()) { - return; - } - - for (pml = smb_sharing_violation_queue; pml; pml = pml->next) { + for (pml = deferred_open_queue; pml; pml = pml->next) { if (mid == SVAL(pml->buf.data,smb_mid)) { - DEBUG(10,("remove_sharing_violation_open_smb_message: deleting mid %u len %u\n", - (unsigned int)mid, (unsigned int)pml->buf.length )); - DLIST_REMOVE(smb_sharing_violation_queue, pml); - free_queued_message(pml); + DEBUG(10,("remove_sharing_violation_open_smb_message: " + "deleting mid %u len %u\n", + (unsigned int)mid, + (unsigned int)pml->buf.length )); + DLIST_REMOVE(deferred_open_queue, pml); + talloc_free(pml); return; } } @@ -176,30 +142,26 @@ void remove_sharing_violation_open_smb_message(uint16 mid) schedule it for immediate processing. ****************************************************************************/ -void schedule_sharing_violation_open_smb_message(uint16 mid) +void schedule_deferred_open_smb_message(uint16 mid) { struct pending_message_list *pml; int i = 0; - if (!lp_defer_sharing_violations()) { - return; - } - - for (pml = smb_sharing_violation_queue; pml; pml = pml->next) { + for (pml = deferred_open_queue; pml; pml = pml->next) { uint16 msg_mid = SVAL(pml->buf.data,smb_mid); - DEBUG(10,("schedule_sharing_violation_open_smb_message: [%d] msg_mid = %u\n", i++, + DEBUG(10,("schedule_deferred_open_smb_message: [%d] msg_mid = %u\n", i++, (unsigned int)msg_mid )); if (mid == msg_mid) { - DEBUG(10,("schedule_sharing_violation_open_smb_message: scheduling mid %u\n", + DEBUG(10,("schedule_deferred_open_smb_message: scheduling mid %u\n", mid )); - pml->msg_time.tv_sec = 0; - pml->msg_time.tv_usec = 0; - DLIST_PROMOTE(smb_sharing_violation_queue, pml); + pml->end_time.tv_sec = 0; + pml->end_time.tv_usec = 0; + DLIST_PROMOTE(deferred_open_queue, pml); return; } } - DEBUG(10,("schedule_sharing_violation_open_smb_message: failed to find message mid %u\n", + DEBUG(10,("schedule_deferred_open_smb_message: failed to find message mid %u\n", mid )); } @@ -211,13 +173,9 @@ BOOL open_was_deferred(uint16 mid) { struct pending_message_list *pml; - if (!lp_defer_sharing_violations()) { - return False; - } - - for (pml = smb_sharing_violation_queue; pml; pml = pml->next) { + for (pml = deferred_open_queue; pml; pml = pml->next) { if (SVAL(pml->buf.data,smb_mid) == mid) { - set_saved_error_triple(SMB_SUCCESS, 0, NT_STATUS_OK); + set_saved_ntstatus(NT_STATUS_OK); return True; } } @@ -232,11 +190,7 @@ struct pending_message_list *get_open_deferred_message(uint16 mid) { struct pending_message_list *pml; - if (!lp_defer_sharing_violations()) { - return NULL; - } - - for (pml = smb_sharing_violation_queue; pml; pml = pml->next) { + for (pml = deferred_open_queue; pml; pml = pml->next) { if (SVAL(pml->buf.data,smb_mid) == mid) { return pml; } @@ -245,57 +199,216 @@ struct pending_message_list *get_open_deferred_message(uint16 mid) } /**************************************************************************** - Function to push a sharing violation open smb message onto a linked list of local smb messages ready - for processing. We must use current_inbuf here not Inbuf in case we're in a chained message set. + Function to push a deferred open smb message onto a linked list of local smb + messages ready for processing. +****************************************************************************/ + +BOOL push_deferred_smb_message(uint16 mid, + struct timeval request_time, + struct timeval timeout, + char *private_data, size_t priv_len) +{ + struct timeval end_time; + + end_time = timeval_sum(&request_time, &timeout); + + DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u " + "timeout time [%u.%06u]\n", + (unsigned int) smb_len(current_inbuf)+4, (unsigned int)mid, + (unsigned int)end_time.tv_sec, + (unsigned int)end_time.tv_usec)); + + return push_queued_message(current_inbuf, smb_len(current_inbuf)+4, + request_time, end_time, + private_data, priv_len); +} + +static struct timed_event *timed_events; + +struct timed_event { + struct timed_event *next, *prev; + struct timeval when; + const char *event_name; + void (*handler)(struct timed_event *te, + const struct timeval *now, + void *private_data); + void *private_data; +}; + +static int timed_event_destructor(void *p) +{ + struct timed_event *te = talloc_get_type_abort(p, struct timed_event); + DEBUG(10, ("Destroying timed event %lx \"%s\"\n", (unsigned long)te, + te->event_name)); + DLIST_REMOVE(timed_events, te); + return 0; +} + +/**************************************************************************** + Schedule a function for future calling, cancel with talloc_free(). + It's the responsibility of the handler to call talloc_free() on the event + handed to it. ****************************************************************************/ -BOOL push_sharing_violation_open_smb_message(struct timeval *ptv, char *private_data, size_t priv_len) +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) { - uint16 mid = SVAL(current_inbuf,smb_mid); - struct timeval tv; - SMB_BIG_INT tdif; + struct timed_event *te, *last_te, *cur_te; - if (!lp_defer_sharing_violations()) { - return True; + te = TALLOC_P(mem_ctx, struct timed_event); + if (te == NULL) { + DEBUG(0, ("talloc failed\n")); + return NULL; } - tv = *ptv; - tdif = tv.tv_sec; - tdif *= 1000000; - tdif += tv.tv_usec; + 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; + } - /* Add on the timeout. */ - tdif += SHARING_VIOLATION_USEC_WAIT; - - tv.tv_sec = tdif / 1000000; - tv.tv_usec = tdif % 1000000; - - DEBUG(10,("push_sharing_violation_open_smb_message: pushing message len %u mid %u\ - timeout time [%u.%06u]\n", (unsigned int) smb_len(current_inbuf)+4, (unsigned int)mid, - (unsigned int)tv.tv_sec, (unsigned int)tv.tv_usec)); + DLIST_ADD_AFTER(timed_events, te, last_te); + talloc_set_destructor(te, timed_event_destructor); - return push_queued_message(SHARE_VIOLATION_QUEUE, current_inbuf, - smb_len(current_inbuf)+4, &tv, private_data, priv_len); + DEBUG(10, ("Added timed event \"%s\": %lx\n", event_name, + (unsigned long)te)); + return te; } +static void run_events(void) +{ + struct timeval now; + + if (timed_events == NULL) { + /* No syscall if there are no events */ + DEBUG(10, ("run_events: No events\n")); + return; + } + + GetTimeOfDay(&now); + + if (timeval_compare(&now, &timed_events->when) < 0) { + /* Nothing to do yet */ + DEBUG(10, ("run_events: Nothing to do\n")); + return; + } + + DEBUG(10, ("Running event \"%s\" %lx\n", timed_events->event_name, + (unsigned long)timed_events)); + + timed_events->handler(timed_events, &now, timed_events->private_data); + return; +} + +struct timeval timed_events_timeout(void) +{ + struct timeval now, timeout; + + if (timed_events == NULL) { + return timeval_set(SMBD_SELECT_TIMEOUT, 0); + } + + now = timeval_current(); + timeout = timeval_until(&now, &timed_events->when); + + DEBUG(10, ("timed_events_timeout: %d/%d\n", (int)timeout.tv_sec, + (int)timeout.tv_usec)); + + return timeout; +} + +struct idle_event { + struct timed_event *te; + struct timeval interval; + BOOL (*handler)(const struct timeval *now, void *private_data); + void *private_data; +}; + +static void idle_event_handler(struct timed_event *te, + const struct timeval *now, + void *private_data) +{ + struct idle_event *event = + talloc_get_type_abort(private_data, struct idle_event); + + talloc_free(event->te); + + if (!event->handler(now, event->private_data)) { + /* Don't repeat, delete ourselves */ + talloc_free(event); + return; + } + + event->te = add_timed_event(event, timeval_sum(now, &event->interval), + "idle_event_handler", + idle_event_handler, event); + + /* We can't do much but fail here. */ + SMB_ASSERT(event->te != NULL); +} + +struct idle_event *add_idle_event(TALLOC_CTX *mem_ctx, + struct timeval interval, + BOOL (*handler)(const struct timeval *now, + void *private_data), + void *private_data) +{ + struct idle_event *result; + struct timeval now = timeval_current(); + + result = TALLOC_P(mem_ctx, struct idle_event); + if (result == NULL) { + DEBUG(0, ("talloc failed\n")); + return NULL; + } + + result->interval = interval; + result->handler = handler; + result->private_data = private_data; + + result->te = add_timed_event(result, timeval_sum(&now, &interval), + "idle_event_handler", + idle_event_handler, result); + if (result->te == NULL) { + DEBUG(0, ("add_timed_event failed\n")); + talloc_free(result); + return NULL; + } + + return result; +} + /**************************************************************************** - Do all async processing in here. This includes UDB oplock messages, kernel - oplock messages, change notify events etc. + Do all async processing in here. This includes kernel oplock messages, change + notify events etc. ****************************************************************************/ -static void async_processing(char *buffer, int buffer_len) +static void async_processing(void) { DEBUG(10,("async_processing: Doing async processing.\n")); process_aio_queue(); - /* check for oplock messages (both UDP and kernel) */ - if (receive_local_message(buffer, buffer_len, 1)) { - process_local_message(buffer, buffer_len); - } + process_kernel_oplocks(); - /* Do the aio check again after receive_local_message as it does a select - and may have eaten our signal. */ + /* Do the aio check again after receive_local_message as it does a + select and may have eaten our signal. */ + /* Is this till true? -- vl */ process_aio_queue(); if (got_sig_term) { @@ -339,17 +452,17 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) { fd_set fds; int selrtn; - struct timeval to; - struct timeval *pto; + struct timeval to = timeval_set(SMBD_SELECT_TIMEOUT, 0); int maxfd; smb_read_error = 0; again: - to.tv_sec = timeout / 1000; - to.tv_usec = (timeout % 1000) * 1000; - pto = timeout > 0 ? &to : NULL; + if (timeout >= 0) { + to.tv_sec = timeout / 1000; + to.tv_usec = (timeout % 1000) * 1000; + } /* * Note that this call must be before processing any SMB @@ -358,38 +471,22 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) */ message_dispatch(); - /* - * Check to see if we already have a message on the smb queue. - * If so - copy and return it. - */ - if(smb_oplock_queue != NULL) { - struct pending_message_list *msg = smb_oplock_queue; - memcpy(buffer, msg->buf.data, MIN(buffer_len, msg->buf.length)); - - /* Free the message we just copied. */ - DLIST_REMOVE(smb_oplock_queue, msg); - free_queued_message(msg); - - DEBUG(5,("receive_message_or_smb: returning queued smb message.\n")); - return True; - } - /* * Check to see if we already have a message on the deferred open queue * and it's time to schedule. */ - if(smb_sharing_violation_queue != NULL) { + if(deferred_open_queue != NULL) { BOOL pop_message = False; - struct pending_message_list *msg = smb_sharing_violation_queue; + struct pending_message_list *msg = deferred_open_queue; - if (msg->msg_time.tv_sec == 0 && msg->msg_time.tv_usec == 0) { + if (timeval_is_zero(&msg->end_time)) { pop_message = True; } else { struct timeval tv; SMB_BIG_INT tdif; GetTimeOfDay(&tv); - tdif = usec_time_diff(&msg->msg_time, &tv); + tdif = usec_time_diff(&msg->end_time, &tv); if (tdif <= 0) { /* Timed out. Schedule...*/ pop_message = True; @@ -398,9 +495,8 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) /* Make a more accurate select timeout. */ to.tv_sec = tdif / 1000000; to.tv_usec = tdif % 1000000; - pto = &to; DEBUG(10,("receive_message_or_smb: select with timeout of [%u.%06u]\n", - (unsigned int)pto->tv_sec, (unsigned int)pto->tv_usec )); + (unsigned int)to.tv_sec, (unsigned int)to.tv_usec )); } } @@ -431,7 +527,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) if (oplock_message_waiting(&fds)) { DEBUG(10,("receive_message_or_smb: oplock_message is waiting.\n")); - async_processing(buffer, buffer_len); + async_processing(); /* * After async processing we must go and do the select again, as * the state of the flag in fds for the server file descriptor is @@ -439,18 +535,26 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) */ goto again; } + + { + struct timeval tmp = timed_events_timeout(); + to = timeval_min(&to, &tmp); + if (timeval_is_zero(&to)) { + return True; + } + } FD_SET(smbd_server_fd(),&fds); maxfd = setup_oplock_select_set(&fds); - selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,pto); + selrtn = sys_select(MAX(maxfd,smbd_server_fd())+1,&fds,NULL,NULL,&to); /* if we get EINTR then maybe we have received an oplock signal - treat this as select returning 1. This is ugly, but is the best we can do until the oplock code knows more about signals */ if (selrtn == -1 && errno == EINTR) { - async_processing(buffer, buffer_len); + async_processing(); /* * After async processing we must go and do the select again, as * the state of the flag in fds for the server file descriptor is @@ -479,7 +583,7 @@ static BOOL receive_message_or_smb(char *buffer, int buffer_len, int timeout) */ if (oplock_message_waiting(&fds)) { - async_processing(buffer, buffer_len); + async_processing(); /* * After async processing we must go and do the select again, as * the state of the flag in fds for the server file descriptor is @@ -518,8 +622,6 @@ BOOL receive_next_smb(char *inbuf, int bufsize, int timeout) void respond_to_all_remaining_local_messages(void) { - char buffer[1024]; - /* * Assert we have no exclusive open oplocks. */ @@ -530,15 +632,7 @@ void respond_to_all_remaining_local_messages(void) return; } - /* - * Keep doing receive_local_message with a 1 ms timeout until - * we have no more messages. - */ - - while(receive_local_message(buffer, sizeof(buffer), 1)) { - /* Deal with oplock break requests from other smbd's. */ - process_local_message(buffer, sizeof(buffer)); - } + process_kernel_oplocks(); return; } @@ -556,8 +650,7 @@ force write permissions on print services. #define TIME_INIT (1<<2) #define CAN_IPC (1<<3) #define AS_GUEST (1<<5) -#define QUEUE_IN_OPLOCK (1<<6) -#define DO_CHDIR (1<<7) +#define DO_CHDIR (1<<6) /* define a list of possible SMB messages and their corresponding @@ -572,19 +665,19 @@ static const struct smb_message_struct { /* 0x00 */ { "SMBmkdir",reply_mkdir,AS_USER | NEED_WRITE}, /* 0x01 */ { "SMBrmdir",reply_rmdir,AS_USER | NEED_WRITE}, -/* 0x02 */ { "SMBopen",reply_open,AS_USER | QUEUE_IN_OPLOCK }, +/* 0x02 */ { "SMBopen",reply_open,AS_USER }, /* 0x03 */ { "SMBcreate",reply_mknew,AS_USER}, /* 0x04 */ { "SMBclose",reply_close,AS_USER | CAN_IPC }, /* 0x05 */ { "SMBflush",reply_flush,AS_USER}, -/* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK}, -/* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK}, +/* 0x06 */ { "SMBunlink",reply_unlink,AS_USER | NEED_WRITE }, +/* 0x07 */ { "SMBmv",reply_mv,AS_USER | NEED_WRITE }, /* 0x08 */ { "SMBgetatr",reply_getatr,AS_USER}, /* 0x09 */ { "SMBsetatr",reply_setatr,AS_USER | NEED_WRITE}, /* 0x0a */ { "SMBread",reply_read,AS_USER}, /* 0x0b */ { "SMBwrite",reply_write,AS_USER | CAN_IPC }, /* 0x0c */ { "SMBlock",reply_lock,AS_USER}, /* 0x0d */ { "SMBunlock",reply_unlock,AS_USER}, -/* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER | QUEUE_IN_OPLOCK }, +/* 0x0e */ { "SMBctemp",reply_ctemp,AS_USER }, /* 0x0f */ { "SMBmknew",reply_mknew,AS_USER}, /* 0x10 */ { "SMBchkpth",reply_chkpth,AS_USER}, /* 0x11 */ { "SMBexit",reply_exit,DO_CHDIR}, @@ -611,11 +704,11 @@ static const struct smb_message_struct { /* 0x26 */ { "SMBtranss",NULL,AS_USER | CAN_IPC}, /* 0x27 */ { "SMBioctl",reply_ioctl,0}, /* 0x28 */ { "SMBioctls",NULL,AS_USER}, -/* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, -/* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, +/* 0x29 */ { "SMBcopy",reply_copy,AS_USER | NEED_WRITE }, +/* 0x2a */ { "SMBmove",NULL,AS_USER | NEED_WRITE }, /* 0x2b */ { "SMBecho",reply_echo,0}, /* 0x2c */ { "SMBwriteclose",reply_writeclose,AS_USER}, -/* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, +/* 0x2d */ { "SMBopenX",reply_open_and_X,AS_USER | CAN_IPC }, /* 0x2e */ { "SMBreadX",reply_read_and_X,AS_USER | CAN_IPC }, /* 0x2f */ { "SMBwriteX",reply_write_and_X,AS_USER | CAN_IPC }, /* 0x30 */ { NULL, NULL, 0 }, @@ -730,12 +823,12 @@ static const struct smb_message_struct { /* 0x9d */ { NULL, NULL, 0 }, /* 0x9e */ { NULL, NULL, 0 }, /* 0x9f */ { NULL, NULL, 0 }, -/* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK}, +/* 0xa0 */ { "SMBnttrans", reply_nttrans, AS_USER | CAN_IPC }, /* 0xa1 */ { "SMBnttranss", reply_nttranss, AS_USER | CAN_IPC }, -/* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC | QUEUE_IN_OPLOCK }, +/* 0xa2 */ { "SMBntcreateX", reply_ntcreate_and_X, AS_USER | CAN_IPC }, /* 0xa3 */ { NULL, NULL, 0 }, /* 0xa4 */ { "SMBntcancel", reply_ntcancel, 0 }, -/* 0xa5 */ { "SMBntrename", reply_ntrename, AS_USER | NEED_WRITE | QUEUE_IN_OPLOCK }, +/* 0xa5 */ { "SMBntrename", reply_ntrename, AS_USER | NEED_WRITE }, /* 0xa6 */ { NULL, NULL, 0 }, /* 0xa7 */ { NULL, NULL, 0 }, /* 0xa8 */ { NULL, NULL, 0 }, @@ -762,7 +855,7 @@ static const struct smb_message_struct { /* 0xbd */ { NULL, NULL, 0 }, /* 0xbe */ { NULL, NULL, 0 }, /* 0xbf */ { NULL, NULL, 0 }, -/* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER | QUEUE_IN_OPLOCK }, +/* 0xc0 */ { "SMBsplopen",reply_printopen,AS_USER}, /* 0xc1 */ { "SMBsplwr",reply_printwrite,AS_USER}, /* 0xc2 */ { "SMBsplclose",reply_printclose,AS_USER}, /* 0xc3 */ { "SMBsplretq",reply_printqueue,AS_USER}, @@ -871,7 +964,7 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize pid = sys_getpid(); errno = 0; - set_saved_error_triple(0, 0, NT_STATUS_OK); + set_saved_ntstatus(NT_STATUS_OK); last_message = type; @@ -900,19 +993,6 @@ static int switch_message(int type,char *inbuf,char *outbuf,int size,int bufsize DEBUG(3,("switch message %s (pid %d) conn 0x%lx\n",smb_fn_name(type),(int)pid,(unsigned long)conn)); smb_dump(smb_fn_name(type), 1, inbuf, size); - if(global_oplock_break) { - if(flags & QUEUE_IN_OPLOCK) { - /* - * Queue this message as we are the process of an oplock break. - */ - - DEBUG( 2, ( "switch_message: queueing message due to being in " ) ); - DEBUGADD( 2, ( "oplock break state.\n" ) ); - - push_oplock_pending_smb_message( inbuf, size ); - return -1; - } - } /* Ensure this value is replaced in the incoming packet. */ SSVAL(inbuf,smb_uid,session_tag); @@ -1289,6 +1369,7 @@ static int setup_select_timeout(void) select_timeout *= 1000; t = change_notify_timeout(); + DEBUG(10, ("change_notify_timeout: %d\n", t)); if (t != -1) select_timeout = MIN(select_timeout, t*1000); @@ -1302,7 +1383,7 @@ static int setup_select_timeout(void) Check if services need reloading. ****************************************************************************/ -void check_reload(int t) +void check_reload(time_t t) { static pid_t mypid = 0; static time_t last_smb_conf_reload_time = 0; @@ -1644,6 +1725,8 @@ void smbd_process(void) num_smbs = 0; /* Reset smb counter. */ } + run_events(); + #if defined(DEVELOPER) clobber_region(SAFE_STRING_FUNCTION_NAME, SAFE_STRING_LINE, InBuffer, total_buffer_size); #endif diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 5572f47e427..ba22a56cfb4 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -30,7 +30,6 @@ extern enum protocol_types Protocol; extern int max_send; extern int max_recv; -extern int global_oplock_break; unsigned int smb_echo_count = 0; extern uint32 global_client_caps; @@ -1779,7 +1778,7 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, } /* We need a better way to return NT status codes from open... */ - set_saved_error_triple(0, 0, NT_STATUS_OK); + set_saved_ntstatus(NT_STATUS_OK); fsp = open_file_ntcreate(conn, fname, pst, DELETE_ACCESS, @@ -1791,12 +1790,12 @@ static NTSTATUS can_rename(connection_struct *conn, char *fname, uint16 dirtype, NULL); if (!fsp) { - NTSTATUS ret; - if (get_saved_error_triple(NULL, NULL, &ret)) { - set_saved_error_triple(0, 0, NT_STATUS_OK); + NTSTATUS ret = get_saved_ntstatus(); + if (!NT_STATUS_IS_OK(ret)) { + set_saved_ntstatus(NT_STATUS_OK); return ret; } - set_saved_error_triple(0, 0, NT_STATUS_OK); + set_saved_ntstatus(NT_STATUS_OK); return NT_STATUS_ACCESS_DENIED; } close_file(fsp,False); @@ -1860,7 +1859,7 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b don't do it here as we'll get it wrong. */ /* We need a better way to return NT status codes from open... */ - set_saved_error_triple(0, 0, NT_STATUS_OK); + set_saved_ntstatus(NT_STATUS_OK); fsp = open_file_ntcreate(conn, fname, &sbuf, DELETE_ACCESS, @@ -1872,12 +1871,12 @@ NTSTATUS can_delete(connection_struct *conn, char *fname, uint32 dirtype, BOOL b NULL); if (!fsp) { - NTSTATUS ret; - if (get_saved_error_triple(NULL, NULL, &ret)) { - set_saved_error_triple(0, 0, NT_STATUS_OK); + NTSTATUS ret = get_saved_ntstatus(); + if (!NT_STATUS_IS_OK(ret)) { + set_saved_ntstatus(NT_STATUS_OK); return ret; } - set_saved_error_triple(0, 0, NT_STATUS_OK); + set_saved_ntstatus(NT_STATUS_OK); return NT_STATUS_ACCESS_DENIED; } close_file(fsp,False); @@ -2209,15 +2208,6 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s * return a zero length response here. */ - if(global_oplock_break) { - _smb_setlen(header,0); - if (write_data(smbd_server_fd(),header,4) != 4) - fail_readraw(); - DEBUG(5,("readbraw - oplock break finished\n")); - END_PROFILE(SMBreadbraw); - return -1; - } - fsp = file_fsp(inbuf,smb_vwv0); if (!FNUM_OK(fsp,conn) || !fsp->can_read) { @@ -2298,8 +2288,8 @@ int reply_readbraw(connection_struct *conn, char *inbuf, char *outbuf, int dum_s nread = 0; #endif - DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%d min=%d nread=%d\n", fsp->fnum, (double)startpos, - (int)maxcount, (int)mincount, (int)nread ) ); + DEBUG( 3, ( "readbraw fnum=%d start=%.0f max=%lu min=%lu nread=%lu\n", fsp->fnum, (double)startpos, + (unsigned long)maxcount, (unsigned long)mincount, (unsigned long)nread ) ); send_file_readbraw(conn, fsp, startpos, nread, mincount, outbuf, out_buffsize); @@ -3744,7 +3734,7 @@ int reply_mkdir(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, if( is_ntfs_stream_name(directory)) { DEBUG(5,("reply_mkdir: failing create on filename %s with colon in name\n", directory)); END_PROFILE(SMBmkdir); - return ERROR_FORCE_DOS(ERRDOS, ERRinvalidname); + return ERROR_NT(NT_STATUS_NOT_A_DIRECTORY); } status = mkdir_internal(conn, directory,bad_path); @@ -5084,7 +5074,8 @@ SMB_BIG_UINT get_lock_offset( char *data, int data_offset, BOOL large_file_forma Reply to a lockingX request. ****************************************************************************/ -int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) +int reply_lockingX(connection_struct *conn, char *inbuf, char *outbuf, + int length, int bufsize) { files_struct *fsp = file_fsp(inbuf,smb_vwv2); unsigned char locktype = CVAL(inbuf,smb_vwv3); @@ -5096,7 +5087,8 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, int32 lock_timeout = IVAL(inbuf,smb_vwv4); int i; char *data; - BOOL large_file_format = (locktype & LOCKING_ANDX_LARGE_FILES)?True:False; + BOOL large_file_format = + (locktype & LOCKING_ANDX_LARGE_FILES)?True:False; BOOL err; BOOL my_lock_ctx = False; NTSTATUS status; @@ -5125,19 +5117,25 @@ int reply_lockingX(connection_struct *conn, char *inbuf,char *outbuf,int length, if ((locktype & LOCKING_ANDX_OPLOCK_RELEASE)) { /* Client can insist on breaking to none. */ BOOL break_to_none = (oplocklevel == 0); - - DEBUG(5,("reply_lockingX: oplock break reply (%u) from client for fnum = %d\n", - (unsigned int)oplocklevel, fsp->fnum )); + BOOL result; + + DEBUG(5,("reply_lockingX: oplock break reply (%u) from client " + "for fnum = %d\n", (unsigned int)oplocklevel, + fsp->fnum )); /* - * Make sure we have granted an exclusive or batch oplock on this file. + * Make sure we have granted an exclusive or batch oplock on + * this file. */ - if(!EXCLUSIVE_OPLOCK_TYPE(fsp->oplock_type)) { - DEBUG(0,("reply_lockingX: Error : oplock break from client for fnum = %d and \ -no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); - - /* if this is a pure oplock break request then don't send a reply */ + if (fsp->oplock_type == 0) { + DEBUG(0,("reply_lockingX: Error : oplock break from " + "client for fnum = %d (oplock=%d) and no " + "oplock granted on this file (%s).\n", + fsp->fnum, fsp->oplock_type, fsp->fsp_name)); + + /* if this is a pure oplock break request then don't + * send a reply */ if (num_locks == 0 && num_ulocks == 0) { END_PROFILE(SMBlockingX); return -1; @@ -5147,17 +5145,30 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); } } - if (remove_oplock(fsp, break_to_none) == False) { - DEBUG(0,("reply_lockingX: error in removing oplock on file %s\n", - fsp->fsp_name )); + if ((fsp->sent_oplock_break == BREAK_TO_NONE_SENT) || + (break_to_none)) { + result = remove_oplock(fsp); + } else { + result = downgrade_oplock(fsp); } - /* if this is a pure oplock break request then don't send a reply */ + if (!result) { + DEBUG(0, ("reply_lockingX: error in removing " + "oplock on file %s\n", fsp->fsp_name)); + /* Hmmm. Is this panic justified? */ + smb_panic("internal tdb error"); + } + + reply_to_oplock_break_requests(fsp); + + /* if this is a pure oplock break request then don't send a + * reply */ if (num_locks == 0 && num_ulocks == 0) { /* Sanity check - ensure a pure oplock break is not a chained request. */ if(CVAL(inbuf,smb_vwv0) != 0xff) - DEBUG(0,("reply_lockingX: Error : pure oplock break is a chained %d request !\n", + DEBUG(0,("reply_lockingX: Error : pure oplock " + "break is a chained %d request !\n", (unsigned int)CVAL(inbuf,smb_vwv0) )); END_PROFILE(SMBlockingX); return -1; @@ -5186,8 +5197,9 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); return ERROR_DOS(ERRDOS,ERRnoaccess); } - DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for pid %u, file %s\n", - (double)offset, (double)count, (unsigned int)lock_pid, fsp->fsp_name )); + DEBUG(10,("reply_lockingX: unlock start=%.0f, len=%.0f for " + "pid %u, file %s\n", (double)offset, (double)count, + (unsigned int)lock_pid, fsp->fsp_name )); status = do_unlock(fsp,conn,lock_pid,count,offset); if (NT_STATUS_V(status)) { @@ -5219,27 +5231,34 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); return ERROR_DOS(ERRDOS,ERRnoaccess); } - DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid %u, file %s timeout = %d\n", - (double)offset, (double)count, (unsigned int)lock_pid, - fsp->fsp_name, (int)lock_timeout )); + DEBUG(10,("reply_lockingX: lock start=%.0f, len=%.0f for pid " + "%u, file %s timeout = %d\n", (double)offset, + (double)count, (unsigned int)lock_pid, + fsp->fsp_name, (int)lock_timeout )); status = do_lock_spin(fsp,conn,lock_pid, count,offset, - ((locktype & 1) ? READ_LOCK : WRITE_LOCK), &my_lock_ctx); + ((locktype & 1) ? READ_LOCK:WRITE_LOCK), + &my_lock_ctx); if (NT_STATUS_V(status)) { /* - * Interesting fact found by IFSTEST /t LockOverlappedTest... - * Even if it's our own lock context, we need to wait here as - * there may be an unlock on the way. - * So I removed a "&& !my_lock_ctx" from the following - * if statement. JRA. + * Interesting fact found by IFSTEST /t + * LockOverlappedTest... Even if it's our own lock + * context, we need to wait here as there may be an + * unlock on the way. So I removed a "&& + * !my_lock_ctx" from the following if statement. JRA. */ - if ((lock_timeout != 0) && lp_blocking_locks(SNUM(conn)) && ERROR_WAS_LOCK_DENIED(status)) { + if ((lock_timeout != 0) && + lp_blocking_locks(SNUM(conn)) && + ERROR_WAS_LOCK_DENIED(status)) { /* * A blocking lock was requested. Package up * this smb into a queued request and push it * onto the blocking lock queue. */ - if(push_blocking_lock_request(inbuf, length, lock_timeout, i, lock_pid, offset, count)) { + if(push_blocking_lock_request(inbuf, length, + lock_timeout, i, + lock_pid, offset, + count)) { END_PROFILE(SMBlockingX); return -1; } @@ -5259,10 +5278,12 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); for(i--; i >= 0; i--) { lock_pid = get_lock_pid( data, i, large_file_format); count = get_lock_count( data, i, large_file_format); - offset = get_lock_offset( data, i, large_file_format, &err); + offset = get_lock_offset( data, i, large_file_format, + &err); /* - * There is no error code marked "stupid client bug".... :-). + * There is no error code marked "stupid client + * bug".... :-). */ if(err) { END_PROFILE(SMBlockingX); @@ -5277,8 +5298,8 @@ no oplock granted on this file (%s).\n", fsp->fnum, fsp->fsp_name)); set_message(outbuf,2,0,True); - DEBUG( 3, ( "lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n", - fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks ) ); + DEBUG(3, ("lockingX fnum=%d type=%d num_locks=%d num_ulocks=%d\n", + fsp->fnum, (unsigned int)locktype, num_locks, num_ulocks)); END_PROFILE(SMBlockingX); return chain_reply(inbuf,outbuf,length,bufsize); diff --git a/source3/smbd/server.c b/source3/smbd/server.c index 1ff03174fe1..8310b408d07 100644 --- a/source3/smbd/server.c +++ b/source3/smbd/server.c @@ -96,7 +96,7 @@ static void killkids(void) somewhere else. ****************************************************************************/ -static void msg_sam_sync(int UNUSED(msg_type), pid_t UNUSED(pid), +static void msg_sam_sync(int UNUSED(msg_type), struct process_id UNUSED(pid), void *UNUSED(buf), size_t UNUSED(len)) { DEBUG(10, ("** sam sync message received, ignoring\n")); @@ -107,7 +107,8 @@ static void msg_sam_sync(int UNUSED(msg_type), pid_t UNUSED(pid), somewhere else. ****************************************************************************/ -static void msg_sam_repl(int msg_type, pid_t pid, void *buf, size_t len) +static void msg_sam_repl(int msg_type, struct process_id pid, + void *buf, size_t len) { uint32 low_serial; @@ -140,7 +141,8 @@ static BOOL open_sockets_inetd(void) return True; } -static void msg_exit_server(int msg_type, pid_t src, void *buf, size_t len) +static void msg_exit_server(int msg_type, struct process_id src, + void *buf, size_t len) { exit_server("Got a SHUTDOWN message"); } @@ -621,9 +623,6 @@ void exit_server(const char *reason) print_notify_send_messages(3); /* 3 second timeout. */ - /* run all registered exit events */ - smb_run_exit_events(); - /* delete our entry in the connections database. */ yield_connection(NULL,""); diff --git a/source3/smbd/sesssetup.c b/source3/smbd/sesssetup.c index bf7287aab9c..fc2d8b4abb4 100644 --- a/source3/smbd/sesssetup.c +++ b/source3/smbd/sesssetup.c @@ -139,6 +139,7 @@ static int reply_spnego_kerberos(connection_struct *conn, int length, int bufsize, DATA_BLOB *secblob) { + TALLOC_CTX *mem_ctx; DATA_BLOB ticket; char *client, *p, *domain; fstring netbios_domain_name; @@ -146,7 +147,7 @@ static int reply_spnego_kerberos(connection_struct *conn, fstring user; int sess_vuid; NTSTATUS ret; - DATA_BLOB auth_data; + PAC_DATA *pac_data; DATA_BLOB ap_rep, ap_rep_wrapped, response; auth_serversupplied_info *server_info = NULL; DATA_BLOB session_key = data_blob(NULL, 0); @@ -154,18 +155,24 @@ static int reply_spnego_kerberos(connection_struct *conn, DATA_BLOB nullblob = data_blob(NULL, 0); fstring real_username; BOOL map_domainuser_to_guest = False; + PAC_LOGON_INFO *logon_info = NULL; + int i; ZERO_STRUCT(ticket); - ZERO_STRUCT(auth_data); + ZERO_STRUCT(pac_data); ZERO_STRUCT(ap_rep); ZERO_STRUCT(ap_rep_wrapped); ZERO_STRUCT(response); + mem_ctx = talloc_init("reply_spnego_kerberos"); + if (mem_ctx == NULL) + return ERROR_NT(NT_STATUS_NO_MEMORY); + if (!spnego_parse_krb5_wrap(*secblob, &ticket, tok_id)) { return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - ret = ads_verify_ticket(lp_realm(), &ticket, &client, &auth_data, &ap_rep, &session_key); + ret = ads_verify_ticket(mem_ctx, lp_realm(), &ticket, &client, &pac_data, &ap_rep, &session_key); data_blob_free(&ticket); @@ -174,7 +181,18 @@ static int reply_spnego_kerberos(connection_struct *conn, return ERROR_NT(NT_STATUS_LOGON_FAILURE); } - data_blob_free(&auth_data); + if (pac_data) { + + /* get the logon_info */ + for (i=0; i < pac_data->num_buffers; i++) { + + if (pac_data->pac_buffer[i].type != PAC_TYPE_LOGON_INFO) + continue; + + logon_info = pac_data->pac_buffer[i].ctr->pac.logon_info; + break; + } + } DEBUG(3,("Ticket name is [%s]\n", client)); @@ -203,7 +221,14 @@ static int reply_spnego_kerberos(connection_struct *conn, domain = p+1; - { + if (logon_info && logon_info->info3.hdr_logon_dom.uni_str_len) { + + unistr2_to_ascii(netbios_domain_name, &logon_info->info3.uni_logon_dom, -1); + domain = netbios_domain_name; + DEBUG(10, ("Mapped to [%s] (using PAC)\n", domain)); + + } else { + /* If we have winbind running, we can (and must) shorten the username by using the short netbios name. Otherwise we will have inconsistent user names. With Kerberos, we get the @@ -231,7 +256,7 @@ static int reply_spnego_kerberos(connection_struct *conn, wb_response.data.domain_info.name); domain = netbios_domain_name; - DEBUG(10, ("Mapped to [%s]\n", domain)); + DEBUG(10, ("Mapped to [%s] (using Winbind)\n", domain)); } else { DEBUG(3, ("Could not find short name -- winbind " "not running?\n")); @@ -274,8 +299,21 @@ static int reply_spnego_kerberos(connection_struct *conn, reload_services(True); if ( map_domainuser_to_guest ) { make_server_info_guest(&server_info); + } else if (logon_info) { + ret = make_server_info_pac(&server_info, real_username, pw, logon_info); + + if ( !NT_STATUS_IS_OK(ret) ) { + DEBUG(1,("make_server_info_pac failed!\n")); + SAFE_FREE(client); + data_blob_free(&ap_rep); + data_blob_free(&session_key); + passwd_free(&pw); + return ERROR_NT(ret); + } + } else { ret = make_server_info_pw(&server_info, real_username, pw); + if ( !NT_STATUS_IS_OK(ret) ) { DEBUG(1,("make_server_info_from_pw failed!\n")); SAFE_FREE(client); @@ -284,15 +322,17 @@ static int reply_spnego_kerberos(connection_struct *conn, passwd_free(&pw); return ERROR_NT(ret); } + + /* make_server_info_pw does not set the domain. Without this we end up + * with the local netbios name in substitutions for %D. */ + + if (server_info->sam_account != NULL) { + pdb_set_domain(server_info->sam_account, domain, PDB_SET); + } } - passwd_free(&pw); - /* make_server_info_pw does not set the domain. Without this we end up - * with the local netbios name in substitutions for %D. */ - if (server_info->sam_account != NULL) { - pdb_set_domain(server_info->sam_account, domain, PDB_SET); - } + passwd_free(&pw); /* register_vuid keeps the server info */ /* register_vuid takes ownership of session_key, no need to free after this. @@ -339,6 +379,7 @@ static int reply_spnego_kerberos(connection_struct *conn, data_blob_free(&ap_rep); data_blob_free(&ap_rep_wrapped); data_blob_free(&response); + talloc_destroy(mem_ctx); return -1; /* already replied */ } @@ -348,6 +389,8 @@ static int reply_spnego_kerberos(connection_struct *conn, Send a session setup reply, wrapped in SPNEGO. Get vuid and check first. End the NTLMSSP exchange context if we are OK/complete fail + This should be split into two functions, one to handle each + leg of the NTLM auth steps. ***************************************************************************/ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *outbuf, @@ -422,6 +465,7 @@ static BOOL reply_spnego_ntlmssp(connection_struct *conn, char *inbuf, char *out and the other end, that we are not finished yet. */ if (!ret || !NT_STATUS_EQUAL(nt_status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { + /* NB. This is *NOT* an error case. JRA */ auth_ntlmssp_end(auth_ntlmssp_state); /* Kill the intermediate vuid */ invalidate_vuid(vuid); @@ -660,7 +704,7 @@ static int reply_sesssetup_and_X_spnego(connection_struct *conn, char *inbuf, return ret; } - if (strncmp(blob1.data, "NTLMSSP", 7) == 0) { + if (strncmp((char *)(blob1.data), "NTLMSSP", 7) == 0) { DATA_BLOB chal; NTSTATUS nt_status; if (!vuser->auth_ntlmssp_state) { diff --git a/source3/smbd/trans2.c b/source3/smbd/trans2.c index 38363bf66ae..f0b7812a1e0 100644 --- a/source3/smbd/trans2.c +++ b/source3/smbd/trans2.c @@ -27,7 +27,6 @@ extern int max_send; extern enum protocol_types Protocol; extern int smb_read_error; -extern int global_oplock_break; extern uint32 global_client_caps; extern struct current_user current_user; @@ -2789,7 +2788,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * delete_pending = get_delete_on_close_flag(sbuf.st_dev, - sbuf.st_ino); + sbuf.st_ino, + fname); } else { /* * Original code - this is an open file. @@ -2804,7 +2804,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * pos = fsp->fh->position_information; delete_pending = get_delete_on_close_flag(sbuf.st_dev, - sbuf.st_ino); + sbuf.st_ino, + fname); access_mask = fsp->access_mask; } } else { @@ -2847,7 +2848,8 @@ static int call_trans2qfilepathinfo(connection_struct *conn, char *inbuf, char * } delete_pending = get_delete_on_close_flag(sbuf.st_dev, - sbuf.st_ino); + sbuf.st_ino, + fname); if (delete_pending) { return ERROR_NT(NT_STATUS_DELETE_PENDING); } @@ -3454,91 +3456,6 @@ total_data=%u (should be %u)\n", (unsigned int)total_data, (unsigned int)IVAL(pd return(-1); } -/**************************************************************************** - Deal with the internal needs of setting the delete on close flag. Note that - as the tdb locking is recursive, it is safe to call this from within - open_file_shared. JRA. -****************************************************************************/ - -NTSTATUS can_set_delete_on_close(files_struct *fsp, BOOL delete_on_close, - uint32 dosmode) -{ - if (!delete_on_close) { - return NT_STATUS_OK; - } - - /* - * Only allow delete on close for writable files. - */ - - if ((dosmode & aRONLY) && - !lp_delete_readonly(SNUM(fsp->conn))) { - DEBUG(10,("can_set_delete_on_close: file %s delete on close " - "flag set but file attribute is readonly.\n", - fsp->fsp_name )); - return NT_STATUS_CANNOT_DELETE; - } - - /* - * Only allow delete on close for writable shares. - */ - - if (!CAN_WRITE(fsp->conn)) { - DEBUG(10,("can_set_delete_on_close: file %s delete on " - "close flag set but write access denied on share.\n", - fsp->fsp_name )); - return NT_STATUS_ACCESS_DENIED; - } - - /* - * Only allow delete on close for files/directories opened with delete - * intent. - */ - - if (!(fsp->access_mask & DELETE_ACCESS)) { - DEBUG(10,("can_set_delete_on_close: file %s delete on " - "close flag set but delete access denied.\n", - fsp->fsp_name )); - return NT_STATUS_ACCESS_DENIED; - } - - return NT_STATUS_OK; -} - -/**************************************************************************** - Sets the delete on close flag over all share modes on this file. - Modify the share mode entry for all files open - on this device and inode to tell other smbds we have - changed the delete on close flag. This will be noticed - in the close code, the last closer will delete the file - if flag is set. -****************************************************************************/ - -NTSTATUS set_delete_on_close(files_struct *fsp, BOOL delete_on_close) -{ - DEBUG(10,("set_delete_on_close: %s delete on close flag for " - "fnum = %d, file %s\n", - delete_on_close ? "Adding" : "Removing", fsp->fnum, - fsp->fsp_name )); - - if (fsp->is_directory || fsp->is_stat) - return NT_STATUS_OK; - - if (lock_share_entry_fsp(fsp) == False) - return NT_STATUS_ACCESS_DENIED; - - if (!modify_delete_flag(fsp->dev, fsp->inode, delete_on_close)) { - DEBUG(0,("set_delete_on_close: failed to change delete " - "on close flag for file %s\n", - fsp->fsp_name )); - unlock_share_entry_fsp(fsp); - return NT_STATUS_ACCESS_DENIED; - } - - unlock_share_entry_fsp(fsp); - return NT_STATUS_OK; -} - /**************************************************************************** Set a hard link (called by UNIX extensions and by NT rename with HARD link code. @@ -3912,16 +3829,6 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char if (fd == -1) { files_struct *new_fsp = NULL; - if(global_oplock_break) { - /* Queue this file modify as we are the process of an oplock break. */ - - DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being ")); - DEBUGADD(2,( "in oplock break state.\n")); - - push_oplock_pending_smb_message(inbuf, length); - return -1; - } - new_fsp = open_file_ntcreate(conn, fname, &sbuf, FILE_WRITE_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE, @@ -4003,9 +3910,8 @@ static int call_trans2setfilepathinfo(connection_struct *conn, char *inbuf, char } /* The set is across all open files on this dev/inode pair. */ - status =set_delete_on_close(fsp, delete_on_close); - if (!NT_STATUS_IS_OK(status)) { - return ERROR_NT(status); + if (!set_delete_on_close(fsp, delete_on_close)) { + return ERROR_NT(NT_STATUS_ACCESS_DENIED); } SSVAL(params,0,0); @@ -4456,16 +4362,6 @@ size = %.0f, uid = %u, gid = %u, raw perms = 0%o\n", if (fd == -1) { files_struct *new_fsp = NULL; - if(global_oplock_break) { - /* Queue this file modify as we are the process of an oplock break. */ - - DEBUG(2,("call_trans2setfilepathinfo: queueing message due to being ")); - DEBUGADD(2,( "in oplock break state.\n")); - - push_oplock_pending_smb_message(inbuf, length); - return -1; - } - new_fsp = open_file_ntcreate(conn, fname, &sbuf, FILE_WRITE_DATA, FILE_SHARE_READ|FILE_SHARE_WRITE, @@ -4859,18 +4755,6 @@ int reply_trans2(connection_struct *conn, unsigned int num_params, num_params_sofar, num_data, num_data_sofar; START_PROFILE(SMBtrans2); - if(global_oplock_break && (tran_call == TRANSACT2_OPEN)) { - /* Queue this open message as we are the process of an - * oplock break. */ - - DEBUG(2,("reply_trans2: queueing message trans2open due to being ")); - DEBUGADD(2,( "in oplock break state.\n")); - - push_oplock_pending_smb_message(inbuf, length); - END_PROFILE(SMBtrans2); - return -1; - } - if (IS_IPC(conn) && (tran_call != TRANSACT2_OPEN) && (tran_call != TRANSACT2_GET_DFS_REFERRAL)) { END_PROFILE(SMBtrans2); diff --git a/source3/tdb/tdbdump.c b/source3/tdb/tdbdump.c index 17ae536bc4a..3efb29e44c1 100644 --- a/source3/tdb/tdbdump.c +++ b/source3/tdb/tdbdump.c @@ -49,10 +49,10 @@ static void print_data(TDB_DATA d) static int traverse_fn(TDB_CONTEXT *tdb, TDB_DATA key, TDB_DATA dbuf, void *state) { printf("{\n"); - printf("key(%d) = \"",key.dsize); + printf("key(%d) = \"", (int)key.dsize); print_data(key); printf("\"\n"); - printf("data(%d) = \"",dbuf.dsize); + printf("data(%d) = \"", (int)dbuf.dsize); print_data(dbuf); printf("\"\n"); printf("}\n"); diff --git a/source3/tdb/tdbtool.c b/source3/tdb/tdbtool.c index d9e7b9315a0..8aa57af7ab7 100644 --- a/source3/tdb/tdbtool.c +++ b/source3/tdb/tdbtool.c @@ -331,7 +331,7 @@ static void move_rec(char *keyname, size_t keylen, char* tdbname) static int print_conn_key(TDB_DATA key) { - printf( "\nkey %d bytes\n", key.dsize); + printf( "\nkey %d bytes\n", (int)key.dsize); printf( "pid =%5d ", ((connections_key*)key.dptr)->pid); printf( "cnum =%10d ", ((connections_key*)key.dptr)->cnum); printf( "name =[%s]\n", ((connections_key*)key.dptr)->name); @@ -340,7 +340,7 @@ static int print_conn_key(TDB_DATA key) static int print_conn_data(TDB_DATA dbuf) { - printf( "\ndata %d bytes\n", dbuf.dsize); + printf( "\ndata %d bytes\n", (int)dbuf.dsize); printf( "pid =%5d ", ((connections_data*)dbuf.dptr)->pid); printf( "cnum =%10d ", ((connections_data*)dbuf.dptr)->cnum); printf( "name =[%s]\n", ((connections_data*)dbuf.dptr)->name); @@ -373,16 +373,16 @@ static int print_crec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *s static int print_arec(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) { - printf("\nkey %d bytes\n", key.dsize); + printf("\nkey %d bytes\n", (int)key.dsize); print_asc(key.dptr, key.dsize); - printf("\ndata %d bytes\n", dbuf.dsize); + printf("\ndata %d bytes\n", (int)dbuf.dsize); print_data(dbuf.dptr, dbuf.dsize); return 0; } static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) { - printf("key %d bytes: ", key.dsize); + printf("key %d bytes: ", (int)key.dsize); print_asc(key.dptr, key.dsize); printf("\n"); return 0; @@ -390,7 +390,7 @@ static int print_key(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *st static int print_hexkey(TDB_CONTEXT *the_tdb, TDB_DATA key, TDB_DATA dbuf, void *state) { - printf("key %d bytes\n", key.dsize); + printf("key %d bytes\n", (int)key.dsize); print_data(key.dptr, key.dsize); printf("\n"); return 0; diff --git a/source3/tdb/tdbutil.c b/source3/tdb/tdbutil.c index 47f1bb2dc24..e27880e5ea0 100644 --- a/source3/tdb/tdbutil.c +++ b/source3/tdb/tdbutil.c @@ -566,7 +566,12 @@ int tdb_unpack(char *buf, int bufsize, const char *fmt, ...) p = va_arg(ap, void **); if (bufsize < len) goto no_space; - *p = (void *)IVAL(buf, 0); + /* + * This isn't a real pointer - only a token (1 or 0) + * to mark the fact a pointer is present. + */ + + *p = (void *)(IVAL(buf, 0) ? (void *)1 : NULL); break; case 'P': s = va_arg(ap,char *); diff --git a/source3/torture/locktest2.c b/source3/torture/locktest2.c index d0b502c74e7..fc180bfafe2 100644 --- a/source3/torture/locktest2.c +++ b/source3/torture/locktest2.c @@ -133,12 +133,12 @@ static BOOL try_unlock(struct cli_state *c, int fstype, return False; } -static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, int pid, +static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, enum brl_type lock_type, br_off start, br_off size) { printf("%6d %05x:%05x %s %.0f:%.0f(%.0f)\n", - (int)pid, (int)dev, (int)ino, + (int)procid_to_pid(&pid), (int)dev, (int)ino, lock_type==READ_LOCK?"R":"W", (double)start, (double)start+size-1,(double)size); diff --git a/source3/torture/mangle_test.c b/source3/torture/mangle_test.c index df0855d93d7..9ce6afa038f 100644 --- a/source3/torture/mangle_test.c +++ b/source3/torture/mangle_test.c @@ -98,7 +98,7 @@ static BOOL test_one(struct cli_state *cli, const char *name) } else { TDB_DATA namedata; /* store it for later */ - namedata.dptr = name; + namedata.dptr = CONST_DISCARD(char *, name); namedata.dsize = strlen(name)+1; tdb_store_bystring(tdb, shortname, namedata, TDB_REPLACE); } diff --git a/source3/torture/msgtest.c b/source3/torture/msgtest.c index ac55d703276..d691ab32f1d 100644 --- a/source3/torture/msgtest.c +++ b/source3/torture/msgtest.c @@ -28,7 +28,7 @@ static int pong_count; /**************************************************************************** a useful function for testing the message system ****************************************************************************/ -void pong_message(int msg_type, pid_t src, void *buf, size_t len) +void pong_message(int msg_type, struct process_id src, void *buf, size_t len) { pong_count++; } @@ -56,7 +56,7 @@ void pong_message(int msg_type, pid_t src, void *buf, size_t len) message_register(MSG_PONG, pong_message); for (i=0;i ASN -> Int %d\n", values[i], val); + ok = False; + } + } + + return ok ? 0 : 1; +} diff --git a/source3/torture/t_strappend.c b/source3/torture/t_strappend.c new file mode 100644 index 00000000000..becc691c7f9 --- /dev/null +++ b/source3/torture/t_strappend.c @@ -0,0 +1,45 @@ +/* + * Copyright (C) 2005 by Volker Lendecke + * + * Test harness for sprintf_append + */ + +#include "includes.h" +#include + +int main(int argc, char *argv[]) +{ + TALLOC_CTX *mem_ctx; + char *string = NULL; + int len = 0; + int bufsize = 4; + int i; + + mem_ctx = talloc_init("t_strappend"); + if (mem_ctx == NULL) { + fprintf(stderr, "talloc_init failed\n"); + return 1; + } + + sprintf_append(mem_ctx, &string, &len, &bufsize, ""); + assert(strlen(string) == len); + sprintf_append(mem_ctx, &string, &len, &bufsize, ""); + assert(strlen(string) == len); + sprintf_append(mem_ctx, &string, &len, &bufsize, + "01234567890123456789012345678901234567890123456789\n"); + assert(strlen(string) == len); + + + for (i=0; i<(100000); i++) { + if (i%1000 == 0) { + printf("%d %d\r", i, bufsize); + fflush(stdout); + } + sprintf_append(mem_ctx, &string, &len, &bufsize, "%d\n", i); + assert(strlen(string) == len); + } + + talloc_destroy(mem_ctx); + + return 0; +} diff --git a/source3/torture/torture.c b/source3/torture/torture.c index 11cea53188f..8ad567f1778 100644 --- a/source3/torture/torture.c +++ b/source3/torture/torture.c @@ -698,7 +698,6 @@ static BOOL run_netbench(int client) { struct cli_state *cli; int i; - fstring fname; pstring line; char cname[20]; FILE *f; diff --git a/source3/torture/vfstest.c b/source3/torture/vfstest.c index 69acd01c1a4..b5ccf930bc6 100644 --- a/source3/torture/vfstest.c +++ b/source3/torture/vfstest.c @@ -38,7 +38,7 @@ extern pstring user_socket_options; /**************************************************************************** handle completion of commands for readline ****************************************************************************/ -static char **completion_fn(char *text, int start, int end) +static char **completion_fn(const char *text, int start, int end) { #define MAX_COMPLETIONS 100 char **matches; diff --git a/source3/utils/log2pcaphex.c b/source3/utils/log2pcaphex.c index d07dc2a2115..24412cbe85e 100644 --- a/source3/utils/log2pcaphex.c +++ b/source3/utils/log2pcaphex.c @@ -200,7 +200,7 @@ void read_log_msg(FILE *in, unsigned char **_buffer, long *buffersize, long *dat long read_log_data(FILE *in, unsigned char *buffer, long data_length) { long i, addr; char real[2][16]; int ret; - unsigned char tmp; + unsigned int tmp; for(i = 0; i < data_length; i++) { if(i % 16 == 0){ if(i != 0) { /* Read data after each line */ @@ -213,7 +213,7 @@ long read_log_data(FILE *in, unsigned char *buffer, long data_length) } assert(addr == i); } - if(!fscanf(in, "%02lX", &tmp)) { + if(!fscanf(in, "%02X", &tmp)) { if(!quiet)fprintf(stderr, "Only first %ld bytes are logged, packet trace will be incomplete\nTry a higher log level\n", i-1); return i-1; } @@ -230,7 +230,7 @@ int main (int argc, char **argv) poptContext pc; char buffer[4096]; long data_offset, data_length; - long data_bytes_read; + long data_bytes_read = 0; int in_packet = 0; struct poptOption long_options[] = { POPT_AUTOHELP diff --git a/source3/utils/net.c b/source3/utils/net.c index e9332f58f7b..4d9dec4b85b 100644 --- a/source3/utils/net.c +++ b/source3/utils/net.c @@ -219,36 +219,39 @@ NTSTATUS connect_to_ipc_anonymous(struct cli_state **c, * * @return Normal NTSTATUS return. **/ -NTSTATUS connect_dst_pipe(struct cli_state **cli_dst, int pipe_num, BOOL *got_pipe) +NTSTATUS connect_dst_pipe(struct cli_state **cli_dst, struct rpc_pipe_client **pp_pipe_hnd, int pipe_num) { NTSTATUS nt_status; char *server_name = SMB_STRDUP("127.0.0.1"); struct cli_state *cli_tmp = NULL; + struct rpc_pipe_client *pipe_hnd = NULL; if (opt_destination) server_name = SMB_STRDUP(opt_destination); /* make a connection to a named pipe */ nt_status = connect_to_ipc(&cli_tmp, NULL, server_name); - if (!NT_STATUS_IS_OK(nt_status)) + if (!NT_STATUS_IS_OK(nt_status)) { return nt_status; + } - if (!cli_nt_session_open(cli_tmp, pipe_num)) { + pipe_hnd = cli_rpc_pipe_open_noauth(cli_tmp, pipe_num, &nt_status); + if (!pipe_hnd) { DEBUG(0, ("couldn't not initialize pipe\n")); cli_shutdown(cli_tmp); - return NT_STATUS_UNSUCCESSFUL; + return nt_status; } *cli_dst = cli_tmp; - *got_pipe = True; + *pp_pipe_hnd = pipe_hnd; return nt_status; } - /**************************************************************************** - Use the local machine's password for this session + Use the local machine's password for this session. ****************************************************************************/ + int net_use_machine_password(void) { char *user_name = NULL; diff --git a/source3/utils/net.h b/source3/utils/net.h index a2df6596b47..2df13cfb8f1 100644 --- a/source3/utils/net.h +++ b/source3/utils/net.h @@ -23,16 +23,21 @@ * include */ -typedef NTSTATUS (*rpc_command_fn)(const DOM_SID *, const char *, - struct cli_state *, TALLOC_CTX *, int, const char **); - +typedef NTSTATUS (*rpc_command_fn)(const DOM_SID *, + const char *, + struct cli_state *cli, + struct rpc_pipe_client *, + TALLOC_CTX *, + int, + const char **); + typedef struct copy_clistate { TALLOC_CTX *mem_ctx; struct cli_state *cli_share_src; struct cli_state *cli_share_dst; char *cwd; uint16 attribute; -}copy_clistate; +}copy_clistate; /* INCLUDE FILES */ diff --git a/source3/utils/net_ads.c b/source3/utils/net_ads.c index 6a58fa9fac4..49a7f1cc2dd 100644 --- a/source3/utils/net_ads.c +++ b/source3/utils/net_ads.c @@ -969,7 +969,8 @@ static int net_ads_printer_info(int argc, const char **argv) return 0; } -void do_drv_upgrade_printer(int msg_type, pid_t src, void *buf, size_t len) +void do_drv_upgrade_printer(int msg_type, struct process_id src, + void *buf, size_t len) { return; } @@ -980,6 +981,7 @@ static int net_ads_printer_publish(int argc, const char **argv) ADS_STATUS rc; const char *servername, *printername; struct cli_state *cli; + struct rpc_pipe_client *pipe_hnd; struct in_addr server_ip; NTSTATUS nt_status; TALLOC_CTX *mem_ctx = talloc_init("net_ads_printer_publish"); @@ -1038,8 +1040,9 @@ static int net_ads_printer_publish(int argc, const char **argv) asprintf(&prt_dn, "cn=%s-%s,%s", srv_cn[0], printername, srv_dn); - cli_nt_session_open(cli, PI_SPOOLSS); - get_remote_printer_publishing_data(cli, mem_ctx, &mods, printername); + pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SPOOLSS, &nt_status); + get_remote_printer_publishing_data(pipe_hnd, mem_ctx, &mods, + printername); rc = ads_add_printer_entry(ads, prt_dn, mem_ctx, &mods); if (!ADS_ERR_OK(rc)) { diff --git a/source3/utils/net_rpc.c b/source3/utils/net_rpc.c index e80e8e6f5c0..f1522ef1582 100644 --- a/source3/utils/net_rpc.c +++ b/source3/utils/net_rpc.c @@ -4,6 +4,7 @@ Copyright (C) 2001 Andrew Bartlett (abartlet@samba.org) Copyright (C) 2002 Jim McDonough (jmcd@us.ibm.com) Copyright (C) 2004 Guenther Deschner (gd@samba.org) + Copyright (C) 2005 Jeremy Allison (jra@samba.org) This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -50,24 +51,26 @@ static int net_mode_share; static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem_ctx, char **domain_name) { + struct rpc_pipe_client *lsa_pipe; DOM_SID *domain_sid; POLICY_HND pol; NTSTATUS result = NT_STATUS_OK; uint32 info_class = 5; - if (!cli_nt_session_open (cli, PI_LSARPC)) { + lsa_pipe = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result); + if (!lsa_pipe) { fprintf(stderr, "could not initialise lsa pipe\n"); goto error; } - result = cli_lsa_open_policy(cli, mem_ctx, False, + result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, False, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); if (!NT_STATUS_IS_OK(result)) { goto error; } - result = cli_lsa_query_info_policy(cli, mem_ctx, &pol, info_class, + result = rpccli_lsa_query_info_policy(lsa_pipe, mem_ctx, &pol, info_class, domain_name, &domain_sid); if (!NT_STATUS_IS_OK(result)) { error: @@ -80,8 +83,10 @@ static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem exit(1); } - cli_lsa_close(cli, mem_ctx, &pol); - cli_nt_session_close(cli); + if (lsa_pipe) { + rpccli_lsa_close(lsa_pipe, mem_ctx, &pol); + cli_rpc_pipe_close(lsa_pipe); + } return domain_sid; } @@ -98,21 +103,26 @@ static DOM_SID *net_get_remote_domain_sid(struct cli_state *cli, TALLOC_CTX *mem * @return A shell status integer (0 for success) */ -int run_rpc_command(struct cli_state *cli_arg, const int pipe_idx, int conn_flags, - rpc_command_fn fn, - int argc, const char **argv) +int run_rpc_command(struct cli_state *cli_arg, + const int pipe_idx, + int conn_flags, + rpc_command_fn fn, + int argc, + const char **argv) { struct cli_state *cli = NULL; + struct rpc_pipe_client *pipe_hnd = NULL; TALLOC_CTX *mem_ctx; NTSTATUS nt_status; DOM_SID *domain_sid; char *domain_name; /* make use of cli_state handed over as an argument, if possible */ - if (!cli_arg) + if (!cli_arg) { cli = net_make_ipc_connection(conn_flags); - else + } else { cli = cli_arg; + } if (!cli) { return -1; @@ -129,14 +139,31 @@ int run_rpc_command(struct cli_state *cli_arg, const int pipe_idx, int conn_flag domain_sid = net_get_remote_domain_sid(cli, mem_ctx, &domain_name); if (!(conn_flags & NET_FLAGS_NO_PIPE)) { - if (!cli_nt_session_open(cli, pipe_idx)) { - DEBUG(0, ("Could not initialise pipe\n")); - cli_shutdown(cli); - return -1; + if (lp_client_schannel() && (pipe_idx == PI_NETLOGON)) { + /* Always try and create an schannel netlogon pipe. */ + pipe_hnd = cli_rpc_pipe_open_schannel(cli, pipe_idx, + PIPE_AUTH_LEVEL_PRIVACY, + domain_name, + &nt_status); + if (!pipe_hnd) { + DEBUG(0, ("Could not initialise schannel netlogon pipe. Error was %s\n", + nt_errstr(nt_status) )); + cli_shutdown(cli); + return -1; + } + } else { + pipe_hnd = cli_rpc_pipe_open_noauth(cli, pipe_idx, &nt_status); + if (!pipe_hnd) { + DEBUG(0, ("Could not initialise pipe %s. Error was %s\n", + cli_get_pipe_name(pipe_idx), + nt_errstr(nt_status) )); + cli_shutdown(cli); + return -1; + } } } - nt_status = fn(domain_sid, domain_name, cli, mem_ctx, argc, argv); + nt_status = fn(domain_sid, domain_name, cli, pipe_hnd, mem_ctx, argc, argv); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(1, ("rpc command function failed! (%s)\n", nt_errstr(nt_status))); @@ -145,23 +172,20 @@ int run_rpc_command(struct cli_state *cli_arg, const int pipe_idx, int conn_flag } if (!(conn_flags & NET_FLAGS_NO_PIPE)) { - if (cli->pipes[cli->pipe_idx].fnum) - cli_nt_session_close(cli); + if (pipe_hnd) { + cli_rpc_pipe_close(pipe_hnd); + } } /* close the connection only if it was opened here */ - if (!cli_arg) + if (!cli_arg) { cli_shutdown(cli); + } talloc_destroy(mem_ctx); - return (!NT_STATUS_IS_OK(nt_status)); } - -/****************************************************************************/ - - /** * Force a change of the trust acccount password. * @@ -178,11 +202,16 @@ int run_rpc_command(struct cli_state *cli_arg, const int pipe_idx, int conn_flag * @return Normal NTSTATUS return. **/ -static NTSTATUS rpc_changetrustpw_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) { +static NTSTATUS rpc_changetrustpw_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) +{ - return trust_pw_find_change_and_store_it(cli, mem_ctx, opt_target_workgroup); + return trust_pw_find_change_and_store_it(pipe_hnd, mem_ctx, opt_target_workgroup); } /** @@ -202,10 +231,6 @@ int net_rpc_changetrustpw(int argc, const char **argv) argc, argv); } - -/****************************************************************************/ - - /** * Join a domain, the old way. * @@ -226,16 +251,29 @@ int net_rpc_changetrustpw(int argc, const char **argv) * @return Normal NTSTATUS return. **/ -static NTSTATUS rpc_oldjoin_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, - int argc, const char **argv) { +static NTSTATUS rpc_oldjoin_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) +{ fstring trust_passwd; unsigned char orig_trust_passwd_hash[16]; NTSTATUS result; uint32 sec_channel_type; + pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, &result); + if (!pipe_hnd) { + DEBUG(0,("rpc_oldjoin_internals: netlogon pipe open to machine %s failed. " + "error was %s\n", + cli->desthost, + nt_errstr(result) )); + return result; + } + /* check what type of join - if the user want's to join as a BDC, the server must agree that we are a BDC. @@ -258,7 +296,7 @@ static NTSTATUS rpc_oldjoin_internals(const DOM_SID *domain_sid, const char *dom E_md4hash(trust_passwd, orig_trust_passwd_hash); - result = trust_pw_change_and_store_it(cli, mem_ctx, opt_target_workgroup, + result = trust_pw_change_and_store_it(pipe_hnd, mem_ctx, opt_target_workgroup, orig_trust_passwd_hash, sec_channel_type); @@ -287,7 +325,7 @@ static NTSTATUS rpc_oldjoin_internals(const DOM_SID *domain_sid, const char *dom static int net_rpc_perform_oldjoin(int argc, const char **argv) { return run_rpc_command(NULL, PI_NETLOGON, - NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, + NET_FLAGS_NO_PIPE | NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, rpc_oldjoin_internals, argc, argv); } @@ -356,8 +394,6 @@ int net_rpc_join(int argc, const char **argv) return net_rpc_join_newstyle(argc, argv); } - - /** * display info about a rpc domain * @@ -374,10 +410,13 @@ int net_rpc_join(int argc, const char **argv) * @return Normal NTSTATUS return. **/ -static NTSTATUS -rpc_info_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, int argc, const char **argv) +static NTSTATUS rpc_info_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { POLICY_HND connect_pol, domain_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; @@ -387,14 +426,14 @@ rpc_info_internals(const DOM_SID *domain_sid, const char *domain_name, sid_to_string(sid_str, domain_sid); /* Get sam policy handle */ - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) { @@ -402,7 +441,7 @@ rpc_info_internals(const DOM_SID *domain_sid, const char *domain_name, } ZERO_STRUCT(ctr); - result = cli_samr_query_dom_info(cli, mem_ctx, &domain_pol, + result = rpccli_samr_query_dom_info(pipe_hnd, mem_ctx, &domain_pol, 2, &ctr); if (NT_STATUS_IS_OK(result)) { TALLOC_CTX *ctx = talloc_init("rpc_info_internals"); @@ -419,13 +458,13 @@ rpc_info_internals(const DOM_SID *domain_sid, const char *domain_name, return result; } - /** * 'net rpc info' entrypoint. * @param argc Standard main() style argc * @param argc Standard main() style argv. Initial components are already * stripped **/ + int net_rpc_info(int argc, const char **argv) { return run_rpc_command(NULL, PI_SAMR, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, @@ -433,7 +472,6 @@ int net_rpc_info(int argc, const char **argv) argc, argv); } - /** * Fetch domain SID into the local secrets.tdb * @@ -450,10 +488,13 @@ int net_rpc_info(int argc, const char **argv) * @return Normal NTSTATUS return. **/ -static NTSTATUS -rpc_getsid_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, int argc, const char **argv) +static NTSTATUS rpc_getsid_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { fstring sid_str; @@ -469,13 +510,13 @@ rpc_getsid_internals(const DOM_SID *domain_sid, const char *domain_name, return NT_STATUS_OK; } - /** * 'net rpc getsid' entrypoint. * @param argc Standard main() style argc * @param argc Standard main() style argv. Initial components are already * stripped **/ + int net_rpc_getsid(int argc, const char **argv) { return run_rpc_command(NULL, PI_SAMR, NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC, @@ -483,7 +524,6 @@ int net_rpc_getsid(int argc, const char **argv) argc, argv); } - /****************************************************************************/ /** @@ -514,9 +554,13 @@ static int rpc_user_usage(int argc, const char **argv) * @return Normal NTSTATUS return. **/ -static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) { +static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, const char **argv) +{ POLICY_HND connect_pol, domain_pol, user_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; @@ -534,7 +578,7 @@ static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, const char *do /* Get sam policy handle */ - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { goto done; @@ -542,7 +586,7 @@ static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, const char *do /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) { @@ -554,7 +598,7 @@ static NTSTATUS rpc_user_add_internals(const DOM_SID *domain_sid, const char *do acb_info = ACB_NORMAL; unknown = 0xe005000b; /* No idea what this is - a permission mask? */ - result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol, + result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol, acct_name, acb_info, unknown, &user_pol, &user_rid); if (!NT_STATUS_IS_OK(result)) { @@ -604,10 +648,12 @@ static int rpc_user_add(int argc, const char **argv) **/ static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid, - const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, - int argc, const char **argv) + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; POLICY_HND connect_pol, domain_pol, user_pol; @@ -619,14 +665,14 @@ static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid, } /* Get sam policy and domain handles */ - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, domain_sid, &domain_pol); @@ -640,7 +686,7 @@ static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid, uint32 *user_rids, num_rids, *name_types; uint32 flags = 0x000003e8; /* Unknown */ - result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, + result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, flags, 1, &argv[0], &num_rids, &user_rids, &name_types); @@ -649,7 +695,7 @@ static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid, goto done; } - result = cli_samr_open_user(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol, MAXIMUM_ALLOWED_ACCESS, user_rids[0], &user_pol); @@ -660,23 +706,22 @@ static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid, /* Delete user */ - result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol); + result = rpccli_samr_delete_dom_user(pipe_hnd, mem_ctx, &user_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } /* Display results */ - if (!NT_STATUS_IS_OK(result)) { + if (!NT_STATUS_IS_OK(result)) { d_printf("Failed to delete user account - %s\n", nt_errstr(result)); - } else { - d_printf("Deleted user account\n"); - } + } else { + d_printf("Deleted user account\n"); + } done: return result; - -} +} /** * Rename a user on a remote RPC server @@ -694,10 +739,14 @@ static NTSTATUS rpc_user_del_internals(const DOM_SID *domain_sid, * @return Normal NTSTATUS return. **/ -static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) { - +static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) +{ POLICY_HND connect_pol, domain_pol, user_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; uint32 info_level = 7; @@ -725,7 +774,7 @@ static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, const char /* Get sam policy handle */ - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { goto done; @@ -733,7 +782,7 @@ static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, const char /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) { @@ -742,7 +791,7 @@ static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, const char names = TALLOC_ARRAY(mem_ctx, const char *, num_names); names[0] = old_name; - result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, + result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, flags, num_names, names, &num_rids, &user_rid, &name_types); if (!NT_STATUS_IS_OK(result)) { @@ -750,7 +799,7 @@ static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, const char } /* Open domain user */ - result = cli_samr_open_user(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol, MAXIMUM_ALLOWED_ACCESS, user_rid[0], &user_pol); if (!NT_STATUS_IS_OK(result)) { @@ -758,7 +807,7 @@ static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, const char } /* Query user info */ - result = cli_samr_query_userinfo(cli, mem_ctx, &user_pol, + result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, &user_pol, info_level, &user_ctr); if (!NT_STATUS_IS_OK(result)) { @@ -771,7 +820,7 @@ static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, const char init_sam_user_info7(&info7, new_name); /* Set new name */ - result = cli_samr_set_userinfo(cli, mem_ctx, &user_pol, + result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, info_level, &cli->user_session_key, &ctr); if (!NT_STATUS_IS_OK(result)) { @@ -788,7 +837,6 @@ static NTSTATUS rpc_user_rename_internals(const DOM_SID *domain_sid, const char return result; } - /** * Rename a user on a remote RPC server * @@ -838,10 +886,12 @@ static int rpc_user_delete(int argc, const char **argv) **/ static NTSTATUS rpc_user_password_internals(const DOM_SID *domain_sid, - const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, - int argc, const char **argv) + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; POLICY_HND connect_pol, domain_pol, user_pol; @@ -870,14 +920,14 @@ static NTSTATUS rpc_user_password_internals(const DOM_SID *domain_sid, /* Get sam policy and domain handles */ - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, domain_sid, &domain_pol); @@ -891,7 +941,7 @@ static NTSTATUS rpc_user_password_internals(const DOM_SID *domain_sid, uint32 *user_rids, num_rids, *name_types; uint32 flags = 0x000003e8; /* Unknown */ - result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, + result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, flags, 1, &user, &num_rids, &user_rids, &name_types); @@ -900,7 +950,7 @@ static NTSTATUS rpc_user_password_internals(const DOM_SID *domain_sid, goto done; } - result = cli_samr_open_user(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol, MAXIMUM_ALLOWED_ACCESS, user_rids[0], &user_pol); @@ -921,7 +971,7 @@ static NTSTATUS rpc_user_password_internals(const DOM_SID *domain_sid, ctr.switch_value = 24; ctr.info.id24 = &p24; - result = cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 24, + result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 24, &cli->user_session_key, &ctr); if (!NT_STATUS_IS_OK(result)) { @@ -967,10 +1017,13 @@ static int rpc_user_password(int argc, const char **argv) * @return Normal NTSTATUS return. **/ -static NTSTATUS -rpc_user_info_internals(const DOM_SID *domain_sid, const char *domain_name, +static NTSTATUS rpc_user_info_internals(const DOM_SID *domain_sid, + const char *domain_name, struct cli_state *cli, - TALLOC_CTX *mem_ctx, int argc, const char **argv) + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { POLICY_HND connect_pol, domain_pol, user_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; @@ -987,31 +1040,31 @@ rpc_user_info_internals(const DOM_SID *domain_sid, const char *domain_name, } /* Get sam policy handle */ - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) goto done; /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) goto done; /* Get handle on user */ - result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, + result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, flags, 1, &argv[0], &num_rids, &rids, &name_types); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_open_user(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol, MAXIMUM_ALLOWED_ACCESS, rids[0], &user_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_query_usergroups(cli, mem_ctx, &user_pol, + result = rpccli_samr_query_usergroups(pipe_hnd, mem_ctx, &user_pol, &num_rids, &user_gids); if (!NT_STATUS_IS_OK(result)) goto done; @@ -1024,7 +1077,7 @@ rpc_user_info_internals(const DOM_SID *domain_sid, const char *domain_name, for (i = 0; i < num_rids; i++) rids[i] = user_gids[i].g_rid; - result = cli_samr_lookup_rids(cli, mem_ctx, &domain_pol, + result = rpccli_samr_lookup_rids(pipe_hnd, mem_ctx, &domain_pol, num_rids, rids, &num_names, &names, &name_types); @@ -1073,10 +1126,13 @@ static int rpc_user_info(int argc, const char **argv) * @return Normal NTSTATUS return. **/ -static NTSTATUS -rpc_user_list_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, int argc, const char **argv) +static NTSTATUS rpc_user_list_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { POLICY_HND connect_pol, domain_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; @@ -1086,7 +1142,7 @@ rpc_user_list_internals(const DOM_SID *domain_sid, const char *domain_name, /* Get sam policy handle */ - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { goto done; @@ -1094,7 +1150,7 @@ rpc_user_list_internals(const DOM_SID *domain_sid, const char *domain_name, /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) { @@ -1115,7 +1171,7 @@ rpc_user_list_internals(const DOM_SID *domain_sid, const char *domain_name, get_query_dispinfo_params( loop_count, &max_entries, &max_size); - result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol, + result = rpccli_samr_query_dispinfo(pipe_hnd, mem_ctx, &domain_pol, &start_idx, 1, &num_entries, max_entries, max_size, &ctr); loop_count++; @@ -1163,7 +1219,6 @@ int net_rpc_user(int argc, const char **argv) return net_run_function(argc, argv, func, rpc_user_usage); } - /****************************************************************************/ /** @@ -1195,10 +1250,12 @@ static int rpc_group_usage(int argc, const char **argv) **/ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid, - const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, - int argc, const char **argv) + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { POLICY_HND connect_pol, domain_pol, group_pol, user_pol; BOOL group_is_primary = False; @@ -1219,7 +1276,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid, return NT_STATUS_OK; /* ok? */ } - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { @@ -1227,7 +1284,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid, goto done; } - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, domain_sid, &domain_pol); @@ -1236,7 +1293,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid, goto done; } - result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, + result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, flags, 1, &argv[0], &num_rids, &group_rids, &name_types); @@ -1249,7 +1306,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid, switch (name_types[0]) { case SID_NAME_DOM_GRP: - result = cli_samr_open_group(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol, MAXIMUM_ALLOWED_ACCESS, group_rids[0], &group_pol); if (!NT_STATUS_IS_OK(result)) { @@ -1259,7 +1316,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid, group_rid = group_rids[0]; - result = cli_samr_query_groupmem(cli, mem_ctx, &group_pol, + result = rpccli_samr_query_groupmem(pipe_hnd, mem_ctx, &group_pol, &num_members, &group_rids, &group_attrs); @@ -1276,7 +1333,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid, /* Check if group is anyone's primary group */ for (i = 0; i < num_members; i++) { - result = cli_samr_open_user(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol, MAXIMUM_ALLOWED_ACCESS, group_rids[i], &user_pol); @@ -1287,7 +1344,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid, ZERO_STRUCT(user_ctr); - result = cli_samr_query_userinfo(cli, mem_ctx, &user_pol, + result = rpccli_samr_query_userinfo(pipe_hnd, mem_ctx, &user_pol, 21, &user_ctr); if (!NT_STATUS_IS_OK(result)) { @@ -1303,7 +1360,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid, group_is_primary = True; } - cli_samr_close(cli, mem_ctx, &user_pol); + rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol); } if (group_is_primary) { @@ -1318,7 +1375,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid, { if (opt_verbose) d_printf("Remove group member %d...",group_rids[i]); - result = cli_samr_del_groupmem(cli, mem_ctx, &group_pol, group_rids[i]); + result = rpccli_samr_del_groupmem(pipe_hnd, mem_ctx, &group_pol, group_rids[i]); if (NT_STATUS_IS_OK(result)) { if (opt_verbose) @@ -1330,12 +1387,12 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid, } } - result = cli_samr_delete_dom_group(cli, mem_ctx, &group_pol); + result = rpccli_samr_delete_dom_group(pipe_hnd, mem_ctx, &group_pol); break; /* removing a local group is easier... */ case SID_NAME_ALIAS: - result = cli_samr_open_alias(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol, MAXIMUM_ALLOWED_ACCESS, group_rids[0], &group_pol); @@ -1344,7 +1401,7 @@ static NTSTATUS rpc_group_delete_internals(const DOM_SID *domain_sid, goto done; } - result = cli_samr_delete_dom_alias(cli, mem_ctx, &group_pol); + result = rpccli_samr_delete_dom_alias(pipe_hnd, mem_ctx, &group_pol); break; default: d_printf("%s is of type %s. This command is only for deleting local or global groups\n", @@ -1373,10 +1430,13 @@ static int rpc_group_delete(int argc, const char **argv) argc,argv); } -static NTSTATUS -rpc_group_add_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, int argc, const char **argv) +static NTSTATUS rpc_group_add_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { POLICY_HND connect_pol, domain_pol, group_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; @@ -1390,20 +1450,20 @@ rpc_group_add_internals(const DOM_SID *domain_sid, const char *domain_name, /* Get sam policy handle */ - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) goto done; /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) goto done; /* Create the group */ - result = cli_samr_create_dom_group(cli, mem_ctx, &domain_pol, + result = rpccli_samr_create_dom_group(pipe_hnd, mem_ctx, &domain_pol, argv[0], MAXIMUM_ALLOWED_ACCESS, &group_pol); if (!NT_STATUS_IS_OK(result)) goto done; @@ -1415,7 +1475,7 @@ rpc_group_add_internals(const DOM_SID *domain_sid, const char *domain_name, group_info.switch_value1 = 4; init_samr_group_info4(&group_info.group.info4, opt_comment); - result = cli_samr_set_groupinfo(cli, mem_ctx, &group_pol, &group_info); + result = rpccli_samr_set_groupinfo(pipe_hnd, mem_ctx, &group_pol, &group_info); if (!NT_STATUS_IS_OK(result)) goto done; done: @@ -1427,10 +1487,13 @@ rpc_group_add_internals(const DOM_SID *domain_sid, const char *domain_name, return result; } -static NTSTATUS -rpc_alias_add_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, int argc, const char **argv) +static NTSTATUS rpc_alias_add_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { POLICY_HND connect_pol, domain_pol, alias_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; @@ -1444,20 +1507,20 @@ rpc_alias_add_internals(const DOM_SID *domain_sid, const char *domain_name, /* Get sam policy handle */ - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) goto done; /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) goto done; /* Create the group */ - result = cli_samr_create_dom_alias(cli, mem_ctx, &domain_pol, + result = rpccli_samr_create_dom_alias(pipe_hnd, mem_ctx, &domain_pol, argv[0], &alias_pol); if (!NT_STATUS_IS_OK(result)) goto done; @@ -1468,7 +1531,7 @@ rpc_alias_add_internals(const DOM_SID *domain_sid, const char *domain_name, alias_info.level = 3; init_samr_alias_info3(&alias_info.alias.info3, opt_comment); - result = cli_samr_set_aliasinfo(cli, mem_ctx, &alias_pol, &alias_info); + result = rpccli_samr_set_aliasinfo(pipe_hnd, mem_ctx, &alias_pol, &alias_info); if (!NT_STATUS_IS_OK(result)) goto done; done: @@ -1492,33 +1555,31 @@ static int rpc_group_add(int argc, const char **argv) argc, argv); } -static NTSTATUS -get_sid_from_name(struct cli_state *cli, TALLOC_CTX *mem_ctx, const char *name, - DOM_SID *sid, enum SID_NAME_USE *type) +static NTSTATUS get_sid_from_name(struct cli_state *cli, + TALLOC_CTX *mem_ctx, + const char *name, + DOM_SID *sid, + enum SID_NAME_USE *type) { - int current_pipe = cli->pipe_idx; - DOM_SID *sids = NULL; uint32 *types = NULL; + struct rpc_pipe_client *pipe_hnd; POLICY_HND lsa_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - if (current_pipe != PI_LSARPC) { - - if (current_pipe != -1) - cli_nt_session_close(cli); - - if (!cli_nt_session_open(cli, PI_LSARPC)) - goto done; + pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result); + if (!pipe_hnd) { + goto done; } - result = cli_lsa_open_policy(cli, mem_ctx, False, + result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, False, SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol); - if (!NT_STATUS_IS_OK(result)) + if (!NT_STATUS_IS_OK(result)) { goto done; + } - result = cli_lsa_lookup_names(cli, mem_ctx, &lsa_pol, 1, + result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &lsa_pol, 1, &name, &sids, &types); if (NT_STATUS_IS_OK(result)) { @@ -1526,13 +1587,11 @@ get_sid_from_name(struct cli_state *cli, TALLOC_CTX *mem_ctx, const char *name, *type = types[0]; } - cli_lsa_close(cli, mem_ctx, &lsa_pol); + rpccli_lsa_close(pipe_hnd, mem_ctx, &lsa_pol); done: - if (current_pipe != PI_LSARPC) { - cli_nt_session_close(cli); - if (current_pipe != -1) - cli_nt_session_open(cli, current_pipe); + if (pipe_hnd) { + cli_rpc_pipe_close(pipe_hnd); } if (!NT_STATUS_IS_OK(result) && (StrnCaseCmp(name, "S-", 2) == 0)) { @@ -1551,9 +1610,10 @@ get_sid_from_name(struct cli_state *cli, TALLOC_CTX *mem_ctx, const char *name, return result; } -static NTSTATUS -rpc_add_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, - const DOM_SID *group_sid, const char *member) +static NTSTATUS rpc_add_groupmem(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + const DOM_SID *group_sid, + const char *member) { POLICY_HND connect_pol, domain_pol; NTSTATUS result; @@ -1568,23 +1628,26 @@ rpc_add_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, sid_copy(&sid, group_sid); - if (!sid_split_rid(&sid, &group_rid)) + if (!sid_split_rid(&sid, &group_rid)) { return NT_STATUS_UNSUCCESSFUL; + } /* Get sam policy handle */ - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); - if (!NT_STATUS_IS_OK(result)) + if (!NT_STATUS_IS_OK(result)) { return result; + } /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &sid, &domain_pol); - if (!NT_STATUS_IS_OK(result)) + if (!NT_STATUS_IS_OK(result)) { return result; + } - result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, 1000, + result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000, 1, &member, &num_rids, &rids, &rid_types); @@ -1593,23 +1656,25 @@ rpc_add_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, goto done; } - result = cli_samr_open_group(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol, MAXIMUM_ALLOWED_ACCESS, group_rid, &group_pol); - if (!NT_STATUS_IS_OK(result)) + if (!NT_STATUS_IS_OK(result)) { goto done; + } - result = cli_samr_add_groupmem(cli, mem_ctx, &group_pol, rids[0]); + result = rpccli_samr_add_groupmem(pipe_hnd, mem_ctx, &group_pol, rids[0]); done: - cli_samr_close(cli, mem_ctx, &connect_pol); + rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol); return result; } -static NTSTATUS -rpc_add_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, - const DOM_SID *alias_sid, const char *member) +static NTSTATUS rpc_add_aliasmem(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + const DOM_SID *alias_sid, + const char *member) { POLICY_HND connect_pol, domain_pol; NTSTATUS result; @@ -1623,10 +1688,11 @@ rpc_add_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, sid_copy(&sid, alias_sid); - if (!sid_split_rid(&sid, &alias_rid)) + if (!sid_split_rid(&sid, &alias_rid)) { return NT_STATUS_UNSUCCESSFUL; + } - result = get_sid_from_name(cli, mem_ctx, member, + result = get_sid_from_name(pipe_hnd->cli, mem_ctx, member, &member_sid, &member_type); if (!NT_STATUS_IS_OK(result)) { @@ -1635,41 +1701,46 @@ rpc_add_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, } /* Get sam policy handle */ - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } - result = cli_samr_open_alias(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol, MAXIMUM_ALLOWED_ACCESS, alias_rid, &alias_pol); - if (!NT_STATUS_IS_OK(result)) + if (!NT_STATUS_IS_OK(result)) { return result; + } - result = cli_samr_add_aliasmem(cli, mem_ctx, &alias_pol, &member_sid); + result = rpccli_samr_add_aliasmem(pipe_hnd, mem_ctx, &alias_pol, &member_sid); - if (!NT_STATUS_IS_OK(result)) + if (!NT_STATUS_IS_OK(result)) { return result; + } done: - cli_samr_close(cli, mem_ctx, &connect_pol); + rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol); return result; } -static NTSTATUS -rpc_group_addmem_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, int argc, const char **argv) +static NTSTATUS rpc_group_addmem_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { DOM_SID group_sid; enum SID_NAME_USE group_type; @@ -1686,7 +1757,7 @@ rpc_group_addmem_internals(const DOM_SID *domain_sid, const char *domain_name, } if (group_type == SID_NAME_DOM_GRP) { - NTSTATUS result = rpc_add_groupmem(cli, mem_ctx, + NTSTATUS result = rpc_add_groupmem(pipe_hnd, mem_ctx, &group_sid, argv[1]); if (!NT_STATUS_IS_OK(result)) { @@ -1697,7 +1768,7 @@ rpc_group_addmem_internals(const DOM_SID *domain_sid, const char *domain_name, } if (group_type == SID_NAME_ALIAS) { - NTSTATUS result = rpc_add_aliasmem(cli, mem_ctx, + NTSTATUS result = rpc_add_aliasmem(pipe_hnd, mem_ctx, &group_sid, argv[1]); if (!NT_STATUS_IS_OK(result)) { @@ -1720,9 +1791,10 @@ static int rpc_group_addmem(int argc, const char **argv) argc, argv); } -static NTSTATUS -rpc_del_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, - const DOM_SID *group_sid, const char *member) +static NTSTATUS rpc_del_groupmem(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + const DOM_SID *group_sid, + const char *member) { POLICY_HND connect_pol, domain_pol; NTSTATUS result; @@ -1741,19 +1813,19 @@ rpc_del_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, return NT_STATUS_UNSUCCESSFUL; /* Get sam policy handle */ - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) return result; /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) return result; - result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, 1000, + result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000, 1, &member, &num_rids, &rids, &rid_types); @@ -1762,23 +1834,24 @@ rpc_del_groupmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, goto done; } - result = cli_samr_open_group(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol, MAXIMUM_ALLOWED_ACCESS, group_rid, &group_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_del_groupmem(cli, mem_ctx, &group_pol, rids[0]); + result = rpccli_samr_del_groupmem(pipe_hnd, mem_ctx, &group_pol, rids[0]); done: - cli_samr_close(cli, mem_ctx, &connect_pol); + rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol); return result; } -static NTSTATUS -rpc_del_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, - const DOM_SID *alias_sid, const char *member) +static NTSTATUS rpc_del_aliasmem(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + const DOM_SID *alias_sid, + const char *member) { POLICY_HND connect_pol, domain_pol; NTSTATUS result; @@ -1795,7 +1868,7 @@ rpc_del_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, if (!sid_split_rid(&sid, &alias_rid)) return NT_STATUS_UNSUCCESSFUL; - result = get_sid_from_name(cli, mem_ctx, member, + result = get_sid_from_name(pipe_hnd->cli, mem_ctx, member, &member_sid, &member_type); if (!NT_STATUS_IS_OK(result)) { @@ -1804,41 +1877,44 @@ rpc_del_aliasmem(struct cli_state *cli, TALLOC_CTX *mem_ctx, } /* Get sam policy handle */ - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } - result = cli_samr_open_alias(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol, MAXIMUM_ALLOWED_ACCESS, alias_rid, &alias_pol); if (!NT_STATUS_IS_OK(result)) return result; - result = cli_samr_del_aliasmem(cli, mem_ctx, &alias_pol, &member_sid); + result = rpccli_samr_del_aliasmem(pipe_hnd, mem_ctx, &alias_pol, &member_sid); if (!NT_STATUS_IS_OK(result)) return result; done: - cli_samr_close(cli, mem_ctx, &connect_pol); + rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol); return result; } -static NTSTATUS -rpc_group_delmem_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, int argc, const char **argv) +static NTSTATUS rpc_group_delmem_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { DOM_SID group_sid; enum SID_NAME_USE group_type; @@ -1855,7 +1931,7 @@ rpc_group_delmem_internals(const DOM_SID *domain_sid, const char *domain_name, } if (group_type == SID_NAME_DOM_GRP) { - NTSTATUS result = rpc_del_groupmem(cli, mem_ctx, + NTSTATUS result = rpc_del_groupmem(pipe_hnd, mem_ctx, &group_sid, argv[1]); if (!NT_STATUS_IS_OK(result)) { @@ -1866,7 +1942,7 @@ rpc_group_delmem_internals(const DOM_SID *domain_sid, const char *domain_name, } if (group_type == SID_NAME_ALIAS) { - NTSTATUS result = rpc_del_aliasmem(cli, mem_ctx, + NTSTATUS result = rpc_del_aliasmem(pipe_hnd, mem_ctx, &group_sid, argv[1]); if (!NT_STATUS_IS_OK(result)) { @@ -1905,10 +1981,13 @@ static int rpc_group_delmem(int argc, const char **argv) * @return Normal NTSTATUS return. **/ -static NTSTATUS -rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, int argc, const char **argv) +static NTSTATUS rpc_group_list_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { POLICY_HND connect_pol, domain_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; @@ -1937,7 +2016,7 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name, /* Get sam policy handle */ - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { goto done; @@ -1945,7 +2024,7 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name, /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) { @@ -1970,7 +2049,7 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name, get_query_dispinfo_params( loop_count, &max_entries, &max_size); - result = cli_samr_query_dispinfo(cli, mem_ctx, &domain_pol, + result = rpccli_samr_query_dispinfo(pipe_hnd, mem_ctx, &domain_pol, &start_idx, 3, &num_entries, max_entries, max_size, &ctr); @@ -2003,7 +2082,7 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name, * everything. I'm too lazy (sorry) to get this through to * rpc_parse/ etc. Volker */ - result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol, + result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol, &start_idx, 0xffff, &groups, &num_entries); @@ -2020,15 +2099,15 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name, POLICY_HND alias_pol; ALIAS_INFO_CTR ctr; - if ((NT_STATUS_IS_OK(cli_samr_open_alias(cli, mem_ctx, + if ((NT_STATUS_IS_OK(rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol, 0x8, groups[i].rid, &alias_pol))) && - (NT_STATUS_IS_OK(cli_samr_query_alias_info(cli, mem_ctx, + (NT_STATUS_IS_OK(rpccli_samr_query_alias_info(pipe_hnd, mem_ctx, &alias_pol, 3, &ctr))) && - (NT_STATUS_IS_OK(cli_samr_close(cli, mem_ctx, + (NT_STATUS_IS_OK(rpccli_samr_close(pipe_hnd, mem_ctx, &alias_pol)))) { description = unistr2_tdup(mem_ctx, ctr.alias.info3.description.string); @@ -2044,10 +2123,10 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name, } } } while (NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)); - cli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol); /* Get builtin policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &global_sid_Builtin, &domain_pol); if (!NT_STATUS_IS_OK(result)) { @@ -2058,7 +2137,7 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name, do { if (!builtin) break; - result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol, + result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol, &start_idx, max_entries, &groups, &num_entries); @@ -2075,15 +2154,15 @@ rpc_group_list_internals(const DOM_SID *domain_sid, const char *domain_name, POLICY_HND alias_pol; ALIAS_INFO_CTR ctr; - if ((NT_STATUS_IS_OK(cli_samr_open_alias(cli, mem_ctx, + if ((NT_STATUS_IS_OK(rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol, 0x8, groups[i].rid, &alias_pol))) && - (NT_STATUS_IS_OK(cli_samr_query_alias_info(cli, mem_ctx, + (NT_STATUS_IS_OK(rpccli_samr_query_alias_info(pipe_hnd, mem_ctx, &alias_pol, 3, &ctr))) && - (NT_STATUS_IS_OK(cli_samr_close(cli, mem_ctx, + (NT_STATUS_IS_OK(rpccli_samr_close(pipe_hnd, mem_ctx, &alias_pol)))) { description = unistr2_tdup(mem_ctx, ctr.alias.info3.description.string); @@ -2111,10 +2190,12 @@ static int rpc_group_list(int argc, const char **argv) argc, argv); } -static NTSTATUS -rpc_list_group_members(struct cli_state *cli, TALLOC_CTX *mem_ctx, - const char *domain_name, const DOM_SID *domain_sid, - POLICY_HND *domain_pol, uint32 rid) +static NTSTATUS rpc_list_group_members(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + const char *domain_name, + const DOM_SID *domain_sid, + POLICY_HND *domain_pol, + uint32 rid) { NTSTATUS result; POLICY_HND group_pol; @@ -2127,14 +2208,14 @@ rpc_list_group_members(struct cli_state *cli, TALLOC_CTX *mem_ctx, fstring sid_str; sid_to_string(sid_str, domain_sid); - result = cli_samr_open_group(cli, mem_ctx, domain_pol, + result = rpccli_samr_open_group(pipe_hnd, mem_ctx, domain_pol, MAXIMUM_ALLOWED_ACCESS, rid, &group_pol); if (!NT_STATUS_IS_OK(result)) return result; - result = cli_samr_query_groupmem(cli, mem_ctx, &group_pol, + result = rpccli_samr_query_groupmem(pipe_hnd, mem_ctx, &group_pol, &num_members, &group_rids, &group_attrs); @@ -2147,7 +2228,7 @@ rpc_list_group_members(struct cli_state *cli, TALLOC_CTX *mem_ctx, if (num_members < this_time) this_time = num_members; - result = cli_samr_lookup_rids(cli, mem_ctx, domain_pol, + result = rpccli_samr_lookup_rids(pipe_hnd, mem_ctx, domain_pol, this_time, group_rids, &num_names, &names, &name_types); @@ -2175,11 +2256,13 @@ rpc_list_group_members(struct cli_state *cli, TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } -static NTSTATUS -rpc_list_alias_members(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *domain_pol, uint32 rid) +static NTSTATUS rpc_list_alias_members(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + POLICY_HND *domain_pol, + uint32 rid) { NTSTATUS result; + struct rpc_pipe_client *lsa_pipe; POLICY_HND alias_pol, lsa_pol; uint32 num_members; DOM_SID *alias_sids; @@ -2188,13 +2271,13 @@ rpc_list_alias_members(struct cli_state *cli, TALLOC_CTX *mem_ctx, uint32 *types; int i; - result = cli_samr_open_alias(cli, mem_ctx, domain_pol, + result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, domain_pol, MAXIMUM_ALLOWED_ACCESS, rid, &alias_pol); if (!NT_STATUS_IS_OK(result)) return result; - result = cli_samr_query_aliasmem(cli, mem_ctx, &alias_pol, + result = rpccli_samr_query_aliasmem(pipe_hnd, mem_ctx, &alias_pol, &num_members, &alias_sids); if (!NT_STATUS_IS_OK(result)) { @@ -2206,28 +2289,30 @@ rpc_list_alias_members(struct cli_state *cli, TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } - cli_nt_session_close(cli); - - if (!cli_nt_session_open(cli, PI_LSARPC)) { - d_printf("Couldn't open LSA pipe\n"); + lsa_pipe = cli_rpc_pipe_open_noauth(pipe_hnd->cli, PI_LSARPC, &result); + if (!lsa_pipe) { + d_printf("Couldn't open LSA pipe. Error was %s\n", + nt_errstr(result) ); return result; } - result = cli_lsa_open_policy(cli, mem_ctx, True, + result = rpccli_lsa_open_policy(lsa_pipe, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol); if (!NT_STATUS_IS_OK(result)) { d_printf("Couldn't open LSA policy handle\n"); + cli_rpc_pipe_close(lsa_pipe); return result; } - result = cli_lsa_lookup_sids(cli, mem_ctx, &lsa_pol, num_members, + result = rpccli_lsa_lookup_sids(lsa_pipe, mem_ctx, &lsa_pol, num_members, alias_sids, &domains, &names, &types); if (!NT_STATUS_IS_OK(result) && !NT_STATUS_EQUAL(result, STATUS_SOME_UNMAPPED)) { d_printf("Couldn't lookup SIDs\n"); + cli_rpc_pipe_close(lsa_pipe); return result; } @@ -2247,14 +2332,17 @@ rpc_list_alias_members(struct cli_state *cli, TALLOC_CTX *mem_ctx, } } + cli_rpc_pipe_close(lsa_pipe); return NT_STATUS_OK; } -static NTSTATUS -rpc_group_members_internals(const DOM_SID *domain_sid, - const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, int argc, const char **argv) +static NTSTATUS rpc_group_members_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { NTSTATUS result; POLICY_HND connect_pol, domain_pol; @@ -2262,7 +2350,7 @@ rpc_group_members_internals(const DOM_SID *domain_sid, /* Get sam policy handle */ - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) @@ -2270,14 +2358,14 @@ rpc_group_members_internals(const DOM_SID *domain_sid, /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) return result; - result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, 1000, + result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000, 1, argv, &num_rids, &rids, &rid_types); if (!NT_STATUS_IS_OK(result)) { @@ -2286,11 +2374,11 @@ rpc_group_members_internals(const DOM_SID *domain_sid, DOM_SID sid_Builtin; - cli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol); string_to_sid(&sid_Builtin, "S-1-5-32"); - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, &sid_Builtin, &domain_pol); @@ -2299,7 +2387,7 @@ rpc_group_members_internals(const DOM_SID *domain_sid, return result; } - result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, 1000, + result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000, 1, argv, &num_rids, &rids, &rid_types); @@ -2315,13 +2403,13 @@ rpc_group_members_internals(const DOM_SID *domain_sid, } if (rid_types[0] == SID_NAME_DOM_GRP) { - return rpc_list_group_members(cli, mem_ctx, domain_name, + return rpc_list_group_members(pipe_hnd, mem_ctx, domain_name, domain_sid, &domain_pol, rids[0]); } if (rid_types[0] == SID_NAME_ALIAS) { - return rpc_list_alias_members(cli, mem_ctx, &domain_pol, + return rpc_list_alias_members(pipe_hnd, mem_ctx, &domain_pol, rids[0]); } @@ -2339,11 +2427,13 @@ static int rpc_group_members(int argc, const char **argv) argc, argv); } -static NTSTATUS -rpc_group_rename_internals(const DOM_SID *domain_sid, - const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, int argc, const char **argv) +static NTSTATUS rpc_group_rename_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { NTSTATUS result; POLICY_HND connect_pol, domain_pol, group_pol; @@ -2357,7 +2447,7 @@ rpc_group_rename_internals(const DOM_SID *domain_sid, /* Get sam policy handle */ - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) @@ -2365,14 +2455,14 @@ rpc_group_rename_internals(const DOM_SID *domain_sid, /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) return result; - result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, 1000, + result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, 1000, 1, argv, &num_rids, &rids, &rid_types); if (num_rids != 1) { @@ -2385,7 +2475,7 @@ rpc_group_rename_internals(const DOM_SID *domain_sid, return NT_STATUS_UNSUCCESSFUL; } - result = cli_samr_open_group(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_group(pipe_hnd, mem_ctx, &domain_pol, MAXIMUM_ALLOWED_ACCESS, rids[0], &group_pol); @@ -2397,7 +2487,7 @@ rpc_group_rename_internals(const DOM_SID *domain_sid, ctr.switch_value1 = 2; init_samr_group_info2(&ctr.group.info2, argv[1]); - result = cli_samr_set_groupinfo(cli, mem_ctx, &group_pol, &ctr); + result = rpccli_samr_set_groupinfo(pipe_hnd, mem_ctx, &group_pol, &ctr); if (!NT_STATUS_IS_OK(result)) return result; @@ -2467,10 +2557,12 @@ static int rpc_share_usage(int argc, const char **argv) * * @return Normal NTSTATUS return. **/ -static NTSTATUS -rpc_share_add_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx,int argc, const char **argv) +static NTSTATUS rpc_share_add_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx,int argc, + const char **argv) { WERROR result; char *sharename=talloc_strdup(mem_ctx, argv[0]); @@ -2485,7 +2577,7 @@ rpc_share_add_internals(const DOM_SID *domain_sid, const char *domain_name, return NT_STATUS_UNSUCCESSFUL; *path++ = '\0'; - result = cli_srvsvc_net_share_add(cli, mem_ctx, sharename, type, + result = rpccli_srvsvc_net_share_add(pipe_hnd, mem_ctx, sharename, type, opt_comment, perms, opt_maxusers, num_users, path, password, level, NULL); @@ -2518,14 +2610,17 @@ static int rpc_share_add(int argc, const char **argv) * * @return Normal NTSTATUS return. **/ -static NTSTATUS -rpc_share_del_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx,int argc, const char **argv) +static NTSTATUS rpc_share_del_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { WERROR result; - result = cli_srvsvc_net_share_del(cli, mem_ctx, argv[0]); + result = rpccli_srvsvc_net_share_del(pipe_hnd, mem_ctx, argv[0]); return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } @@ -2572,10 +2667,12 @@ static void display_share_info_1(SRV_SHARE_INFO_1 *info1) } - -static WERROR get_share_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, - uint32 level, int argc, const char **argv, - SRV_SHARE_INFO_CTR *ctr) +static WERROR get_share_info(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + uint32 level, + int argc, + const char **argv, + SRV_SHARE_INFO_CTR *ctr) { WERROR result; SRV_SHARE_INFO info; @@ -2588,12 +2685,12 @@ static WERROR get_share_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, init_enum_hnd(&hnd, 0); - return cli_srvsvc_net_share_enum(cli, mem_ctx, level, ctr, + return rpccli_srvsvc_net_share_enum(pipe_hnd, mem_ctx, level, ctr, preferred_len, &hnd); } /* request just one share */ - result = cli_srvsvc_net_share_get_info(cli, mem_ctx, argv[0], level, &info); + result = rpccli_srvsvc_net_share_get_info(pipe_hnd, mem_ctx, argv[0], level, &info); if (!W_ERROR_IS_OK(result)) goto done; @@ -2720,16 +2817,19 @@ done: * @return Normal NTSTATUS return. **/ -static NTSTATUS -rpc_share_list_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, int argc, const char **argv) +static NTSTATUS rpc_share_list_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { SRV_SHARE_INFO_CTR ctr; WERROR result; uint32 i, level = 1; - result = get_share_info(cli, mem_ctx, level, argc, argv, &ctr); + result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr); if (!W_ERROR_IS_OK(result)) goto done; @@ -2808,10 +2908,14 @@ static BOOL check_share_sanity(struct cli_state *cli, fstring netname, uint32 ty * * @return Normal NTSTATUS return. **/ -static NTSTATUS -rpc_share_migrate_shares_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) + +static NTSTATUS rpc_share_migrate_shares_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { WERROR result; NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; @@ -2819,16 +2923,16 @@ rpc_share_migrate_shares_internals(const DOM_SID *domain_sid, const char *domain uint32 type = STYPE_DISKTREE; /* only allow disk shares to be added */ char *password = NULL; /* don't allow a share password */ uint32 i; - BOOL got_dst_srvsvc_pipe = False; + struct rpc_pipe_client *srvsvc_pipe = NULL; struct cli_state *cli_dst = NULL; uint32 level = 502; /* includes secdesc */ - result = get_share_info(cli, mem_ctx, level, argc, argv, &ctr_src); + result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src); if (!W_ERROR_IS_OK(result)) goto done; /* connect destination PI_SRVSVC */ - nt_status = connect_dst_pipe(&cli_dst, PI_SRVSVC, &got_dst_srvsvc_pipe); + nt_status = connect_dst_pipe(&cli_dst, &srvsvc_pipe, PI_SRVSVC); if (!NT_STATUS_IS_OK(nt_status)) return nt_status; @@ -2854,7 +2958,7 @@ rpc_share_migrate_shares_internals(const DOM_SID *domain_sid, const char *domain printf("migrating: [%s], path: %s, comment: %s, without share-ACLs\n", netname, path, remark); - result = cli_srvsvc_net_share_add(cli_dst, mem_ctx, netname, type, remark, + result = rpccli_srvsvc_net_share_add(srvsvc_pipe, mem_ctx, netname, type, remark, ctr_src.share.info502[i].info_502.perms, ctr_src.share.info502[i].info_502.max_uses, ctr_src.share.info502[i].info_502.num_uses, @@ -2876,8 +2980,7 @@ rpc_share_migrate_shares_internals(const DOM_SID *domain_sid, const char *domain nt_status = NT_STATUS_OK; done: - if (got_dst_srvsvc_pipe) { - cli_nt_session_close(cli_dst); + if (cli_dst) { cli_shutdown(cli_dst); } @@ -3038,7 +3141,7 @@ BOOL sync_files(struct copy_clistate *cp_clistate, pstring mask) BOOL copy_top_level_perms(struct copy_clistate *cp_clistate, const char *sharename) { - NTSTATUS nt_status; + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; switch (net_mode_share) { case NET_MODE_SHARE_MIGRATE: @@ -3066,7 +3169,6 @@ BOOL copy_top_level_perms(struct copy_clistate *cp_clistate, return True; } - /** * Sync all files inside a remote share to another share (over smb) * @@ -3082,10 +3184,14 @@ BOOL copy_top_level_perms(struct copy_clistate *cp_clistate, * * @return Normal NTSTATUS return. **/ -static NTSTATUS -rpc_share_migrate_files_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) + +static NTSTATUS rpc_share_migrate_files_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { WERROR result; NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; @@ -3100,7 +3206,7 @@ rpc_share_migrate_files_internals(const DOM_SID *domain_sid, const char *domain_ dst = SMB_STRDUP(opt_destination?opt_destination:"127.0.0.1"); - result = get_share_info(cli, mem_ctx, level, argc, argv, &ctr_src); + result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src); if (!W_ERROR_IS_OK(result)) goto done; @@ -3216,27 +3322,31 @@ static int rpc_share_migrate_files(int argc, const char **argv) * * @return Normal NTSTATUS return. **/ -static NTSTATUS -rpc_share_migrate_security_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) + +static NTSTATUS rpc_share_migrate_security_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { WERROR result; NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; SRV_SHARE_INFO_CTR ctr_src; SRV_SHARE_INFO info; uint32 i; - BOOL got_dst_srvsvc_pipe = False; + struct rpc_pipe_client *srvsvc_pipe = NULL; struct cli_state *cli_dst = NULL; uint32 level = 502; /* includes secdesc */ - result = get_share_info(cli, mem_ctx, level, argc, argv, &ctr_src); + result = get_share_info(pipe_hnd, mem_ctx, level, argc, argv, &ctr_src); if (!W_ERROR_IS_OK(result)) goto done; /* connect destination PI_SRVSVC */ - nt_status = connect_dst_pipe(&cli_dst, PI_SRVSVC, &got_dst_srvsvc_pipe); + nt_status = connect_dst_pipe(&cli_dst, &srvsvc_pipe, PI_SRVSVC); if (!NT_STATUS_IS_OK(nt_status)) return nt_status; @@ -3273,7 +3383,7 @@ rpc_share_migrate_security_internals(const DOM_SID *domain_sid, const char *doma info.share.info502 = ctr_src.share.info502[i]; /* finally modify the share on the dst server */ - result = cli_srvsvc_net_share_set_info(cli_dst, mem_ctx, netname, level, &info); + result = rpccli_srvsvc_net_share_set_info(srvsvc_pipe, mem_ctx, netname, level, &info); if (!W_ERROR_IS_OK(result)) { printf("cannot set share-acl: %s\n", dos_errstr(result)); @@ -3285,8 +3395,7 @@ rpc_share_migrate_security_internals(const DOM_SID *domain_sid, const char *doma nt_status = NT_STATUS_OK; done: - if (got_dst_srvsvc_pipe) { - cli_nt_session_close(cli_dst); + if (cli_dst) { cli_shutdown(cli_dst); } @@ -3399,10 +3508,11 @@ static void push_alias(TALLOC_CTX *mem_ctx, struct full_alias *alias) * For a specific domain on the server, fetch all the aliases * and their members. Add all of them to the server_aliases. */ -static NTSTATUS -rpc_fetch_domain_aliases(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *connect_pol, - const DOM_SID *domain_sid) + +static NTSTATUS rpc_fetch_domain_aliases(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + POLICY_HND *connect_pol, + const DOM_SID *domain_sid) { uint32 start_idx, max_entries, num_entries, i; struct acct_info *groups; @@ -3411,7 +3521,7 @@ rpc_fetch_domain_aliases(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, connect_pol, MAXIMUM_ALLOWED_ACCESS, domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) @@ -3421,7 +3531,7 @@ rpc_fetch_domain_aliases(struct cli_state *cli, TALLOC_CTX *mem_ctx, max_entries = 250; do { - result = cli_samr_enum_als_groups(cli, mem_ctx, &domain_pol, + result = rpccli_samr_enum_als_groups(pipe_hnd, mem_ctx, &domain_pol, &start_idx, max_entries, &groups, &num_entries); @@ -3432,21 +3542,21 @@ rpc_fetch_domain_aliases(struct cli_state *cli, TALLOC_CTX *mem_ctx, DOM_SID *members; int j; - result = cli_samr_open_alias(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_alias(pipe_hnd, mem_ctx, &domain_pol, MAXIMUM_ALLOWED_ACCESS, groups[i].rid, &alias_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_query_aliasmem(cli, mem_ctx, + result = rpccli_samr_query_aliasmem(pipe_hnd, mem_ctx, &alias_pol, &alias.num_members, &members); if (!NT_STATUS_IS_OK(result)) goto done; - result = cli_samr_close(cli, mem_ctx, &alias_pol); + result = rpccli_samr_close(pipe_hnd, mem_ctx, &alias_pol); if (!NT_STATUS_IS_OK(result)) goto done; @@ -3470,7 +3580,7 @@ rpc_fetch_domain_aliases(struct cli_state *cli, TALLOC_CTX *mem_ctx, result = NT_STATUS_OK; done: - cli_samr_close(cli, mem_ctx, &domain_pol); + rpccli_samr_close(pipe_hnd, mem_ctx, &domain_pol); return result; } @@ -3478,16 +3588,20 @@ rpc_fetch_domain_aliases(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* * Dump server_aliases as names for debugging purposes. */ -static NTSTATUS -rpc_aliaslist_dump(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) + +static NTSTATUS rpc_aliaslist_dump(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { int i; NTSTATUS result; POLICY_HND lsa_pol; - result = cli_lsa_open_policy(cli, mem_ctx, True, + result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol); if (!NT_STATUS_IS_OK(result)) @@ -3501,7 +3615,7 @@ rpc_aliaslist_dump(const DOM_SID *domain_sid, const char *domain_name, struct full_alias *alias = &server_aliases[i]; - result = cli_lsa_lookup_sids(cli, mem_ctx, &lsa_pol, 1, + result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, 1, &alias->sid, &domains, &names, &types); if (!NT_STATUS_IS_OK(result)) @@ -3514,7 +3628,7 @@ rpc_aliaslist_dump(const DOM_SID *domain_sid, const char *domain_name, continue; } - result = cli_lsa_lookup_sids(cli, mem_ctx, &lsa_pol, + result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &lsa_pol, alias->num_members, alias->members, &domains, &names, &types); @@ -3530,7 +3644,7 @@ rpc_aliaslist_dump(const DOM_SID *domain_sid, const char *domain_name, DEBUG(1, ("\n")); } - cli_lsa_close(cli, mem_ctx, &lsa_pol); + rpccli_lsa_close(pipe_hnd, mem_ctx, &lsa_pol); return NT_STATUS_OK; } @@ -3539,30 +3653,34 @@ rpc_aliaslist_dump(const DOM_SID *domain_sid, const char *domain_name, * Fetch a list of all server aliases and their members into * server_aliases. */ -static NTSTATUS -rpc_aliaslist_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) + +static NTSTATUS rpc_aliaslist_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { NTSTATUS result; POLICY_HND connect_pol; - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) goto done; - result = rpc_fetch_domain_aliases(cli, mem_ctx, &connect_pol, + result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol, &global_sid_Builtin); if (!NT_STATUS_IS_OK(result)) goto done; - result = rpc_fetch_domain_aliases(cli, mem_ctx, &connect_pol, + result = rpc_fetch_domain_aliases(pipe_hnd, mem_ctx, &connect_pol, domain_sid); - cli_samr_close(cli, mem_ctx, &connect_pol); + rpccli_samr_close(pipe_hnd, mem_ctx, &connect_pol); done: return result; } @@ -3662,8 +3780,7 @@ static void collect_alias_memberships(NT_USER_TOKEN *token) } } -static BOOL get_user_sids(const char *domain, const char *user, - NT_USER_TOKEN *token) +static BOOL get_user_sids(const char *domain, const char *user, NT_USER_TOKEN *token) { struct winbindd_request request; struct winbindd_response response; @@ -3749,6 +3866,7 @@ static BOOL get_user_sids(const char *domain, const char *user, /** * Get a list of all user tokens we want to look at **/ + static BOOL get_user_tokens(int *num_tokens, struct user_token **user_tokens) { struct winbindd_request request; @@ -3884,19 +4002,22 @@ static BOOL get_user_tokens_from_file(FILE *f, * Show the list of all users that have access to a share */ -static void show_userlist(struct cli_state *cli, - TALLOC_CTX *mem_ctx, const char *netname, - int num_tokens, struct user_token *tokens) +static void show_userlist(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + const char *netname, + int num_tokens, + struct user_token *tokens) { int fnum; SEC_DESC *share_sd = NULL; SEC_DESC *root_sd = NULL; + struct cli_state *cli = pipe_hnd->cli; int i; SRV_SHARE_INFO info; WERROR result; uint16 cnum; - result = cli_srvsvc_net_share_get_info(cli, mem_ctx, netname, + result = rpccli_srvsvc_net_share_get_info(pipe_hnd, mem_ctx, netname, 502, &info); if (!W_ERROR_IS_OK(result)) { @@ -4005,12 +4126,13 @@ static void rpc_share_userlist_usage(void) * @return Normal NTSTATUS return. **/ -static NTSTATUS -rpc_share_allowedusers_internals(const DOM_SID *domain_sid, - const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, - int argc, const char **argv) +static NTSTATUS rpc_share_allowedusers_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { int ret; BOOL r; @@ -4073,7 +4195,7 @@ rpc_share_allowedusers_internals(const DOM_SID *domain_sid, d_printf("%s\n", netname); - show_userlist(cli, mem_ctx, netname, + show_userlist(pipe_hnd, mem_ctx, netname, num_tokens, tokens); } done: @@ -4086,8 +4208,7 @@ rpc_share_allowedusers_internals(const DOM_SID *domain_sid, return NT_STATUS_OK; } -static int -rpc_share_allowedusers(int argc, const char **argv) +static int rpc_share_allowedusers(int argc, const char **argv) { int result; @@ -4192,13 +4313,16 @@ static int rpc_file_usage(int argc, const char **argv) * * @return Normal NTSTATUS return. **/ -static NTSTATUS -rpc_file_close_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, int argc, const char **argv) +static NTSTATUS rpc_file_close_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { WERROR result; - result = cli_srvsvc_net_file_close(cli, mem_ctx, atoi(argv[0])); + result = rpccli_srvsvc_net_file_close(pipe_hnd, mem_ctx, atoi(argv[0])); return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } @@ -4257,10 +4381,13 @@ static void display_file_info_3(FILE_INFO_3 *info3, FILE_INFO_3_STR *str3) * @return Normal NTSTATUS return. **/ -static NTSTATUS -rpc_file_list_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, int argc, const char **argv) +static NTSTATUS rpc_file_list_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { SRV_FILE_INFO_CTR ctr; WERROR result; @@ -4274,8 +4401,8 @@ rpc_file_list_internals(const DOM_SID *domain_sid, const char *domain_name, if (argc > 0) username = smb_xstrdup(argv[0]); - result = cli_srvsvc_net_file_enum( - cli, mem_ctx, 3, username, &ctr, preferred_len, &hnd); + result = rpccli_srvsvc_net_file_enum(pipe_hnd, + mem_ctx, 3, username, &ctr, preferred_len, &hnd); if (!W_ERROR_IS_OK(result)) goto done; @@ -4293,7 +4420,6 @@ rpc_file_list_internals(const DOM_SID *domain_sid, const char *domain_name, return W_ERROR_IS_OK(result) ? NT_STATUS_OK : NT_STATUS_UNSUCCESSFUL; } - /** * List files for a user on a remote RPC server * @@ -4303,6 +4429,7 @@ rpc_file_list_internals(const DOM_SID *domain_sid, const char *domain_name, * * @return A shell status integer (0 for success) **/ + static int rpc_file_user(int argc, const char **argv) { if (argc < 1) { @@ -4315,7 +4442,6 @@ static int rpc_file_user(int argc, const char **argv) argc, argv); } - /** * 'net rpc file' entrypoint. * @param argc Standard main() style argc @@ -4342,10 +4468,6 @@ int net_rpc_file(int argc, const char **argv) return net_run_function(argc, argv, func, rpc_file_usage); } -/****************************************************************************/ - - - /** * ABORT the shutdown of a remote RPC Server over, initshutdown pipe * @@ -4363,14 +4485,16 @@ int net_rpc_file(int argc, const char **argv) **/ static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, - const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, - int argc, const char **argv) + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - result = cli_shutdown_abort(cli, mem_ctx); + result = rpccli_shutdown_abort(pipe_hnd, mem_ctx); if (NT_STATUS_IS_OK(result)) { d_printf("\nShutdown successfully aborted\n"); @@ -4381,7 +4505,6 @@ static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, return result; } - /** * ABORT the shutdown of a remote RPC Server, over winreg pipe * @@ -4399,14 +4522,16 @@ static NTSTATUS rpc_shutdown_abort_internals(const DOM_SID *domain_sid, **/ static NTSTATUS rpc_reg_shutdown_abort_internals(const DOM_SID *domain_sid, - const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, - int argc, const char **argv) + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; - result = werror_to_ntstatus(cli_reg_abort_shutdown(cli, mem_ctx)); + result = werror_to_ntstatus(rpccli_reg_abort_shutdown(pipe_hnd, mem_ctx)); if (NT_STATUS_IS_OK(result)) { d_printf("\nShutdown successfully aborted\n"); @@ -4460,10 +4585,12 @@ static int rpc_shutdown_abort(int argc, const char **argv) **/ static NTSTATUS rpc_init_shutdown_internals(const DOM_SID *domain_sid, - const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, - int argc, const char **argv) + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; const char *msg = "This machine will be shutdown shortly"; @@ -4471,16 +4598,13 @@ static NTSTATUS rpc_init_shutdown_internals(const DOM_SID *domain_sid, if (opt_comment) { msg = opt_comment; - } else { - msg = ""; } - if (opt_timeout) { timeout = opt_timeout; } /* create an entry */ - result = cli_shutdown_init(cli, mem_ctx, msg, timeout, opt_reboot, + result = rpccli_shutdown_init(pipe_hnd, mem_ctx, msg, timeout, opt_reboot, opt_force); if (NT_STATUS_IS_OK(result)) { @@ -4509,10 +4633,12 @@ static NTSTATUS rpc_init_shutdown_internals(const DOM_SID *domain_sid, **/ static NTSTATUS rpc_reg_shutdown_internals(const DOM_SID *domain_sid, - const char *domain_name, - struct cli_state *cli, - TALLOC_CTX *mem_ctx, - int argc, const char **argv) + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { NTSTATUS result = NT_STATUS_UNSUCCESSFUL; const char *msg = "This machine will be shutdown shortly"; @@ -4550,7 +4676,7 @@ static NTSTATUS rpc_reg_shutdown_internals(const DOM_SID *domain_sid, } /* create an entry */ - result = werror_to_ntstatus(cli_reg_shutdown(cli, mem_ctx, msg, timeout, opt_reboot, opt_force)); + result = werror_to_ntstatus(rpccli_reg_shutdown(pipe_hnd, mem_ctx, msg, timeout, opt_reboot, opt_force)); if (NT_STATUS_IS_OK(result)) { d_printf("\nShutdown of remote machine succeeded\n"); @@ -4607,10 +4733,13 @@ static int rpc_shutdown(int argc, const char **argv) */ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, - const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) { - + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) +{ POLICY_HND connect_pol, domain_pol, user_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; char *acct_name; @@ -4633,14 +4762,14 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, strupper_m(acct_name); /* Get samr policy handle */ - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) { @@ -4652,7 +4781,7 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, unknown = 0xe00500b0; /* No idea what this is - a permission mask? mimir: yes, most probably it is */ - result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol, + result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol, acct_name, acb_info, unknown, &user_pol, &user_rid); if (!NT_STATUS_IS_OK(result)) { @@ -4688,7 +4817,7 @@ static NTSTATUS rpc_trustdom_add_internals(const DOM_SID *domain_sid, ctr.info.id23 = &p23; p23.passmustchange = 0; - result = cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 23, + result = rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 23, &cli->user_session_key, &ctr); if (!NT_STATUS_IS_OK(result)) { @@ -4740,10 +4869,13 @@ static int rpc_trustdom_add(int argc, const char **argv) */ static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid, - const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) { - + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) +{ POLICY_HND connect_pol, domain_pol, user_pol; NTSTATUS result = NT_STATUS_UNSUCCESSFUL; char *acct_name; @@ -4772,21 +4904,21 @@ static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid, /* Get samr policy handle */ - result = cli_samr_connect(cli, mem_ctx, MAXIMUM_ALLOWED_ACCESS, + result = rpccli_samr_connect(pipe_hnd, mem_ctx, MAXIMUM_ALLOWED_ACCESS, &connect_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } /* Get domain policy handle */ - result = cli_samr_open_domain(cli, mem_ctx, &connect_pol, + result = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_pol, MAXIMUM_ALLOWED_ACCESS, domain_sid, &domain_pol); if (!NT_STATUS_IS_OK(result)) { goto done; } - result = cli_samr_lookup_names(cli, mem_ctx, &domain_pol, flags, 1, + result = rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, flags, 1, names, &num_rids, &user_rids, &name_types); @@ -4794,7 +4926,7 @@ static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid, goto done; } - result = cli_samr_open_user(cli, mem_ctx, &domain_pol, + result = rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol, MAXIMUM_ALLOWED_ACCESS, user_rids[0], &user_pol); @@ -4810,7 +4942,7 @@ static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid, /* remove the sid */ - result = cli_samr_remove_sid_foreign_domain(cli, mem_ctx, &user_pol, + result = rpccli_samr_remove_sid_foreign_domain(pipe_hnd, mem_ctx, &user_pol, &trust_acct_sid); if (!NT_STATUS_IS_OK(result)) { @@ -4819,7 +4951,7 @@ static NTSTATUS rpc_trustdom_del_internals(const DOM_SID *domain_sid, /* Delete user */ - result = cli_samr_delete_dom_user(cli, mem_ctx, &user_pol); + result = rpccli_samr_delete_dom_user(pipe_hnd, mem_ctx, &user_pol); if (!NT_STATUS_IS_OK(result)) { goto done; @@ -4868,8 +5000,9 @@ static int rpc_trustdom_del(int argc, const char **argv) static int rpc_trustdom_establish(int argc, const char **argv) { - struct cli_state *cli; + struct cli_state *cli = NULL; struct in_addr server_ip; + struct rpc_pipe_client *pipe_hnd = NULL; POLICY_HND connect_hnd; TALLOC_CTX *mem_ctx; NTSTATUS nt_status; @@ -4954,34 +5087,38 @@ static int rpc_trustdom_establish(int argc, const char **argv) * Call LsaOpenPolicy and LsaQueryInfo */ - if (!cli_nt_session_open(cli, PI_LSARPC)) { - DEBUG(0, ("Could not initialise lsa pipe\n")); + pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status); + if (!pipe_hnd) { + DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", nt_errstr(nt_status) )); cli_shutdown(cli); return -1; } - nt_status = cli_lsa_open_policy2(cli, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE, + nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, True, SEC_RIGHTS_QUERY_VALUE, &connect_hnd); if (NT_STATUS_IS_ERR(nt_status)) { DEBUG(0, ("Couldn't open policy handle. Error was %s\n", nt_errstr(nt_status))); + cli_shutdown(cli); return -1; } /* Querying info level 5 */ - nt_status = cli_lsa_query_info_policy(cli, mem_ctx, &connect_hnd, + nt_status = rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx, &connect_hnd, 5 /* info level */, &domain_name_pol, &domain_sid); if (NT_STATUS_IS_ERR(nt_status)) { DEBUG(0, ("LSA Query Info failed. Returned error was %s\n", nt_errstr(nt_status))); + cli_shutdown(cli); return -1; } if (push_ucs2_talloc(mem_ctx, &uni_domain_name, domain_name_pol) == (size_t)-1) { DEBUG(0, ("Could not convert domain name %s to unicode\n", domain_name_pol)); + cli_shutdown(cli); return -1; } @@ -4998,6 +5135,7 @@ static int rpc_trustdom_establish(int argc, const char **argv) opt_password, *domain_sid)) { DEBUG(0, ("Storing password for trusted domain failed.\n")); + cli_shutdown(cli); return -1; } @@ -5005,16 +5143,14 @@ static int rpc_trustdom_establish(int argc, const char **argv) * Close the pipes and clean up */ - nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd); + nt_status = rpccli_lsa_close(pipe_hnd, mem_ctx, &connect_hnd); if (NT_STATUS_IS_ERR(nt_status)) { DEBUG(0, ("Couldn't close LSA pipe. Error was %s\n", nt_errstr(nt_status))); + cli_shutdown(cli); return -1; } - if (cli->pipes[cli->pipe_idx].fnum) - cli_nt_session_close(cli); - cli_shutdown(cli); talloc_destroy(mem_ctx); @@ -5074,9 +5210,12 @@ static int rpc_trustdom_usage(int argc, const char **argv) static NTSTATUS rpc_query_domain_sid(const DOM_SID *domain_sid, - const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { fstring str_sid; sid_to_string(str_sid, domain_sid); @@ -5100,7 +5239,7 @@ static void print_trusted_domain(DOM_SID *dom_sid, const char *trusted_dom_name) d_printf("%s%s%s\n", trusted_dom_name, padding, ascii_sid); } -static NTSTATUS vampire_trusted_domain(struct cli_state *cli, +static NTSTATUS vampire_trusted_domain(struct rpc_pipe_client *pipe_hnd, TALLOC_CTX *mem_ctx, POLICY_HND *pol, DOM_SID dom_sid, @@ -5112,7 +5251,7 @@ static NTSTATUS vampire_trusted_domain(struct cli_state *cli, DATA_BLOB data; smb_ucs2_t *uni_dom_name; - nt_status = cli_lsa_query_trusted_domain_info_by_sid(cli, mem_ctx, pol, 4, &dom_sid, &info); + nt_status = rpccli_lsa_query_trusted_domain_info_by_sid(pipe_hnd, mem_ctx, pol, 4, &dom_sid, &info); if (NT_STATUS_IS_ERR(nt_status)) { DEBUG(0,("Could not query trusted domain info. Error was %s\n", @@ -5125,7 +5264,7 @@ static NTSTATUS vampire_trusted_domain(struct cli_state *cli, memcpy(data.data, info->password.password.data, info->password.password.length); data.length = info->password.password.length; - cleartextpwd = decrypt_trustdom_secret(cli->pwd.password, &data); + cleartextpwd = decrypt_trustdom_secret(pipe_hnd->cli->pwd.password, &data); if (cleartextpwd == NULL) { DEBUG(0,("retrieved NULL password\n")); @@ -5164,7 +5303,8 @@ static int rpc_trustdom_vampire(int argc, const char **argv) { /* common variables */ TALLOC_CTX* mem_ctx; - struct cli_state *cli; + struct cli_state *cli = NULL; + struct rpc_pipe_client *pipe_hnd = NULL; NTSTATUS nt_status; const char *domain_name = NULL; DOM_SID *queried_dom_sid; @@ -5204,27 +5344,32 @@ static int rpc_trustdom_vampire(int argc, const char **argv) return -1; }; - if (!cli_nt_session_open(cli, PI_LSARPC)) { - DEBUG(0, ("Could not initialise lsa pipe\n")); + pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status); + if (!pipe_hnd) { + DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", + nt_errstr(nt_status) )); + cli_shutdown(cli); return -1; }; - nt_status = cli_lsa_open_policy2(cli, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE, + nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE, &connect_hnd); if (NT_STATUS_IS_ERR(nt_status)) { DEBUG(0, ("Couldn't open policy handle. Error was %s\n", nt_errstr(nt_status))); + cli_shutdown(cli); return -1; }; /* query info level 5 to obtain sid of a domain being queried */ - nt_status = cli_lsa_query_info_policy( - cli, mem_ctx, &connect_hnd, 5 /* info level */, + nt_status = rpccli_lsa_query_info_policy( + pipe_hnd, mem_ctx, &connect_hnd, 5 /* info level */, &dummy, &queried_dom_sid); if (NT_STATUS_IS_ERR(nt_status)) { DEBUG(0, ("LSA Query Info failed. Returned error was %s\n", nt_errstr(nt_status))); + cli_shutdown(cli); return -1; } @@ -5236,13 +5381,14 @@ static int rpc_trustdom_vampire(int argc, const char **argv) d_printf("Vampire trusted domains:\n\n"); do { - nt_status = cli_lsa_enum_trust_dom(cli, mem_ctx, &connect_hnd, &enum_ctx, + nt_status = rpccli_lsa_enum_trust_dom(pipe_hnd, mem_ctx, &connect_hnd, &enum_ctx, &num_domains, &trusted_dom_names, &domain_sids); if (NT_STATUS_IS_ERR(nt_status)) { DEBUG(0, ("Couldn't enumerate trusted domains. Error was %s\n", nt_errstr(nt_status))); + cli_shutdown(cli); return -1; }; @@ -5250,10 +5396,12 @@ static int rpc_trustdom_vampire(int argc, const char **argv) print_trusted_domain(&(domain_sids[i]), trusted_dom_names[i]); - nt_status = vampire_trusted_domain(cli, mem_ctx, &connect_hnd, + nt_status = vampire_trusted_domain(pipe_hnd, mem_ctx, &connect_hnd, domain_sids[i], trusted_dom_names[i]); - if (!NT_STATUS_IS_OK(nt_status)) + if (!NT_STATUS_IS_OK(nt_status)) { + cli_shutdown(cli); return -1; + } }; /* @@ -5265,15 +5413,15 @@ static int rpc_trustdom_vampire(int argc, const char **argv) } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES)); /* close this connection before doing next one */ - nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd); + nt_status = rpccli_lsa_close(pipe_hnd, mem_ctx, &connect_hnd); if (NT_STATUS_IS_ERR(nt_status)) { DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n", nt_errstr(nt_status))); + cli_shutdown(cli); return -1; }; /* close lsarpc pipe and connection to IPC$ */ - cli_nt_session_close(cli); cli_shutdown(cli); talloc_destroy(mem_ctx); @@ -5284,7 +5432,8 @@ static int rpc_trustdom_list(int argc, const char **argv) { /* common variables */ TALLOC_CTX* mem_ctx; - struct cli_state *cli, *remote_cli; + struct cli_state *cli = NULL, *remote_cli = NULL; + struct rpc_pipe_client *pipe_hnd = NULL; NTSTATUS nt_status; const char *domain_name = NULL; DOM_SID *queried_dom_sid; @@ -5331,12 +5480,14 @@ static int rpc_trustdom_list(int argc, const char **argv) return -1; }; - if (!cli_nt_session_open(cli, PI_LSARPC)) { - DEBUG(0, ("Could not initialise lsa pipe\n")); + pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &nt_status); + if (!pipe_hnd) { + DEBUG(0, ("Could not initialise lsa pipe. Error was %s\n", + nt_errstr(nt_status) )); return -1; }; - nt_status = cli_lsa_open_policy2(cli, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE, + nt_status = rpccli_lsa_open_policy2(pipe_hnd, mem_ctx, False, SEC_RIGHTS_QUERY_VALUE, &connect_hnd); if (NT_STATUS_IS_ERR(nt_status)) { DEBUG(0, ("Couldn't open policy handle. Error was %s\n", @@ -5345,8 +5496,8 @@ static int rpc_trustdom_list(int argc, const char **argv) }; /* query info level 5 to obtain sid of a domain being queried */ - nt_status = cli_lsa_query_info_policy( - cli, mem_ctx, &connect_hnd, 5 /* info level */, + nt_status = rpccli_lsa_query_info_policy( + pipe_hnd, mem_ctx, &connect_hnd, 5 /* info level */, &dummy, &queried_dom_sid); if (NT_STATUS_IS_ERR(nt_status)) { @@ -5363,7 +5514,7 @@ static int rpc_trustdom_list(int argc, const char **argv) d_printf("Trusted domains list:\n\n"); do { - nt_status = cli_lsa_enum_trust_dom(cli, mem_ctx, &connect_hnd, &enum_ctx, + nt_status = rpccli_lsa_enum_trust_dom(pipe_hnd, mem_ctx, &connect_hnd, &enum_ctx, &num_domains, &trusted_dom_names, &domain_sids); @@ -5386,14 +5537,14 @@ static int rpc_trustdom_list(int argc, const char **argv) } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES)); /* close this connection before doing next one */ - nt_status = cli_lsa_close(cli, mem_ctx, &connect_hnd); + nt_status = rpccli_lsa_close(pipe_hnd, mem_ctx, &connect_hnd); if (NT_STATUS_IS_ERR(nt_status)) { DEBUG(0, ("Couldn't properly close lsa policy handle. Error was %s\n", nt_errstr(nt_status))); return -1; }; - cli_nt_session_close(cli); + cli_rpc_pipe_close(pipe_hnd); /* * Listing trusting domains (stored in passdb backend, if local) @@ -5404,13 +5555,14 @@ static int rpc_trustdom_list(int argc, const char **argv) /* * Open \PIPE\samr and get needed policy handles */ - if (!cli_nt_session_open(cli, PI_SAMR)) { - DEBUG(0, ("Could not initialise samr pipe\n")); + pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &nt_status); + if (!pipe_hnd) { + DEBUG(0, ("Could not initialise samr pipe. Error was %s\n", nt_errstr(nt_status))); return -1; }; /* SamrConnect */ - nt_status = cli_samr_connect(cli, mem_ctx, SA_RIGHT_SAM_OPEN_DOMAIN, + nt_status = rpccli_samr_connect(pipe_hnd, mem_ctx, SA_RIGHT_SAM_OPEN_DOMAIN, &connect_hnd); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("Couldn't open SAMR policy handle. Error was %s\n", @@ -5420,7 +5572,7 @@ static int rpc_trustdom_list(int argc, const char **argv) /* SamrOpenDomain - we have to open domain policy handle in order to be able to enumerate accounts*/ - nt_status = cli_samr_open_domain(cli, mem_ctx, &connect_hnd, + nt_status = rpccli_samr_open_domain(pipe_hnd, mem_ctx, &connect_hnd, SA_RIGHT_DOMAIN_ENUM_ACCOUNTS, queried_dom_sid, &domain_hnd); if (!NT_STATUS_IS_OK(nt_status)) { @@ -5436,7 +5588,7 @@ static int rpc_trustdom_list(int argc, const char **argv) enum_ctx = 0; /* reset enumeration context from last enumeration */ do { - nt_status = cli_samr_enum_dom_users(cli, mem_ctx, &domain_hnd, + nt_status = rpccli_samr_enum_dom_users(pipe_hnd, mem_ctx, &domain_hnd, &enum_ctx, ACB_DOMTRUST, 0xffff, &trusting_dom_names, &trusting_dom_rids, &num_domains); @@ -5490,18 +5642,17 @@ static int rpc_trustdom_list(int argc, const char **argv) } while (NT_STATUS_EQUAL(nt_status, STATUS_MORE_ENTRIES)); /* close opened samr and domain policy handles */ - nt_status = cli_samr_close(cli, mem_ctx, &domain_hnd); + nt_status = rpccli_samr_close(pipe_hnd, mem_ctx, &domain_hnd); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("Couldn't properly close domain policy handle for domain %s\n", domain_name)); }; - nt_status = cli_samr_close(cli, mem_ctx, &connect_hnd); + nt_status = rpccli_samr_close(pipe_hnd, mem_ctx, &connect_hnd); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0, ("Couldn't properly close samr policy handle for domain %s\n", domain_name)); }; /* close samr pipe and connection to IPC$ */ - cli_nt_session_close(cli); cli_shutdown(cli); talloc_destroy(mem_ctx); @@ -5577,7 +5728,7 @@ BOOL net_rpc_check(unsigned flags) /* dump sam database via samsync rpc calls */ static int rpc_samdump(int argc, const char **argv) { - return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_samdump_internals, + return run_rpc_command(NULL, PI_NETLOGON, NET_FLAGS_ANONYMOUS, rpc_samdump_internals, argc, argv); } diff --git a/source3/utils/net_rpc_join.c b/source3/utils/net_rpc_join.c index 8d19ad888fc..6b762563b3b 100644 --- a/source3/utils/net_rpc_join.c +++ b/source3/utils/net_rpc_join.c @@ -35,7 +35,6 @@ goto done; \ } - /** * confirm that a domain join is still valid * @@ -44,44 +43,30 @@ **/ static int net_rpc_join_ok(const char *domain) { - struct cli_state *cli; - uchar stored_md4_trust_password[16]; + struct cli_state *cli = NULL; + struct rpc_pipe_client *pipe_hnd = NULL; int retval = 1; - uint32 channel; + NTSTATUS ret; /* Connect to remote machine */ if (!(cli = net_make_ipc_connection(NET_FLAGS_ANONYMOUS | NET_FLAGS_PDC))) { return 1; } - if (!cli_nt_session_open(cli, PI_NETLOGON)) { - DEBUG(0,("Error connecting to NETLOGON pipe\n")); - goto done; - } + pipe_hnd = cli_rpc_pipe_open_schannel(cli, PI_NETLOGON, + PIPE_AUTH_LEVEL_PRIVACY, + domain, &ret); - if (!secrets_fetch_trust_account_password(domain, - stored_md4_trust_password, - NULL, &channel)) { - DEBUG(0,("Could not retreive domain trust secret")); + if (!pipe_hnd) { + DEBUG(0,("Error connecting to NETLOGON pipe. Error was %s\n", nt_errstr(ret) )); goto done; } - - /* ensure that schannel uses the right domain */ - fstrcpy(cli->domain, domain); - if (! NT_STATUS_IS_OK(cli_nt_establish_netlogon(cli, channel, stored_md4_trust_password))) { - DEBUG(0,("Error in domain join verfication (fresh connection)\n")); - goto done; - } - + retval = 0; /* Success! */ done: - /* Close down pipe - this will clean up open policy handles */ - if (cli->pipes[cli->pipe_idx].fnum) - cli_nt_session_close(cli); cli_shutdown(cli); - return retval; } @@ -103,7 +88,10 @@ int net_rpc_join_newstyle(int argc, const char **argv) struct cli_state *cli; TALLOC_CTX *mem_ctx; uint32 acb_info = ACB_WSTRUST; + uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS|NETLOGON_NEG_SCHANNEL; uint32 sec_channel_type; + struct rpc_pipe_client *pipe_hnd = NULL; + struct rpc_pipe_client *netlogon_schannel_pipe = NULL; /* rpc variables */ @@ -151,7 +139,7 @@ int net_rpc_join_newstyle(int argc, const char **argv) #endif } - /* Connect to remote machine */ + /* Make authenticated connection to remote machine */ if (!(cli = net_make_ipc_connection(NET_FLAGS_PDC))) return 1; @@ -163,38 +151,41 @@ int net_rpc_join_newstyle(int argc, const char **argv) /* Fetch domain sid */ - if (!cli_nt_session_open(cli, PI_LSARPC)) { - DEBUG(0, ("Error connecting to LSA pipe\n")); + pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_LSARPC, &result); + if (!pipe_hnd) { + DEBUG(0, ("Error connecting to LSA pipe. Error was %s\n", + nt_errstr(result) )); goto done; } - CHECK_RPC_ERR(cli_lsa_open_policy(cli, mem_ctx, True, + CHECK_RPC_ERR(rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &lsa_pol), "error opening lsa policy handle"); - CHECK_RPC_ERR(cli_lsa_query_info_policy(cli, mem_ctx, &lsa_pol, + CHECK_RPC_ERR(rpccli_lsa_query_info_policy(pipe_hnd, mem_ctx, &lsa_pol, 5, &domain, &domain_sid), "error querying info policy"); - cli_lsa_close(cli, mem_ctx, &lsa_pol); - - cli_nt_session_close(cli); /* Done with this pipe */ + rpccli_lsa_close(pipe_hnd, mem_ctx, &lsa_pol); + cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */ /* Create domain user */ - if (!cli_nt_session_open(cli, PI_SAMR)) { - DEBUG(0, ("Error connecting to SAM pipe\n")); + pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_SAMR, &result); + if (!pipe_hnd) { + DEBUG(0, ("Error connecting to SAM pipe. Error was %s\n", + nt_errstr(result) )); goto done; } - CHECK_RPC_ERR(cli_samr_connect(cli, mem_ctx, + CHECK_RPC_ERR(rpccli_samr_connect(pipe_hnd, mem_ctx, SEC_RIGHTS_MAXIMUM_ALLOWED, &sam_pol), "could not connect to SAM database"); - CHECK_RPC_ERR(cli_samr_open_domain(cli, mem_ctx, &sam_pol, + CHECK_RPC_ERR(rpccli_samr_open_domain(pipe_hnd, mem_ctx, &sam_pol, SEC_RIGHTS_MAXIMUM_ALLOWED, domain_sid, &domain_pol), "could not open domain"); @@ -204,7 +195,7 @@ int net_rpc_join_newstyle(int argc, const char **argv) strlower_m(acct_name); const_acct_name = acct_name; - result = cli_samr_create_dom_user(cli, mem_ctx, &domain_pol, + result = rpccli_samr_create_dom_user(pipe_hnd, mem_ctx, &domain_pol, acct_name, acb_info, 0xe005000b, &user_pol, &user_rid); @@ -225,10 +216,11 @@ int net_rpc_join_newstyle(int argc, const char **argv) /* We *must* do this.... don't ask... */ - if (NT_STATUS_IS_OK(result)) - cli_samr_close(cli, mem_ctx, &user_pol); + if (NT_STATUS_IS_OK(result)) { + rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol); + } - CHECK_RPC_ERR_DEBUG(cli_samr_lookup_names(cli, mem_ctx, + CHECK_RPC_ERR_DEBUG(rpccli_samr_lookup_names(pipe_hnd, mem_ctx, &domain_pol, flags, 1, &const_acct_name, &num_rids, @@ -246,7 +238,7 @@ int net_rpc_join_newstyle(int argc, const char **argv) /* Open handle on user */ CHECK_RPC_ERR_DEBUG( - cli_samr_open_user(cli, mem_ctx, &domain_pol, + rpccli_samr_open_user(pipe_hnd, mem_ctx, &domain_pol, SEC_RIGHTS_MAXIMUM_ALLOWED, user_rid, &user_pol), ("could not re-open existing user %s: %s\n", @@ -273,7 +265,7 @@ int net_rpc_join_newstyle(int argc, const char **argv) ctr.switch_value = 24; ctr.info.id24 = &p24; - CHECK_RPC_ERR(cli_samr_set_userinfo(cli, mem_ctx, &user_pol, 24, + CHECK_RPC_ERR(rpccli_samr_set_userinfo(pipe_hnd, mem_ctx, &user_pol, 24, &cli->user_session_key, &ctr), "error setting trust account password"); @@ -295,26 +287,52 @@ int net_rpc_join_newstyle(int argc, const char **argv) /* Ignoring the return value is necessary for joining a domain as a normal user with "Add workstation to domain" privilege. */ - result = cli_samr_set_userinfo2(cli, mem_ctx, &user_pol, 16, + result = rpccli_samr_set_userinfo2(pipe_hnd, mem_ctx, &user_pol, 16, &cli->user_session_key, &ctr); + rpccli_samr_close(pipe_hnd, mem_ctx, &user_pol); + cli_rpc_pipe_close(pipe_hnd); /* Done with this pipe */ + /* Now check the whole process from top-to-bottom */ - cli_samr_close(cli, mem_ctx, &user_pol); - cli_nt_session_close(cli); /* Done with this pipe */ - if (!cli_nt_session_open(cli, PI_NETLOGON)) { - DEBUG(0,("Error connecting to NETLOGON pipe\n")); + pipe_hnd = cli_rpc_pipe_open_noauth(cli, PI_NETLOGON, &result); + if (!pipe_hnd) { + DEBUG(0,("Error connecting to NETLOGON pipe. Error was %s\n", + nt_errstr(result) )); goto done; } - /* ensure that schannel uses the right domain */ - fstrcpy(cli->domain, domain); + result = rpccli_netlogon_setup_creds(pipe_hnd, + cli->desthost, + domain, + global_myname(), + md4_trust_password, + sec_channel_type, + &neg_flags); + + if (!NT_STATUS_IS_OK(result)) { + DEBUG(0, ("Error in domain join verification (credential setup failed): %s\n\n", + nt_errstr(result))); - result = cli_nt_establish_netlogon(cli, sec_channel_type, - md4_trust_password); + if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && + (sec_channel_type == SEC_CHAN_BDC) ) { + d_printf("Please make sure that no computer account\n" + "named like this machine (%s) exists in the domain\n", + global_myname()); + } + + goto done; + } + + netlogon_schannel_pipe = cli_rpc_pipe_open_schannel_with_key(cli, + PI_NETLOGON, + PIPE_AUTH_LEVEL_PRIVACY, + domain, + pipe_hnd->dc, + &result); if (!NT_STATUS_IS_OK(result)) { - DEBUG(0, ("Error domain join verification (reused connection): %s\n\n", + DEBUG(0, ("Error in domain join verification (schannel setup failed): %s\n\n", nt_errstr(result))); if ( NT_STATUS_EQUAL(result, NT_STATUS_ACCESS_DENIED) && @@ -327,6 +345,9 @@ int net_rpc_join_newstyle(int argc, const char **argv) goto done; } + cli_rpc_pipe_close(pipe_hnd); + cli_rpc_pipe_close(netlogon_schannel_pipe); + /* Now store the secret in the secrets database */ strupper_m(domain); @@ -344,10 +365,6 @@ int net_rpc_join_newstyle(int argc, const char **argv) retval = net_rpc_join_ok(domain); done: - /* Close down pipe - this will clean up open policy handles */ - - if (cli->pipes[cli->pipe_idx].fnum) - cli_nt_session_close(cli); /* Display success or failure */ @@ -364,7 +381,6 @@ done: return retval; } - /** * check that a join is OK * diff --git a/source3/utils/net_rpc_printer.c b/source3/utils/net_rpc_printer.c index e82db46b9f4..d8f3099dec8 100644 --- a/source3/utils/net_rpc_printer.c +++ b/source3/utils/net_rpc_printer.c @@ -49,9 +49,11 @@ static const struct table_node archi_table[]= { * possibly be removed later on * **/ + /**************************************************************************** -convert a security permissions into a string + Convert a security permissions into a string. ****************************************************************************/ + char *get_sec_mask_str(uint32 type) { static fstring typestr=""; @@ -86,10 +88,10 @@ char *get_sec_mask_str(uint32 type) return typestr; } - /**************************************************************************** - display sec_ace structure + Display sec_ace structure. ****************************************************************************/ + void display_sec_ace(SEC_ACE *ace) { fstring sid_str; @@ -119,10 +121,10 @@ void display_sec_ace(SEC_ACE *ace) printf("\t\tSID: %s\n\n", sid_str); } - /**************************************************************************** - display sec_acl structure + Display sec_acl structure. ****************************************************************************/ + void display_sec_acl(SEC_ACL *sec_acl) { int i; @@ -138,8 +140,9 @@ void display_sec_acl(SEC_ACL *sec_acl) } /**************************************************************************** - display sec_desc structure + Display sec_desc structure. ****************************************************************************/ + void display_sec_desc(SEC_DESC *sec) { fstring sid_str; @@ -175,8 +178,9 @@ void display_sec_desc(SEC_DESC *sec) **/ /**************************************************************************** -printer info level 3 display function + Printer info level 3 display function. ****************************************************************************/ + static void display_print_driver_3(DRIVER_INFO_3 *i1) { fstring name = ""; @@ -233,7 +237,6 @@ static void display_print_driver_3(DRIVER_INFO_3 *i1) return; } - static void display_reg_value(const char *subkey, REGISTRY_VALUE value) { pstring text; @@ -275,7 +278,6 @@ static void display_reg_value(const char *subkey, REGISTRY_VALUE value) } - /** * Copies ACLs, DOS-attributes and timestamps from one * file or directory from one connected share to another connected share @@ -292,6 +294,7 @@ static void display_reg_value(const char *subkey, REGISTRY_VALUE value) * * @return Normal NTSTATUS return. **/ + NTSTATUS net_copy_fileattr(TALLOC_CTX *mem_ctx, struct cli_state *cli_share_src, struct cli_state *cli_share_dst, @@ -310,7 +313,6 @@ NTSTATUS net_copy_fileattr(TALLOC_CTX *mem_ctx, if (!copy_timestamps && !copy_acls && !copy_attrs) return NT_STATUS_OK; - /* open file/dir on the originating server */ DEBUGADD(3,("opening %s %s on originating server\n", @@ -429,7 +431,6 @@ out: return nt_status; } - /** * Copy a file or directory from a connected share to another connected share * @@ -445,6 +446,7 @@ out: * * @return Normal NTSTATUS return. **/ + NTSTATUS net_copy_file(TALLOC_CTX *mem_ctx, struct cli_state *cli_share_src, struct cli_state *cli_share_dst, @@ -605,7 +607,6 @@ out: return nt_status; } - /** * Copy a driverfile from on connected share to another connected share * This silently assumes that a driver-file is picked up from @@ -625,6 +626,7 @@ out: * * @return Normal NTSTATUS return. **/ + static NTSTATUS net_copy_driverfile(TALLOC_CTX *mem_ctx, struct cli_state *cli_share_src, struct cli_state *cli_share_dst, @@ -673,7 +675,6 @@ out: return nt_status; } - /** * Check for existing Architecture directory on a given server * @@ -682,8 +683,8 @@ out: * * @return Normal NTSTATUS return. **/ -static NTSTATUS -check_arch_dir(struct cli_state *cli_share, const char *short_archi) + +static NTSTATUS check_arch_dir(struct cli_state *cli_share, const char *short_archi) { NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; @@ -715,7 +716,6 @@ out: return nt_status; } - /** * Copy a print-driver (level 3) from one connected print$-share to another * connected print$-share @@ -728,8 +728,8 @@ out: * * @return Normal NTSTATUS return. **/ -static NTSTATUS -copy_print_driver_3(TALLOC_CTX *mem_ctx, + +static NTSTATUS copy_print_driver_3(TALLOC_CTX *mem_ctx, struct cli_state *cli_share_src, struct cli_state *cli_share_dst, const char *short_archi, DRIVER_INFO_3 *i1) @@ -799,7 +799,6 @@ copy_print_driver_3(TALLOC_CTX *mem_ctx, return NT_STATUS_OK; } - /** * net_spoolss-functions * ===================== @@ -812,16 +811,18 @@ copy_print_driver_3(TALLOC_CTX *mem_ctx, * **/ -static BOOL -net_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx, - char *name, uint32 flags, uint32 level, - uint32 *num_printers, PRINTER_INFO_CTR *ctr) +static BOOL net_spoolss_enum_printers(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + char *name, + uint32 flags, + uint32 level, + uint32 *num_printers, + PRINTER_INFO_CTR *ctr) { - WERROR result; /* enum printers */ - result = cli_spoolss_enum_printers(cli, mem_ctx, name, flags, + result = rpccli_spoolss_enum_printers(pipe_hnd, mem_ctx, name, flags, level, num_printers, ctr); if (!W_ERROR_IS_OK(result)) { @@ -832,16 +833,17 @@ net_spoolss_enum_printers(struct cli_state *cli, TALLOC_CTX *mem_ctx, return True; } - -static BOOL -net_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx, - const char *printername, uint32 access_required, - const char *username, POLICY_HND *hnd) +static BOOL net_spoolss_open_printer_ex(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + const char *printername, + uint32 access_required, + const char *username, + POLICY_HND *hnd) { WERROR result; fstring servername, printername2; - slprintf(servername, sizeof(servername)-1, "\\\\%s", cli->desthost); + slprintf(servername, sizeof(servername)-1, "\\\\%s", pipe_hnd->cli->desthost); fstrcpy(printername2, servername); fstrcat(printername2, "\\"); @@ -851,7 +853,7 @@ net_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx, servername, username, printername2, access_required)); /* open printer */ - result = cli_spoolss_open_printer_ex(cli, mem_ctx, printername2, + result = rpccli_spoolss_open_printer_ex(pipe_hnd, mem_ctx, printername2, "", access_required, servername, username, hnd); @@ -874,16 +876,16 @@ net_spoolss_open_printer_ex(struct cli_state *cli, TALLOC_CTX *mem_ctx, return True; } - -static BOOL -net_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *hnd, uint32 level, - PRINTER_INFO_CTR *ctr) +static BOOL net_spoolss_getprinter(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, + uint32 level, + PRINTER_INFO_CTR *ctr) { WERROR result; /* getprinter call */ - result = cli_spoolss_getprinter(cli, mem_ctx, hnd, level, ctr); + result = rpccli_spoolss_getprinter(pipe_hnd, mem_ctx, hnd, level, ctr); if (!W_ERROR_IS_OK(result)) { printf("cannot get printer-info: %s\n", dos_errstr(result)); @@ -893,16 +895,16 @@ net_spoolss_getprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, return True; } - -static BOOL -net_spoolss_setprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *hnd, uint32 level, - PRINTER_INFO_CTR *ctr) +static BOOL net_spoolss_setprinter(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, + uint32 level, + PRINTER_INFO_CTR *ctr) { WERROR result; /* setprinter call */ - result = cli_spoolss_setprinter(cli, mem_ctx, hnd, level, ctr, 0); + result = rpccli_spoolss_setprinter(pipe_hnd, mem_ctx, hnd, level, ctr, 0); if (!W_ERROR_IS_OK(result)) { printf("cannot set printer-info: %s\n", dos_errstr(result)); @@ -913,14 +915,15 @@ net_spoolss_setprinter(struct cli_state *cli, TALLOC_CTX *mem_ctx, } -static BOOL -net_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *hnd, REGISTRY_VALUE *value) +static BOOL net_spoolss_setprinterdata(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, + REGISTRY_VALUE *value) { WERROR result; /* setprinterdata call */ - result = cli_spoolss_setprinterdata(cli, mem_ctx, hnd, value); + result = rpccli_spoolss_setprinterdata(pipe_hnd, mem_ctx, hnd, value); if (!W_ERROR_IS_OK(result)) { printf ("unable to set printerdata: %s\n", dos_errstr(result)); @@ -931,15 +934,16 @@ net_spoolss_setprinterdata(struct cli_state *cli, TALLOC_CTX *mem_ctx, } -static BOOL -net_spoolss_enumprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *hnd, const char *keyname, - uint16 **keylist) +static BOOL net_spoolss_enumprinterkey(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, + const char *keyname, + uint16 **keylist) { WERROR result; /* enumprinterkey call */ - result = cli_spoolss_enumprinterkey(cli, mem_ctx, hnd, keyname, keylist, NULL); + result = rpccli_spoolss_enumprinterkey(pipe_hnd, mem_ctx, hnd, keyname, keylist, NULL); if (!W_ERROR_IS_OK(result)) { printf("enumprinterkey failed: %s\n", dos_errstr(result)); @@ -949,17 +953,17 @@ net_spoolss_enumprinterkey(struct cli_state *cli, TALLOC_CTX *mem_ctx, return True; } - -static BOOL -net_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx, - uint32 offered, - POLICY_HND *hnd, const char *keyname, - REGVAL_CTR *ctr) +static BOOL net_spoolss_enumprinterdataex(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + uint32 offered, + POLICY_HND *hnd, + const char *keyname, + REGVAL_CTR *ctr) { WERROR result; /* enumprinterdataex call */ - result = cli_spoolss_enumprinterdataex(cli, mem_ctx, hnd, keyname, ctr); + result = rpccli_spoolss_enumprinterdataex(pipe_hnd, mem_ctx, hnd, keyname, ctr); if (!W_ERROR_IS_OK(result)) { printf("enumprinterdataex failed: %s\n", dos_errstr(result)); @@ -970,15 +974,16 @@ net_spoolss_enumprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx, } -static BOOL -net_spoolss_setprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *hnd, char *keyname, - REGISTRY_VALUE *value) +static BOOL net_spoolss_setprinterdataex(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, + char *keyname, + REGISTRY_VALUE *value) { WERROR result; /* setprinterdataex call */ - result = cli_spoolss_setprinterdataex(cli, mem_ctx, hnd, + result = rpccli_spoolss_setprinterdataex(pipe_hnd, mem_ctx, hnd, keyname, value); if (!W_ERROR_IS_OK(result)) { @@ -989,17 +994,18 @@ net_spoolss_setprinterdataex(struct cli_state *cli, TALLOC_CTX *mem_ctx, return True; } - -static BOOL -net_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *hnd, int level, uint32 *num_forms, - FORM_1 **forms) +static BOOL net_spoolss_enumforms(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + POLICY_HND *hnd, + int level, + uint32 *num_forms, + FORM_1 **forms) { WERROR result; /* enumforms call */ - result = cli_spoolss_enumforms(cli, mem_ctx, hnd, level, num_forms, forms); + result = rpccli_spoolss_enumforms(pipe_hnd, mem_ctx, hnd, level, num_forms, forms); if (!W_ERROR_IS_OK(result)) { printf("could not enum forms: %s\n", dos_errstr(result)); @@ -1009,18 +1015,17 @@ net_spoolss_enumforms(struct cli_state *cli, TALLOC_CTX *mem_ctx, return True; } - -static BOOL -net_spoolss_enumprinterdrivers (struct cli_state *cli, TALLOC_CTX *mem_ctx, - uint32 level, const char *env, - uint32 *num_drivers, - PRINTER_DRIVER_CTR *ctr) +static BOOL net_spoolss_enumprinterdrivers (struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + uint32 level, const char *env, + uint32 *num_drivers, + PRINTER_DRIVER_CTR *ctr) { WERROR result; /* enumprinterdrivers call */ - result = cli_spoolss_enumprinterdrivers( - cli, mem_ctx, level, + result = rpccli_spoolss_enumprinterdrivers( + pipe_hnd, mem_ctx, level, env, num_drivers, ctr); if (!W_ERROR_IS_OK(result)) { @@ -1031,9 +1036,7 @@ net_spoolss_enumprinterdrivers (struct cli_state *cli, TALLOC_CTX *mem_ctx, return True; } - -static BOOL -net_spoolss_getprinterdriver(struct cli_state *cli, +static BOOL net_spoolss_getprinterdriver(struct rpc_pipe_client *pipe_hnd, TALLOC_CTX *mem_ctx, POLICY_HND *hnd, uint32 level, const char *env, int version, @@ -1042,8 +1045,8 @@ net_spoolss_getprinterdriver(struct cli_state *cli, WERROR result; /* getprinterdriver call */ - result = cli_spoolss_getprinterdriver( - cli, mem_ctx, hnd, level, + result = rpccli_spoolss_getprinterdriver( + pipe_hnd, mem_ctx, hnd, level, env, version, ctr); if (!W_ERROR_IS_OK(result)) { @@ -1060,15 +1063,14 @@ net_spoolss_getprinterdriver(struct cli_state *cli, } -static BOOL -net_spoolss_addprinterdriver(struct cli_state *cli, +static BOOL net_spoolss_addprinterdriver(struct rpc_pipe_client *pipe_hnd, TALLOC_CTX *mem_ctx, uint32 level, PRINTER_DRIVER_CTR *ctr) { WERROR result; /* addprinterdriver call */ - result = cli_spoolss_addprinterdriver(cli, mem_ctx, level, ctr); + result = rpccli_spoolss_addprinterdriver(pipe_hnd, mem_ctx, level, ctr); /* be more verbose */ if (W_ERROR_V(result) == W_ERROR_V(WERR_ACCESS_DENIED)) { @@ -1087,10 +1089,14 @@ net_spoolss_addprinterdriver(struct cli_state *cli, * abstraction function to get uint32 num_printers and PRINTER_INFO_CTR ctr * for a single printer or for all printers depending on argc/argv **/ -static BOOL -get_printer_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, - int level, int argc, const char **argv, - uint32 *num_printers, PRINTER_INFO_CTR *ctr) + +static BOOL get_printer_info(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int level, + int argc, + const char **argv, + uint32 *num_printers, + PRINTER_INFO_CTR *ctr) { POLICY_HND hnd; @@ -1098,7 +1104,7 @@ get_printer_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* no arguments given, enumerate all printers */ if (argc == 0) { - if (!net_spoolss_enum_printers(cli, mem_ctx, NULL, + if (!net_spoolss_enum_printers(pipe_hnd, mem_ctx, NULL, PRINTER_ENUM_LOCAL|PRINTER_ENUM_SHARED, level, num_printers, ctr)) return False; @@ -1108,16 +1114,16 @@ get_printer_info(struct cli_state *cli, TALLOC_CTX *mem_ctx, /* argument given, get a single printer by name */ - if (!net_spoolss_open_printer_ex(cli, mem_ctx, argv[0], - MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd)) + if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, argv[0], + MAXIMUM_ALLOWED_ACCESS, pipe_hnd->cli->user_name, &hnd)) return False; - if (!net_spoolss_getprinter(cli, mem_ctx, &hnd, level, ctr)) { - cli_spoolss_close_printer(cli, mem_ctx, &hnd); + if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, ctr)) { + rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd); return False; } - cli_spoolss_close_printer(cli, mem_ctx, &hnd); + rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd); *num_printers = 1; @@ -1128,7 +1134,6 @@ out: } - /** * List print-queues (including local printers that are not shared) * @@ -1144,9 +1149,14 @@ out: * * @return Normal NTSTATUS return. **/ -NTSTATUS rpc_printer_list_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) + +NTSTATUS rpc_printer_list_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; uint32 i, num_printers; @@ -1156,7 +1166,7 @@ NTSTATUS rpc_printer_list_internals(const DOM_SID *domain_sid, const char *domai printf("listing printers\n"); - if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr)) + if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &ctr)) return nt_status; for (i = 0; i < num_printers; i++) { @@ -1174,7 +1184,6 @@ NTSTATUS rpc_printer_list_internals(const DOM_SID *domain_sid, const char *domai return NT_STATUS_OK; } - /** * List printer-drivers from a server * @@ -1190,9 +1199,14 @@ NTSTATUS rpc_printer_list_internals(const DOM_SID *domain_sid, const char *domai * * @return Normal NTSTATUS return. **/ -NTSTATUS rpc_printer_driver_list_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) + +NTSTATUS rpc_printer_driver_list_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; uint32 i; @@ -1202,7 +1216,6 @@ NTSTATUS rpc_printer_driver_list_internals(const DOM_SID *domain_sid, const char ZERO_STRUCT(drv_ctr_enum); - printf("listing printer-drivers\n"); for (i=0; archi_table[i].long_archi!=NULL; i++) { @@ -1210,7 +1223,7 @@ NTSTATUS rpc_printer_driver_list_internals(const DOM_SID *domain_sid, const char uint32 num_drivers; /* enum remote drivers */ - if (!net_spoolss_enumprinterdrivers(cli, mem_ctx, level, + if (!net_spoolss_enumprinterdrivers(pipe_hnd, mem_ctx, level, archi_table[i].long_archi, &num_drivers, &drv_ctr_enum)) { @@ -1254,8 +1267,11 @@ done: * @return Normal NTSTATUS return. **/ -static NTSTATUS rpc_printer_publish_internals_args(struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv, uint32 action) +static NTSTATUS rpc_printer_publish_internals_args(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv, + uint32 action) { NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; uint32 i, num_printers; @@ -1267,7 +1283,7 @@ static NTSTATUS rpc_printer_publish_internals_args(struct cli_state *cli, TALLOC WERROR result; const char *action_str; - if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &ctr)) + if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &ctr)) return nt_status; for (i = 0; i < num_printers; i++) { @@ -1279,14 +1295,14 @@ static NTSTATUS rpc_printer_publish_internals_args(struct cli_state *cli, TALLOC sizeof(sharename), -1, STR_TERMINATE); /* open printer handle */ - if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, - PRINTER_ALL_ACCESS, cli->user_name, &hnd)) + if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename, + PRINTER_ALL_ACCESS, pipe_hnd->cli->user_name, &hnd)) goto done; got_hnd = True; /* check for existing dst printer */ - if (!net_spoolss_getprinter(cli, mem_ctx, &hnd, level, &ctr_pub)) + if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &ctr_pub)) goto done; /* check action and set string */ @@ -1308,7 +1324,7 @@ static NTSTATUS rpc_printer_publish_internals_args(struct cli_state *cli, TALLOC ctr_pub.printers_7->action = action; - result = cli_spoolss_setprinter(cli, mem_ctx, &hnd, level, &ctr_pub, 0); + result = rpccli_spoolss_setprinter(pipe_hnd, mem_ctx, &hnd, level, &ctr_pub, 0); if (!W_ERROR_IS_OK(result) && (W_ERROR_V(result) != W_ERROR_V(WERR_IO_PENDING))) { printf("cannot set printer-info: %s\n", dos_errstr(result)); goto done; @@ -1321,30 +1337,42 @@ static NTSTATUS rpc_printer_publish_internals_args(struct cli_state *cli, TALLOC done: if (got_hnd) - cli_spoolss_close_printer(cli, mem_ctx, &hnd); + rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd); return nt_status; } -NTSTATUS rpc_printer_publish_publish_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) +NTSTATUS rpc_printer_publish_publish_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { - return rpc_printer_publish_internals_args(cli, mem_ctx, argc, argv, SPOOL_DS_PUBLISH); + return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, SPOOL_DS_PUBLISH); } -NTSTATUS rpc_printer_publish_unpublish_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) +NTSTATUS rpc_printer_publish_unpublish_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { - return rpc_printer_publish_internals_args(cli, mem_ctx, argc, argv, SPOOL_DS_UNPUBLISH); + return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, SPOOL_DS_UNPUBLISH); } -NTSTATUS rpc_printer_publish_update_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) +NTSTATUS rpc_printer_publish_update_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { - return rpc_printer_publish_internals_args(cli, mem_ctx, argc, argv, SPOOL_DS_UPDATE); + return rpc_printer_publish_internals_args(pipe_hnd, mem_ctx, argc, argv, SPOOL_DS_UPDATE); } /** @@ -1362,9 +1390,14 @@ NTSTATUS rpc_printer_publish_update_internals(const DOM_SID *domain_sid, const c * * @return Normal NTSTATUS return. **/ -NTSTATUS rpc_printer_publish_list_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) + +NTSTATUS rpc_printer_publish_list_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; uint32 i, num_printers; @@ -1376,7 +1409,7 @@ NTSTATUS rpc_printer_publish_list_internals(const DOM_SID *domain_sid, const cha BOOL got_hnd = False; int state; - if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &ctr)) + if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &ctr)) return nt_status; for (i = 0; i < num_printers; i++) { @@ -1390,14 +1423,14 @@ NTSTATUS rpc_printer_publish_list_internals(const DOM_SID *domain_sid, const cha sizeof(sharename), -1, STR_TERMINATE); /* open printer handle */ - if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, + if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename, PRINTER_ALL_ACCESS, cli->user_name, &hnd)) goto done; got_hnd = True; /* check for existing dst printer */ - if (!net_spoolss_getprinter(cli, mem_ctx, &hnd, level, &ctr_pub)) + if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd, level, &ctr_pub)) goto done; rpcstr_pull(guid, ctr_pub.printers_7->guid.buffer, sizeof(guid), -1, STR_TERMINATE); @@ -1426,7 +1459,7 @@ NTSTATUS rpc_printer_publish_list_internals(const DOM_SID *domain_sid, const cha done: if (got_hnd) - cli_spoolss_close_printer(cli, mem_ctx, &hnd); + rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd); return nt_status; } @@ -1446,9 +1479,14 @@ done: * * @return Normal NTSTATUS return. **/ -NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) + +NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { /* TODO: what now, info2 or info3 ? convince jerry that we should add clientside setacls level 3 at least @@ -1460,7 +1498,7 @@ NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const pstring printername = "", sharename = ""; BOOL got_hnd_src = False; BOOL got_hnd_dst = False; - BOOL got_dst_spoolss_pipe = False; + struct rpc_pipe_client *pipe_hnd_dst = NULL; POLICY_HND hnd_src, hnd_dst; PRINTER_INFO_CTR ctr_src, ctr_dst, ctr_enum; struct cli_state *cli_dst = NULL; @@ -1470,13 +1508,13 @@ NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const DEBUG(3,("copying printer ACLs\n")); /* connect destination PI_SPOOLSS */ - nt_status = connect_dst_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe); + nt_status = connect_dst_pipe(&cli_dst, &pipe_hnd_dst, PI_SPOOLSS); if (!NT_STATUS_IS_OK(nt_status)) return nt_status; /* enum source printers */ - if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) { + if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) { nt_status = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -1487,7 +1525,6 @@ NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const goto done; } - /* do something for all printers */ for (i = 0; i < num_printers; i++) { @@ -1510,30 +1547,27 @@ NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const */ /* open src printer handle */ - if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, + if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename, MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src)) goto done; got_hnd_src = True; - /* open dst printer handle */ - if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, + if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename, PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst)) goto done; got_hnd_dst = True; - /* check for existing dst printer */ - if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) + if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) goto done; /* check for existing src printer */ - if (!net_spoolss_getprinter(cli, mem_ctx, &hnd_src, 3, &ctr_src)) + if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, 3, &ctr_src)) goto done; - /* Copy Security Descriptor */ /* copy secdesc (info level 2) */ @@ -1543,7 +1577,7 @@ NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const if (opt_verbose) display_sec_desc(ctr_dst.printers_2->secdesc); - if (!net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, 2, &ctr_dst)) + if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &ctr_dst)) goto done; DEBUGADD(1,("\tSetPrinter of SECDESC succeeded\n")); @@ -1551,12 +1585,12 @@ NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const /* close printer handles here */ if (got_hnd_src) { - cli_spoolss_close_printer(cli, mem_ctx, &hnd_src); + rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src); got_hnd_src = False; } if (got_hnd_dst) { - cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst); + rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst); got_hnd_dst = False; } @@ -1566,20 +1600,20 @@ NTSTATUS rpc_printer_migrate_security_internals(const DOM_SID *domain_sid, const done: - if (got_hnd_src) - cli_spoolss_close_printer(cli, mem_ctx, &hnd_src); + if (got_hnd_src) { + rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src); + } - if (got_hnd_dst) - cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst); + if (got_hnd_dst) { + rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst); + } - if (got_dst_spoolss_pipe) { - cli_nt_session_close(cli_dst); + if (cli_dst) { cli_shutdown(cli_dst); } return nt_status; } - /** * Migrate printer-forms from a src server to the dst server * @@ -1595,9 +1629,14 @@ done: * * @return Normal NTSTATUS return. **/ -NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) + +NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; WERROR result; @@ -1607,7 +1646,7 @@ NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const ch pstring printername = "", sharename = ""; BOOL got_hnd_src = False; BOOL got_hnd_dst = False; - BOOL got_dst_spoolss_pipe = False; + struct rpc_pipe_client *pipe_hnd_dst = NULL; POLICY_HND hnd_src, hnd_dst; PRINTER_INFO_CTR ctr_enum, ctr_dst; uint32 num_forms; @@ -1619,13 +1658,13 @@ NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const ch DEBUG(3,("copying forms\n")); /* connect destination PI_SPOOLSS */ - nt_status = connect_dst_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe); + nt_status = connect_dst_pipe(&cli_dst, &pipe_hnd_dst, PI_SPOOLSS); if (!NT_STATUS_IS_OK(nt_status)) return nt_status; /* enum src printers */ - if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &ctr_enum)) { + if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &ctr_enum)) { nt_status = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -1654,7 +1693,7 @@ NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const ch /* open src printer handle */ - if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, + if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename, MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src)) goto done; @@ -1662,7 +1701,7 @@ NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const ch /* open dst printer handle */ - if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, + if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename, PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) goto done; @@ -1670,11 +1709,11 @@ NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const ch /* check for existing dst printer */ - if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) + if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) goto done; /* finally migrate forms */ - if (!net_spoolss_enumforms(cli, mem_ctx, &hnd_src, level, &num_forms, &forms)) + if (!net_spoolss_enumforms(pipe_hnd, mem_ctx, &hnd_src, level, &num_forms, &forms)) goto done; DEBUG(1,("got %d forms for printer\n", num_forms)); @@ -1711,7 +1750,7 @@ NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const ch /* FIXME: there might be something wrong with samba's builtin-forms */ - result = cli_spoolss_addform(cli_dst, mem_ctx, + result = rpccli_spoolss_addform(pipe_hnd_dst, mem_ctx, &hnd_dst, 1, &form); if (!W_ERROR_IS_OK(result)) { d_printf("\tAddForm form %d: [%s] refused.\n", @@ -1725,12 +1764,12 @@ NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const ch /* close printer handles here */ if (got_hnd_src) { - cli_spoolss_close_printer(cli, mem_ctx, &hnd_src); + rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src); got_hnd_src = False; } if (got_hnd_dst) { - cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst); + rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst); got_hnd_dst = False; } } @@ -1740,20 +1779,17 @@ NTSTATUS rpc_printer_migrate_forms_internals(const DOM_SID *domain_sid, const ch done: if (got_hnd_src) - cli_spoolss_close_printer(cli, mem_ctx, &hnd_src); + rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src); if (got_hnd_dst) - cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst); + rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst); - if (got_dst_spoolss_pipe) { - cli_nt_session_close(cli_dst); + if (cli_dst) { cli_shutdown(cli_dst); } return nt_status; - } - /** * Migrate printer-drivers from a src server to the dst server * @@ -1769,9 +1805,14 @@ done: * * @return Normal NTSTATUS return. **/ -NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) + +NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; uint32 i, p; @@ -1780,9 +1821,9 @@ NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const pstring printername = "", sharename = ""; BOOL got_hnd_src = False; BOOL got_hnd_dst = False; - BOOL got_dst_spoolss_pipe = False; BOOL got_src_driver_share = False; BOOL got_dst_driver_share = False; + struct rpc_pipe_client *pipe_hnd_dst = NULL; POLICY_HND hnd_src, hnd_dst; PRINTER_DRIVER_CTR drv_ctr_src, drv_ctr_dst; PRINTER_INFO_CTR info_ctr_enum, info_ctr_dst; @@ -1799,7 +1840,7 @@ NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const DEBUG(3,("copying printer-drivers\n")); - nt_status = connect_dst_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe); + nt_status = connect_dst_pipe(&cli_dst, &pipe_hnd_dst, PI_SPOOLSS); if (!NT_STATUS_IS_OK(nt_status)) return nt_status; @@ -1823,7 +1864,7 @@ NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const /* enum src printers */ - if (!get_printer_info(cli, mem_ctx, 2, argc, argv, &num_printers, &info_ctr_enum)) { + if (!get_printer_info(pipe_hnd, mem_ctx, 2, argc, argv, &num_printers, &info_ctr_enum)) { nt_status = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -1851,20 +1892,20 @@ NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const printername, sharename); /* open dst printer handle */ - if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, + if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename, PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) goto done; got_hnd_dst = True; /* check for existing dst printer */ - if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst)) + if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst)) goto done; /* open src printer handle */ - if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, - MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src)) + if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename, + MAXIMUM_ALLOWED_ACCESS, pipe_hnd->cli->user_name, &hnd_src)) goto done; got_hnd_src = True; @@ -1876,7 +1917,7 @@ NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const for (i=0; archi_table[i].long_archi!=NULL; i++) { /* getdriver src */ - if (!net_spoolss_getprinterdriver(cli, mem_ctx, &hnd_src, + if (!net_spoolss_getprinterdriver(pipe_hnd, mem_ctx, &hnd_src, level, archi_table[i].long_archi, archi_table[i].version, &drv_ctr_src)) continue; @@ -1903,7 +1944,7 @@ NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const /* adddriver dst */ - if (!net_spoolss_addprinterdriver(cli_dst, mem_ctx, level, &drv_ctr_src)) { + if (!net_spoolss_addprinterdriver(pipe_hnd_dst, mem_ctx, level, &drv_ctr_src)) { nt_status = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -1922,7 +1963,7 @@ NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const /* setdriver dst */ init_unistr(&info_ctr_dst.printers_2->drivername, drivername); - if (!net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst)) { + if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 2, &info_ctr_dst)) { nt_status = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -1932,13 +1973,13 @@ NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const /* close dst */ if (got_hnd_dst) { - cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst); + rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst); got_hnd_dst = False; } /* close src */ if (got_hnd_src) { - cli_spoolss_close_printer(cli, mem_ctx, &hnd_src); + rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src); got_hnd_src = False; } } @@ -1948,13 +1989,12 @@ NTSTATUS rpc_printer_migrate_drivers_internals(const DOM_SID *domain_sid, const done: if (got_hnd_src) - cli_spoolss_close_printer(cli, mem_ctx, &hnd_src); + rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src); if (got_hnd_dst) - cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst); + rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst); - if (got_dst_spoolss_pipe) { - cli_nt_session_close(cli_dst); + if (cli_dst) { cli_shutdown(cli_dst); } @@ -1968,7 +2008,6 @@ done: } - /** * Migrate printer-queues from a src to the dst server * (requires a working "addprinter command" to be installed for the local smbd) @@ -1985,9 +2024,14 @@ done: * * @return Normal NTSTATUS return. **/ -NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) + +NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { WERROR result; NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; @@ -1999,18 +2043,18 @@ NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, const pstring printername, sharename; BOOL got_hnd_src = False; BOOL got_hnd_dst = False; - BOOL got_dst_spoolss_pipe = False; + struct rpc_pipe_client *pipe_hnd_dst = NULL; DEBUG(3,("copying printers\n")); /* connect destination PI_SPOOLSS */ - nt_status = connect_dst_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe); + nt_status = connect_dst_pipe(&cli_dst, &pipe_hnd_dst, PI_SPOOLSS); if (!NT_STATUS_IS_OK(nt_status)) return nt_status; /* enum printers */ - if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) { + if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) { nt_status = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -2039,7 +2083,7 @@ NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, const /* open dst printer handle */ - if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, + if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename, PRINTER_ALL_ACCESS, cli->user_name, &hnd_dst)) { DEBUG(1,("could not open printer: %s\n", sharename)); @@ -2049,18 +2093,18 @@ NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, const /* check for existing dst printer */ - if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) { + if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) { printf ("could not get printer, creating printer.\n"); } else { DEBUG(1,("printer already exists: %s\n", sharename)); /* close printer handles here */ if (got_hnd_src) { - cli_spoolss_close_printer(cli, mem_ctx, &hnd_src); + rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src); got_hnd_src = False; } if (got_hnd_dst) { - cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst); + rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst); got_hnd_dst = False; } continue; @@ -2071,21 +2115,21 @@ NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, const we first need a handle for that */ /* open src printer handle */ - if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, + if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename, MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src)) goto done; got_hnd_src = True; /* getprinter on the src server */ - if (!net_spoolss_getprinter(cli, mem_ctx, &hnd_src, level, &ctr_src)) + if (!net_spoolss_getprinter(pipe_hnd, mem_ctx, &hnd_src, level, &ctr_src)) goto done; /* copy each src printer to a dst printer 1:1, maybe some values have to be changed though */ d_printf("creating printer: %s\n", printername); - result = cli_spoolss_addprinterex (cli_dst, mem_ctx, level, &ctr_src); + result = rpccli_spoolss_addprinterex (pipe_hnd_dst, mem_ctx, level, &ctr_src); if (W_ERROR_IS_OK(result)) d_printf ("printer [%s] successfully added.\n", printername); @@ -2098,12 +2142,12 @@ NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, const /* close printer handles here */ if (got_hnd_src) { - cli_spoolss_close_printer(cli, mem_ctx, &hnd_src); + rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src); got_hnd_src = False; } if (got_hnd_dst) { - cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst); + rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst); got_hnd_dst = False; } } @@ -2112,19 +2156,17 @@ NTSTATUS rpc_printer_migrate_printers_internals(const DOM_SID *domain_sid, const done: if (got_hnd_src) - cli_spoolss_close_printer(cli, mem_ctx, &hnd_src); + rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src); if (got_hnd_dst) - cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst); + rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst); - if (got_dst_spoolss_pipe) { - cli_nt_session_close(cli_dst); + if (cli_dst) { cli_shutdown(cli_dst); } return nt_status; } - /** * Migrate Printer-Settings from a src server to the dst server * (for this to work, printers and drivers already have to be migrated earlier) @@ -2141,9 +2183,14 @@ done: * * @return Normal NTSTATUS return. **/ -NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) + +NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { /* FIXME: Here the nightmare begins */ @@ -2156,7 +2203,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const pstring printername = "", sharename = ""; BOOL got_hnd_src = False; BOOL got_hnd_dst = False; - BOOL got_dst_spoolss_pipe = False; + struct rpc_pipe_client *pipe_hnd_dst = NULL; POLICY_HND hnd_src, hnd_dst; PRINTER_INFO_CTR ctr_enum, ctr_dst, ctr_dst_publish; REGVAL_CTR *reg_ctr; @@ -2171,13 +2218,13 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const DEBUG(3,("copying printer settings\n")); /* connect destination PI_SPOOLSS */ - nt_status = connect_dst_pipe(&cli_dst, PI_SPOOLSS, &got_dst_spoolss_pipe); + nt_status = connect_dst_pipe(&cli_dst, &pipe_hnd_dst, PI_SPOOLSS); if (!NT_STATUS_IS_OK(nt_status)) return nt_status; /* enum src printers */ - if (!get_printer_info(cli, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) { + if (!get_printer_info(pipe_hnd, mem_ctx, level, argc, argv, &num_printers, &ctr_enum)) { nt_status = NT_STATUS_UNSUCCESSFUL; goto done; } @@ -2210,7 +2257,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const /* open src printer handle */ - if (!net_spoolss_open_printer_ex(cli, mem_ctx, sharename, + if (!net_spoolss_open_printer_ex(pipe_hnd, mem_ctx, sharename, MAXIMUM_ALLOWED_ACCESS, cli->user_name, &hnd_src)) goto done; @@ -2218,7 +2265,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const /* open dst printer handle */ - if (!net_spoolss_open_printer_ex(cli_dst, mem_ctx, sharename, + if (!net_spoolss_open_printer_ex(pipe_hnd_dst, mem_ctx, sharename, PRINTER_ALL_ACCESS, cli_dst->user_name, &hnd_dst)) goto done; @@ -2226,7 +2273,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const /* check for existing dst printer */ - if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, + if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) goto done; @@ -2245,13 +2292,13 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const if (ctr_enum.printers_2[i].attributes & PRINTER_ATTRIBUTE_PUBLISHED) { /* check for existing dst printer */ - if (!net_spoolss_getprinter(cli_dst, mem_ctx, &hnd_dst, 7, &ctr_dst_publish)) + if (!net_spoolss_getprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &ctr_dst_publish)) goto done; ctr_dst_publish.printers_7->action = SPOOL_DS_PUBLISH; /* ignore False from setprinter due to WERR_IO_PENDING */ - net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, 7, &ctr_dst_publish); + net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, 7, &ctr_dst_publish); DEBUG(3,("republished printer\n")); } @@ -2278,7 +2325,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const init_unistr(&ctr_dst.printers_2->devmode->devicename, devicename); #endif - if (!net_spoolss_setprinter(cli_dst, mem_ctx, &hnd_dst, + if (!net_spoolss_setprinter(pipe_hnd_dst, mem_ctx, &hnd_dst, level, &ctr_dst)) goto done; @@ -2288,13 +2335,13 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const /* STEP 2: COPY REGISTRY VALUES */ /* please keep in mind that samba parse_spools gives horribly - crippled results when used to cli_spoolss_enumprinterdataex + crippled results when used to rpccli_spoolss_enumprinterdataex a win2k3-server. (Bugzilla #1851) FIXME: IIRC I've seen it too on a win2k-server */ /* enumerate data on src handle */ - result = cli_spoolss_enumprinterdata(cli, mem_ctx, &hnd_src, p, 0, 0, + result = rpccli_spoolss_enumprinterdata(pipe_hnd, mem_ctx, &hnd_src, p, 0, 0, &val_needed, &data_needed, NULL); /* loop for all printerdata of "PrinterDriverData" */ @@ -2302,8 +2349,8 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const REGISTRY_VALUE value; - result = cli_spoolss_enumprinterdata( - cli, mem_ctx, &hnd_src, p++, val_needed, + result = rpccli_spoolss_enumprinterdata( + pipe_hnd, mem_ctx, &hnd_src, p++, val_needed, data_needed, 0, 0, &value); /* loop for all reg_keys */ @@ -2314,7 +2361,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const display_reg_value(SPOOL_PRINTERDATA_KEY, value); /* set_value */ - if (!net_spoolss_setprinterdata(cli_dst, mem_ctx, + if (!net_spoolss_setprinterdata(pipe_hnd_dst, mem_ctx, &hnd_dst, &value)) goto done; @@ -2330,7 +2377,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const respond to enumprinterkey, win2k does, so continue in case of an error */ - if (!net_spoolss_enumprinterkey(cli, mem_ctx, &hnd_src, "", &keylist)) { + if (!net_spoolss_enumprinterkey(pipe_hnd, mem_ctx, &hnd_src, "", &keylist)) { printf("got no key-data\n"); continue; } @@ -2355,7 +2402,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const return NT_STATUS_NO_MEMORY; /* enumerate all src subkeys */ - if (!net_spoolss_enumprinterdataex(cli, mem_ctx, 0, + if (!net_spoolss_enumprinterdataex(pipe_hnd, mem_ctx, 0, &hnd_src, subkey, reg_ctr)) goto done; @@ -2426,7 +2473,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const display_reg_value(subkey, value); /* here we have to set all subkeys on the dst server */ - if (!net_spoolss_setprinterdataex(cli_dst, mem_ctx, &hnd_dst, + if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst, subkey, &value)) goto done; @@ -2436,7 +2483,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const display_reg_value(subkey, *(reg_ctr->values[j])); /* here we have to set all subkeys on the dst server */ - if (!net_spoolss_setprinterdataex(cli_dst, mem_ctx, &hnd_dst, + if (!net_spoolss_setprinterdataex(pipe_hnd_dst, mem_ctx, &hnd_dst, subkey, reg_ctr->values[j])) goto done; @@ -2446,7 +2493,7 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const subkey, reg_ctr->values[j]->valuename)); } - + TALLOC_FREE( reg_ctr ); } @@ -2454,12 +2501,12 @@ NTSTATUS rpc_printer_migrate_settings_internals(const DOM_SID *domain_sid, const /* close printer handles here */ if (got_hnd_src) { - cli_spoolss_close_printer(cli, mem_ctx, &hnd_src); + rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src); got_hnd_src = False; } if (got_hnd_dst) { - cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst); + rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst); got_hnd_dst = False; } @@ -2473,13 +2520,12 @@ done: SAFE_FREE(unc_name); if (got_hnd_src) - cli_spoolss_close_printer(cli, mem_ctx, &hnd_src); + rpccli_spoolss_close_printer(pipe_hnd, mem_ctx, &hnd_src); if (got_hnd_dst) - cli_spoolss_close_printer(cli_dst, mem_ctx, &hnd_dst); + rpccli_spoolss_close_printer(pipe_hnd_dst, mem_ctx, &hnd_dst); - if (got_dst_spoolss_pipe) { - cli_nt_session_close(cli_dst); + if (cli_dst) { cli_shutdown(cli_dst); } return nt_status; diff --git a/source3/utils/net_rpc_registry.c b/source3/utils/net_rpc_registry.c index 8bb01cd89a8..33ccb6c1b7f 100644 --- a/source3/utils/net_rpc_registry.c +++ b/source3/utils/net_rpc_registry.c @@ -22,7 +22,6 @@ #include "regfio.h" #include "reg_objects.h" - /******************************************************************** ********************************************************************/ @@ -85,9 +84,13 @@ void dump_regval_buffer( uint32 type, REGVAL_BUFFER *buffer ) /******************************************************************** ********************************************************************/ -static NTSTATUS rpc_registry_enumerate_internal( const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv ) +static NTSTATUS rpc_registry_enumerate_internal(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv ) { WERROR result = WERR_GENERAL_FAILURE; uint32 hive; @@ -108,13 +111,13 @@ static NTSTATUS rpc_registry_enumerate_internal( const DOM_SID *domain_sid, cons /* open the top level hive and then the registry key */ - result = cli_reg_connect( cli, mem_ctx, hive, MAXIMUM_ALLOWED_ACCESS, &pol_hive ); + result = rpccli_reg_connect(pipe_hnd, mem_ctx, hive, MAXIMUM_ALLOWED_ACCESS, &pol_hive ); if ( !W_ERROR_IS_OK(result) ) { d_printf("Unable to connect to remote registry\n"); return werror_to_ntstatus(result); } - result = cli_reg_open_entry( cli, mem_ctx, &pol_hive, subpath, MAXIMUM_ALLOWED_ACCESS, &pol_key ); + result = rpccli_reg_open_entry(pipe_hnd, mem_ctx, &pol_hive, subpath, MAXIMUM_ALLOWED_ACCESS, &pol_key ); if ( !W_ERROR_IS_OK(result) ) { d_printf("Unable to open [%s]\n", argv[0]); return werror_to_ntstatus(result); @@ -128,7 +131,7 @@ static NTSTATUS rpc_registry_enumerate_internal( const DOM_SID *domain_sid, cons time_t modtime; fstring keyname, classname; - result = cli_reg_enum_key( cli, mem_ctx, &pol_key, idx, + result = rpccli_reg_enum_key(pipe_hnd, mem_ctx, &pol_key, idx, keyname, classname, &modtime ); if ( W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) { @@ -159,7 +162,7 @@ static NTSTATUS rpc_registry_enumerate_internal( const DOM_SID *domain_sid, cons fstrcpy( name, "" ); ZERO_STRUCT( value ); - result = cli_reg_enum_val( cli, mem_ctx, &pol_key, idx, + result = rpccli_reg_enum_val(pipe_hnd, mem_ctx, &pol_key, idx, name, &type, &value ); if ( W_ERROR_EQUAL(result, WERR_NO_MORE_ITEMS) ) { @@ -180,8 +183,8 @@ static NTSTATUS rpc_registry_enumerate_internal( const DOM_SID *domain_sid, cons out: /* cleanup */ - cli_reg_close( cli, mem_ctx, &pol_key ); - cli_reg_close( cli, mem_ctx, &pol_hive ); + rpccli_reg_close(pipe_hnd, mem_ctx, &pol_key ); + rpccli_reg_close(pipe_hnd, mem_ctx, &pol_hive ); return werror_to_ntstatus(result); } @@ -198,9 +201,13 @@ static int rpc_registry_enumerate( int argc, const char **argv ) /******************************************************************** ********************************************************************/ -static NTSTATUS rpc_registry_save_internal( const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv ) +static NTSTATUS rpc_registry_save_internal(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv ) { WERROR result = WERR_GENERAL_FAILURE; uint32 hive; @@ -219,19 +226,19 @@ static NTSTATUS rpc_registry_save_internal( const DOM_SID *domain_sid, const cha /* open the top level hive and then the registry key */ - result = cli_reg_connect( cli, mem_ctx, hive, MAXIMUM_ALLOWED_ACCESS, &pol_hive ); + result = rpccli_reg_connect(pipe_hnd, mem_ctx, hive, MAXIMUM_ALLOWED_ACCESS, &pol_hive ); if ( !W_ERROR_IS_OK(result) ) { d_printf("Unable to connect to remote registry\n"); return werror_to_ntstatus(result); } - result = cli_reg_open_entry( cli, mem_ctx, &pol_hive, subpath, MAXIMUM_ALLOWED_ACCESS, &pol_key ); + result = rpccli_reg_open_entry(pipe_hnd, mem_ctx, &pol_hive, subpath, MAXIMUM_ALLOWED_ACCESS, &pol_key ); if ( !W_ERROR_IS_OK(result) ) { d_printf("Unable to open [%s]\n", argv[0]); return werror_to_ntstatus(result); } - result = cli_reg_save_key( cli, mem_ctx, &pol_key, argv[1] ); + result = rpccli_reg_save_key(pipe_hnd, mem_ctx, &pol_key, argv[1] ); if ( !W_ERROR_IS_OK(result) ) { d_printf("Unable to save [%s] to %s:%s\n", argv[0], cli->desthost, argv[1]); } @@ -239,8 +246,8 @@ static NTSTATUS rpc_registry_save_internal( const DOM_SID *domain_sid, const cha /* cleanup */ - cli_reg_close( cli, mem_ctx, &pol_key ); - cli_reg_close( cli, mem_ctx, &pol_hive ); + rpccli_reg_close(pipe_hnd, mem_ctx, &pol_key ); + rpccli_reg_close(pipe_hnd, mem_ctx, &pol_hive ); return werror_to_ntstatus(result); } @@ -490,5 +497,3 @@ int net_rpc_registry(int argc, const char **argv) return net_help_registry( argc, argv ); } - - diff --git a/source3/utils/net_rpc_rights.c b/source3/utils/net_rpc_rights.c index 3a986ed2516..a563475ee10 100644 --- a/source3/utils/net_rpc_rights.c +++ b/source3/utils/net_rpc_rights.c @@ -23,22 +23,23 @@ /******************************************************************** ********************************************************************/ -static NTSTATUS sid_to_name(struct cli_state *cli, - TALLOC_CTX *mem_ctx, - DOM_SID *sid, fstring name) +static NTSTATUS sid_to_name(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + DOM_SID *sid, + fstring name) { POLICY_HND pol; uint32 *sid_types; NTSTATUS result; char **domains, **names; - result = cli_lsa_open_policy(cli, mem_ctx, True, + result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); if ( !NT_STATUS_IS_OK(result) ) return result; - result = cli_lsa_lookup_sids(cli, mem_ctx, &pol, 1, sid, &domains, &names, &sid_types); + result = rpccli_lsa_lookup_sids(pipe_hnd, mem_ctx, &pol, 1, sid, &domains, &names, &sid_types); if ( NT_STATUS_IS_OK(result) ) { if ( *domains[0] ) @@ -47,14 +48,14 @@ static NTSTATUS sid_to_name(struct cli_state *cli, fstrcpy( name, names[0] ); } - cli_lsa_close(cli, mem_ctx, &pol); + rpccli_lsa_close(pipe_hnd, mem_ctx, &pol); return result; } /******************************************************************** ********************************************************************/ -static NTSTATUS name_to_sid(struct cli_state *cli, +static NTSTATUS name_to_sid(struct rpc_pipe_client *pipe_hnd, TALLOC_CTX *mem_ctx, DOM_SID *sid, const char *name) { @@ -64,31 +65,31 @@ static NTSTATUS name_to_sid(struct cli_state *cli, DOM_SID *sids; /* maybe its a raw SID */ - if ( strncmp(name, "S-", 2) == 0 && string_to_sid(sid, name) ) - { + if ( strncmp(name, "S-", 2) == 0 && string_to_sid(sid, name) ) { return NT_STATUS_OK; } - result = cli_lsa_open_policy(cli, mem_ctx, True, + result = rpccli_lsa_open_policy(pipe_hnd, mem_ctx, True, SEC_RIGHTS_MAXIMUM_ALLOWED, &pol); if ( !NT_STATUS_IS_OK(result) ) return result; - result = cli_lsa_lookup_names(cli, mem_ctx, &pol, 1, &name, &sids, &sid_types); + result = rpccli_lsa_lookup_names(pipe_hnd, mem_ctx, &pol, 1, &name, &sids, &sid_types); if ( NT_STATUS_IS_OK(result) ) sid_copy( sid, &sids[0] ); - cli_lsa_close(cli, mem_ctx, &pol); + rpccli_lsa_close(pipe_hnd, mem_ctx, &pol); return result; } /******************************************************************** ********************************************************************/ -static NTSTATUS enum_privileges( TALLOC_CTX *ctx, struct cli_state *cli, - POLICY_HND *pol ) +static NTSTATUS enum_privileges(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *ctx, + POLICY_HND *pol ) { NTSTATUS result; uint32 enum_context = 0; @@ -103,7 +104,7 @@ static NTSTATUS enum_privileges( TALLOC_CTX *ctx, struct cli_state *cli, uint16 lang_id_desc; fstring description; - result = cli_lsa_enum_privilege(cli, ctx, pol, &enum_context, + result = rpccli_lsa_enum_privilege(pipe_hnd, ctx, pol, &enum_context, pref_max_length, &count, &privs_name, &privs_high, &privs_low); if ( !NT_STATUS_IS_OK(result) ) @@ -116,7 +117,7 @@ static NTSTATUS enum_privileges( TALLOC_CTX *ctx, struct cli_state *cli, /* try to get the description */ - if ( !NT_STATUS_IS_OK(cli_lsa_get_dispname(cli, ctx, pol, + if ( !NT_STATUS_IS_OK(rpccli_lsa_get_dispname(pipe_hnd, ctx, pol, privs_name[i], lang_id, lang_id_sys, description, &lang_id_desc)) ) { d_printf("??????\n"); @@ -127,21 +128,23 @@ static NTSTATUS enum_privileges( TALLOC_CTX *ctx, struct cli_state *cli, } return NT_STATUS_OK; - } /******************************************************************** ********************************************************************/ -static NTSTATUS check_privilege_for_user( TALLOC_CTX *ctx, struct cli_state *cli, - POLICY_HND *pol, DOM_SID *sid, const char *right) +static NTSTATUS check_privilege_for_user(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *ctx, + POLICY_HND *pol, + DOM_SID *sid, + const char *right) { NTSTATUS result; uint32 count; char **rights; int i; - result = cli_lsa_enum_account_rights(cli, ctx, pol, sid, &count, &rights); + result = rpccli_lsa_enum_account_rights(pipe_hnd, ctx, pol, sid, &count, &rights); if (!NT_STATUS_IS_OK(result)) { return result; @@ -163,15 +166,17 @@ static NTSTATUS check_privilege_for_user( TALLOC_CTX *ctx, struct cli_state *cli /******************************************************************** ********************************************************************/ -static NTSTATUS enum_privileges_for_user( TALLOC_CTX *ctx, struct cli_state *cli, - POLICY_HND *pol, DOM_SID *sid ) +static NTSTATUS enum_privileges_for_user(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *ctx, + POLICY_HND *pol, + DOM_SID *sid ) { NTSTATUS result; uint32 count; char **rights; int i; - result = cli_lsa_enum_account_rights(cli, ctx, pol, sid, &count, &rights); + result = rpccli_lsa_enum_account_rights(pipe_hnd, ctx, pol, sid, &count, &rights); if (!NT_STATUS_IS_OK(result)) return result; @@ -189,8 +194,10 @@ static NTSTATUS enum_privileges_for_user( TALLOC_CTX *ctx, struct cli_state *cli /******************************************************************** ********************************************************************/ -static NTSTATUS enum_accounts_for_privilege(TALLOC_CTX *ctx, struct cli_state *cli, - POLICY_HND *pol, const char *privilege) +static NTSTATUS enum_accounts_for_privilege(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *ctx, + POLICY_HND *pol, + const char *privilege) { NTSTATUS result; uint32 enum_context=0; @@ -200,7 +207,7 @@ static NTSTATUS enum_accounts_for_privilege(TALLOC_CTX *ctx, struct cli_state *c int i; fstring name; - result = cli_lsa_enum_sids(cli, ctx, pol, &enum_context, + result = rpccli_lsa_enum_sids(pipe_hnd, ctx, pol, &enum_context, pref_max_length, &count, &sids); if (!NT_STATUS_IS_OK(result)) @@ -211,7 +218,7 @@ static NTSTATUS enum_accounts_for_privilege(TALLOC_CTX *ctx, struct cli_state *c for ( i=0; i 2005 Modified by Volker Lendecke 2002 + Copyright (C) Jeremy Allison 2005. This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by @@ -41,7 +42,6 @@ static void display_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *g) d_printf("\n"); } - static const char *display_time(NTTIME *nttime) { static fstring string; @@ -210,10 +210,9 @@ static void display_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta) } } - -static void dump_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds) +static void dump_database(struct rpc_pipe_client *pipe_hnd, uint32 db_type) { - unsigned sync_context = 0; + uint32 sync_context = 0; NTSTATUS result; int i; TALLOC_CTX *mem_ctx; @@ -241,13 +240,12 @@ static void dump_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret } do { - result = cli_netlogon_sam_sync(cli, mem_ctx, ret_creds, db_type, + result = rpccli_netlogon_sam_sync(pipe_hnd, mem_ctx, db_type, sync_context, &num_deltas, &hdr_deltas, &deltas); if (NT_STATUS_IS_ERR(result)) break; - clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), ret_creds); for (i = 0; i < num_deltas; i++) { display_sam_entry(&hdr_deltas[i], &deltas[i]); } @@ -259,41 +257,47 @@ static void dump_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret /* dump sam database via samsync rpc calls */ NTSTATUS rpc_samdump_internals(const DOM_SID *domain_sid, - const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { +#if 0 + /* net_rpc.c now always tries to create an schannel pipe.. */ + NTSTATUS nt_status = NT_STATUS_UNSUCCESSFUL; uchar trust_password[16]; - DOM_CRED ret_creds; - uint32 sec_channel; - - ZERO_STRUCT(ret_creds); - - fstrcpy(cli->domain, domain_name); + uint32 neg_flags = NETLOGON_NEG_AUTH2_FLAGS; + uint32 sec_channel_type = 0; if (!secrets_fetch_trust_account_password(domain_name, trust_password, - NULL, &sec_channel)) { + NULL, &sec_channel_type)) { DEBUG(0,("Could not fetch trust account password\n")); goto fail; } - if (!NT_STATUS_IS_OK(nt_status = cli_nt_establish_netlogon(cli, sec_channel, - trust_password))) { + nt_status = rpccli_netlogon_setup_creds(pipe_hnd, + cli->desthost, + domain_name, + global_myname(), + trust_password, + sec_channel_type, + &neg_flags); + + if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(0,("Error connecting to NETLOGON pipe\n")); goto fail; } +#endif - dump_database(cli, SAM_DATABASE_DOMAIN, &ret_creds); - dump_database(cli, SAM_DATABASE_BUILTIN, &ret_creds); - dump_database(cli, SAM_DATABASE_PRIVS, &ret_creds); - - nt_status = NT_STATUS_OK; + dump_database(pipe_hnd, SAM_DATABASE_DOMAIN); + dump_database(pipe_hnd, SAM_DATABASE_BUILTIN); + dump_database(pipe_hnd, SAM_DATABASE_PRIVS); -fail: - cli_nt_session_close(cli); - return nt_status; + return NT_STATUS_OK; } /* Convert a SAM_ACCOUNT_DELTA to a SAM_ACCOUNT. */ @@ -301,8 +305,7 @@ fail: (!old_string && new_string) ||\ (old_string && new_string && (strcmp(old_string, new_string) != 0)) -static NTSTATUS -sam_account_from_delta(SAM_ACCOUNT *account, SAM_ACCOUNT_INFO *delta) +static NTSTATUS sam_account_from_delta(SAM_ACCOUNT *account, SAM_ACCOUNT_INFO *delta) { const char *old_string, *new_string; time_t unix_time, stored_time; @@ -529,7 +532,7 @@ static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta) add_ret = smbrun(add_script,NULL); DEBUG(add_ret ? 0 : 1,("fetch_account: Running the command `%s' " "gave %d\n", add_script, add_ret)); - } + } /* try and find the possible unix account again */ if ( !(passwd = Get_Pwnam(account)) ) { @@ -590,8 +593,7 @@ static NTSTATUS fetch_account_info(uint32 rid, SAM_ACCOUNT_INFO *delta) return nt_ret; } -static NTSTATUS -fetch_group_info(uint32 rid, SAM_GROUP_INFO *delta) +static NTSTATUS fetch_group_info(uint32 rid, SAM_GROUP_INFO *delta) { fstring name; fstring comment; @@ -651,8 +653,7 @@ fetch_group_info(uint32 rid, SAM_GROUP_INFO *delta) return NT_STATUS_OK; } -static NTSTATUS -fetch_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *delta) +static NTSTATUS fetch_group_mem_info(uint32 rid, SAM_GROUP_MEM_INFO *delta) { int i; TALLOC_CTX *t = NULL; @@ -832,8 +833,7 @@ static NTSTATUS fetch_alias_info(uint32 rid, SAM_ALIAS_INFO *delta, return NT_STATUS_OK; } -static NTSTATUS -fetch_alias_mem(uint32 rid, SAM_ALIAS_MEM_INFO *delta, DOM_SID dom_sid) +static NTSTATUS fetch_alias_mem(uint32 rid, SAM_ALIAS_MEM_INFO *delta, DOM_SID dom_sid) { #if 0 /* * commented out right now after talking to Volker. Can't @@ -998,42 +998,41 @@ static NTSTATUS fetch_domain_info(uint32 rid, SAM_DOMAIN_INFO *delta) } - if (!account_policy_set(AP_PASSWORD_HISTORY, delta->pwd_history_len)) + if (!pdb_set_account_policy(AP_PASSWORD_HISTORY, delta->pwd_history_len)) return nt_status; - if (!account_policy_set(AP_MIN_PASSWORD_LEN, delta->min_pwd_len)) + if (!pdb_set_account_policy(AP_MIN_PASSWORD_LEN, delta->min_pwd_len)) return nt_status; - if (!account_policy_set(AP_MAX_PASSWORD_AGE, (uint32)u_max_age)) + if (!pdb_set_account_policy(AP_MAX_PASSWORD_AGE, (uint32)u_max_age)) return nt_status; - if (!account_policy_set(AP_MIN_PASSWORD_AGE, (uint32)u_min_age)) + if (!pdb_set_account_policy(AP_MIN_PASSWORD_AGE, (uint32)u_min_age)) return nt_status; - if (!account_policy_set(AP_TIME_TO_LOGOUT, (uint32)u_logout)) + if (!pdb_set_account_policy(AP_TIME_TO_LOGOUT, (uint32)u_logout)) return nt_status; - if (!account_policy_set(AP_BAD_ATTEMPT_LOCKOUT, delta->account_lockout.bad_attempt_lockout)) + if (!pdb_set_account_policy(AP_BAD_ATTEMPT_LOCKOUT, delta->account_lockout.bad_attempt_lockout)) return nt_status; - if (!account_policy_set(AP_RESET_COUNT_TIME, (uint32)u_lockoutreset/60)) + if (!pdb_set_account_policy(AP_RESET_COUNT_TIME, (uint32)u_lockoutreset/60)) return nt_status; if (u_lockouttime != -1) u_lockouttime /= 60; - if (!account_policy_set(AP_LOCK_ACCOUNT_DURATION, (uint32)u_lockouttime)) + if (!pdb_set_account_policy(AP_LOCK_ACCOUNT_DURATION, (uint32)u_lockouttime)) return nt_status; - if (!account_policy_set(AP_USER_MUST_LOGON_TO_CHG_PASS, delta->logon_chgpass)) + if (!pdb_set_account_policy(AP_USER_MUST_LOGON_TO_CHG_PASS, delta->logon_chgpass)) return nt_status; return NT_STATUS_OK; } -static void -fetch_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta, +static void fetch_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta, DOM_SID dom_sid) { switch(hdr_delta->type) { @@ -1098,11 +1097,9 @@ fetch_sam_entry(SAM_DELTA_HDR *hdr_delta, SAM_DELTA_CTR *delta, } } -static NTSTATUS -fetch_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds, - DOM_SID dom_sid) +static NTSTATUS fetch_database(struct rpc_pipe_client *pipe_hnd, uint32 db_type, DOM_SID dom_sid) { - unsigned sync_context = 0; + uint32 sync_context = 0; NTSTATUS result; int i; TALLOC_CTX *mem_ctx; @@ -1129,17 +1126,13 @@ fetch_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds, } do { - result = cli_netlogon_sam_sync(cli, mem_ctx, ret_creds, + result = rpccli_netlogon_sam_sync(pipe_hnd, mem_ctx, db_type, sync_context, &num_deltas, &hdr_deltas, &deltas); if (NT_STATUS_IS_OK(result) || NT_STATUS_EQUAL(result, STATUS_MORE_ENTRIES)) { - - clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), - ret_creds); - for (i = 0; i < num_deltas; i++) { fetch_sam_entry(&hdr_deltas[i], &deltas[i], dom_sid); } @@ -1154,8 +1147,7 @@ fetch_database(struct cli_state *cli, unsigned db_type, DOM_CRED *ret_creds, return result; } -static NTSTATUS -populate_ldap_for_ldif(fstring sid, const char *suffix, const char +static NTSTATUS populate_ldap_for_ldif(fstring sid, const char *suffix, const char *builtin_sid, FILE *add_fd) { char *user_suffix, *group_suffix, *machine_suffix, *idmap_suffix; @@ -1448,8 +1440,7 @@ populate_ldap_for_ldif(fstring sid, const char *suffix, const char return NT_STATUS_OK; } -static NTSTATUS -map_populate_groups(GROUPMAP *groupmap, ACCOUNTMAP *accountmap, fstring sid, +static NTSTATUS map_populate_groups(GROUPMAP *groupmap, ACCOUNTMAP *accountmap, fstring sid, const char *suffix, const char *builtin_sid) { char *group_attr = sstring_sub(lp_ldap_group_suffix(), '=', ','); @@ -1521,8 +1512,7 @@ map_populate_groups(GROUPMAP *groupmap, ACCOUNTMAP *accountmap, fstring sid, return NT_STATUS_OK; } -static NTSTATUS -fetch_group_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap, +static NTSTATUS fetch_group_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap, FILE *add_fd, fstring sid, char *suffix) { fstring groupname; @@ -1579,8 +1569,7 @@ fetch_group_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap, return NT_STATUS_OK; } -static NTSTATUS -fetch_account_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap, +static NTSTATUS fetch_account_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap, ACCOUNTMAP *accountmap, FILE *add_fd, fstring sid, char *suffix, int alloced) { @@ -1724,8 +1713,7 @@ fetch_account_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap, return NT_STATUS_OK; } -static NTSTATUS -fetch_alias_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap, +static NTSTATUS fetch_alias_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap, FILE *add_fd, fstring sid, char *suffix, unsigned db_type) { @@ -1798,8 +1786,7 @@ fetch_alias_info_to_ldif(SAM_DELTA_CTR *delta, GROUPMAP *groupmap, return NT_STATUS_OK; } -static NTSTATUS -fetch_groupmem_info_to_ldif(SAM_DELTA_CTR *delta, SAM_DELTA_HDR *hdr_delta, +static NTSTATUS fetch_groupmem_info_to_ldif(SAM_DELTA_CTR *delta, SAM_DELTA_HDR *hdr_delta, GROUPMAP *groupmap, ACCOUNTMAP *accountmap, FILE *mod_fd, int alloced) { @@ -1841,16 +1828,16 @@ fetch_groupmem_info_to_ldif(SAM_DELTA_CTR *delta, SAM_DELTA_HDR *hdr_delta, return NT_STATUS_OK; } -static NTSTATUS -fetch_database_to_ldif(struct cli_state *cli, unsigned db_type, - DOM_CRED *ret_creds, DOM_SID dom_sid, - const char *user_file) +static NTSTATUS fetch_database_to_ldif(struct rpc_pipe_client *pipe_hnd, + uint32 db_type, + DOM_SID dom_sid, + const char *user_file) { char *suffix; const char *builtin_sid = "S-1-5-32"; char *ldif_file; fstring sid, domainname; - unsigned sync_context = 0; + uint32 sync_context = 0; NTSTATUS result; int k; TALLOC_CTX *mem_ctx; @@ -1956,7 +1943,7 @@ fetch_database_to_ldif(struct cli_state *cli, unsigned db_type, } do { - result = cli_netlogon_sam_sync(cli, mem_ctx, ret_creds, + result = rpccli_netlogon_sam_sync(pipe_hnd, mem_ctx, db_type, sync_context, &num_deltas, &hdr_deltas, &deltas); @@ -1965,9 +1952,6 @@ fetch_database_to_ldif(struct cli_state *cli, unsigned db_type, return NT_STATUS_OK; } - clnt_deal_with_creds(cli->sess_key, &(cli->clnt_cred), - ret_creds); - /* Re-allocate memory for groupmap and accountmap arrays */ groupmap = SMB_REALLOC_ARRAY(groupmap, GROUPMAP, num_deltas+num_alloced); @@ -2138,18 +2122,16 @@ int rpc_vampire_usage(int argc, const char **argv) /* dump sam database via samsync rpc calls */ NTSTATUS rpc_vampire_internals(const DOM_SID *domain_sid, - const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv) + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv) { NTSTATUS result; - uchar trust_password[16]; - DOM_CRED ret_creds; fstring my_dom_sid_str; fstring rem_dom_sid_str; - uint32 sec_channel; - - ZERO_STRUCT(ret_creds); if (!sid_equal(domain_sid, get_global_sam_sid())) { d_printf("Cannot import users from %s at this time, " @@ -2164,29 +2146,11 @@ NTSTATUS rpc_vampire_internals(const DOM_SID *domain_sid, return NT_STATUS_UNSUCCESSFUL; } - fstrcpy(cli->domain, domain_name); - - if (!secrets_fetch_trust_account_password(domain_name, - trust_password, NULL, - &sec_channel)) { - result = NT_STATUS_CANT_ACCESS_DOMAIN_INFO; - d_printf("Could not retrieve domain trust secret\n"); - goto fail; - } - - result = cli_nt_establish_netlogon(cli, sec_channel, trust_password); - - if (!NT_STATUS_IS_OK(result)) { - d_printf("Failed to setup BDC creds\n"); - goto fail; - } - if (argc >= 1 && (strcmp(argv[0], "ldif") == 0)) { - result = fetch_database_to_ldif(cli, SAM_DATABASE_DOMAIN, - &ret_creds, *domain_sid, argv[1]); + result = fetch_database_to_ldif(pipe_hnd, SAM_DATABASE_DOMAIN, + *domain_sid, argv[1]); } else { - result = fetch_database(cli, SAM_DATABASE_DOMAIN, &ret_creds, - *domain_sid); + result = fetch_database(pipe_hnd, SAM_DATABASE_DOMAIN, *domain_sid); } if (!NT_STATUS_IS_OK(result)) { @@ -2199,12 +2163,10 @@ NTSTATUS rpc_vampire_internals(const DOM_SID *domain_sid, } if (argc >= 1 && (strcmp(argv[0], "ldif") == 0)) { - result = fetch_database_to_ldif(cli, SAM_DATABASE_BUILTIN, - &ret_creds, global_sid_Builtin, - argv[1]); + result = fetch_database_to_ldif(pipe_hnd, SAM_DATABASE_BUILTIN, + global_sid_Builtin, argv[1]); } else { - result = fetch_database(cli, SAM_DATABASE_BUILTIN, &ret_creds, - global_sid_Builtin); + result = fetch_database(pipe_hnd, SAM_DATABASE_BUILTIN, global_sid_Builtin); } if (!NT_STATUS_IS_OK(result)) { @@ -2219,4 +2181,3 @@ NTSTATUS rpc_vampire_internals(const DOM_SID *domain_sid, fail: return result; } - diff --git a/source3/utils/net_rpc_service.c b/source3/utils/net_rpc_service.c index 8f93ab3d060..3cc4790884c 100644 --- a/source3/utils/net_rpc_service.c +++ b/source3/utils/net_rpc_service.c @@ -24,8 +24,11 @@ /******************************************************************** ********************************************************************/ -static WERROR query_service_state( struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *hSCM, const char *service, uint32 *state ) +static WERROR query_service_state(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + POLICY_HND *hSCM, + const char *service, + uint32 *state ) { POLICY_HND hService; SERVICE_STATUS service_status; @@ -33,7 +36,7 @@ static WERROR query_service_state( struct cli_state *cli, TALLOC_CTX *mem_ctx, /* now cycle until the status is actually 'watch_state' */ - result = cli_svcctl_open_service( cli, mem_ctx, hSCM, &hService, + result = rpccli_svcctl_open_service(pipe_hnd, mem_ctx, hSCM, &hService, service, SC_RIGHT_SVC_QUERY_STATUS ); if ( !W_ERROR_IS_OK(result) ) { @@ -41,12 +44,12 @@ static WERROR query_service_state( struct cli_state *cli, TALLOC_CTX *mem_ctx, return result; } - result = cli_svcctl_query_status( cli, mem_ctx, &hService, &service_status ); + result = rpccli_svcctl_query_status(pipe_hnd, mem_ctx, &hService, &service_status ); if ( W_ERROR_IS_OK(result) ) { *state = service_status.state; } - cli_svcctl_close_service( cli, mem_ctx, &hService ); + rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hService ); return result; } @@ -54,9 +57,12 @@ static WERROR query_service_state( struct cli_state *cli, TALLOC_CTX *mem_ctx, /******************************************************************** ********************************************************************/ -static WERROR watch_service_state( struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *hSCM, const char *service, - uint32 watch_state, uint32 *final_state ) +static WERROR watch_service_state(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + POLICY_HND *hSCM, + const char *service, + uint32 watch_state, + uint32 *final_state ) { uint32 i; uint32 state = 0; @@ -67,7 +73,7 @@ static WERROR watch_service_state( struct cli_state *cli, TALLOC_CTX *mem_ctx, while ( (state != watch_state ) && i<30 ) { /* get the status */ - result = query_service_state( cli, mem_ctx, hSCM, service, &state ); + result = query_service_state(pipe_hnd, mem_ctx, hSCM, service, &state ); if ( !W_ERROR_IS_OK(result) ) { break; } @@ -86,9 +92,12 @@ static WERROR watch_service_state( struct cli_state *cli, TALLOC_CTX *mem_ctx, /******************************************************************** ********************************************************************/ -static WERROR control_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, - POLICY_HND *hSCM, const char *service, - uint32 control, uint32 watch_state ) +static WERROR control_service(struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + POLICY_HND *hSCM, + const char *service, + uint32 control, + uint32 watch_state ) { POLICY_HND hService; WERROR result = WERR_GENERAL_FAILURE; @@ -97,7 +106,7 @@ static WERROR control_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, /* Open the Service */ - result = cli_svcctl_open_service( cli, mem_ctx, hSCM, &hService, + result = rpccli_svcctl_open_service(pipe_hnd, mem_ctx, hSCM, &hService, service, (SC_RIGHT_SVC_STOP|SC_RIGHT_SVC_PAUSE_CONTINUE) ); if ( !W_ERROR_IS_OK(result) ) { @@ -107,7 +116,7 @@ static WERROR control_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, /* get the status */ - result = cli_svcctl_control_service( cli, mem_ctx, &hService, + result = rpccli_svcctl_control_service(pipe_hnd, mem_ctx, &hService, control, &service_status ); if ( !W_ERROR_IS_OK(result) ) { @@ -117,12 +126,12 @@ static WERROR control_service( struct cli_state *cli, TALLOC_CTX *mem_ctx, /* loop -- checking the state until we are where we want to be */ - result = watch_service_state( cli, mem_ctx, hSCM, service, watch_state, &state ); + result = watch_service_state(pipe_hnd, mem_ctx, hSCM, service, watch_state, &state ); d_printf("%s service is %s.\n", service, svc_status_string(state)); done: - cli_svcctl_close_service( cli, mem_ctx, &hService ); + rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hService ); return result; } @@ -130,9 +139,13 @@ done: /******************************************************************** ********************************************************************/ -static NTSTATUS rpc_service_list_internal( const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv ) +static NTSTATUS rpc_service_list_internal(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv ) { POLICY_HND hSCM; ENUM_SERVICES_STATUS *services; @@ -147,13 +160,13 @@ static NTSTATUS rpc_service_list_internal( const DOM_SID *domain_sid, const char return NT_STATUS_OK; } - result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); + result = rpccli_svcctl_open_scm(pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); if ( !W_ERROR_IS_OK(result) ) { d_printf("Failed to open Service Control Manager. [%s]\n", dos_errstr(result)); return werror_to_ntstatus(result); } - result = cli_svcctl_enumerate_services( cli, mem_ctx, &hSCM, SVCCTL_TYPE_WIN32, + result = rpccli_svcctl_enumerate_services(pipe_hnd, mem_ctx, &hSCM, SVCCTL_TYPE_WIN32, SVCCTL_STATE_ALL, &num_services, &services ); if ( !W_ERROR_IS_OK(result) ) { @@ -172,7 +185,7 @@ static NTSTATUS rpc_service_list_internal( const DOM_SID *domain_sid, const char } done: - cli_svcctl_close_service( cli, mem_ctx, &hSCM ); + rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hSCM ); return werror_to_ntstatus(result); } @@ -180,9 +193,13 @@ done: /******************************************************************** ********************************************************************/ -static NTSTATUS rpc_service_status_internal( const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv ) +static NTSTATUS rpc_service_status_internal(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv ) { POLICY_HND hSCM, hService; WERROR result = WERR_GENERAL_FAILURE; @@ -200,7 +217,7 @@ static NTSTATUS rpc_service_status_internal( const DOM_SID *domain_sid, const ch /* Open the Service Control Manager */ - result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); + result = rpccli_svcctl_open_scm(pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); if ( !W_ERROR_IS_OK(result) ) { d_printf("Failed to open Service Control Manager. [%s]\n", dos_errstr(result)); return werror_to_ntstatus(result); @@ -208,7 +225,7 @@ static NTSTATUS rpc_service_status_internal( const DOM_SID *domain_sid, const ch /* Open the Service */ - result = cli_svcctl_open_service( cli, mem_ctx, &hSCM, &hService, servicename, + result = rpccli_svcctl_open_service(pipe_hnd, mem_ctx, &hSCM, &hService, servicename, (SC_RIGHT_SVC_QUERY_STATUS|SC_RIGHT_SVC_QUERY_CONFIG) ); if ( !W_ERROR_IS_OK(result) ) { @@ -218,7 +235,7 @@ static NTSTATUS rpc_service_status_internal( const DOM_SID *domain_sid, const ch /* get the status */ - result = cli_svcctl_query_status( cli, mem_ctx, &hService, &service_status ); + result = rpccli_svcctl_query_status(pipe_hnd, mem_ctx, &hService, &service_status ); if ( !W_ERROR_IS_OK(result) ) { d_printf("Query status request failed. [%s]\n", dos_errstr(result)); goto done; @@ -228,7 +245,7 @@ static NTSTATUS rpc_service_status_internal( const DOM_SID *domain_sid, const ch /* get the config */ - result = cli_svcctl_query_config( cli, mem_ctx, &hService, &config ); + result = rpccli_svcctl_query_config(pipe_hnd, mem_ctx, &hService, &config ); if ( !W_ERROR_IS_OK(result) ) { d_printf("Query config request failed. [%s]\n", dos_errstr(result)); goto done; @@ -268,19 +285,22 @@ static NTSTATUS rpc_service_status_internal( const DOM_SID *domain_sid, const ch } done: - cli_svcctl_close_service( cli, mem_ctx, &hService ); - cli_svcctl_close_service( cli, mem_ctx, &hSCM ); - + rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hService ); + rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hSCM ); + return werror_to_ntstatus(result); } - /******************************************************************** ********************************************************************/ -static NTSTATUS rpc_service_stop_internal( const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv ) +static NTSTATUS rpc_service_stop_internal(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv ) { POLICY_HND hSCM; WERROR result = WERR_GENERAL_FAILURE; @@ -295,16 +315,16 @@ static NTSTATUS rpc_service_stop_internal( const DOM_SID *domain_sid, const char /* Open the Service Control Manager */ - result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); + result = rpccli_svcctl_open_scm(pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); if ( !W_ERROR_IS_OK(result) ) { d_printf("Failed to open Service Control Manager. [%s]\n", dos_errstr(result)); return werror_to_ntstatus(result); } - result = control_service( cli, mem_ctx, &hSCM, servicename, + result = control_service(pipe_hnd, mem_ctx, &hSCM, servicename, SVCCTL_CONTROL_STOP, SVCCTL_STOPPED ); - cli_svcctl_close_service( cli, mem_ctx, &hSCM ); + rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hSCM ); return werror_to_ntstatus(result); } @@ -312,9 +332,13 @@ static NTSTATUS rpc_service_stop_internal( const DOM_SID *domain_sid, const char /******************************************************************** ********************************************************************/ -static NTSTATUS rpc_service_pause_internal( const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv ) +static NTSTATUS rpc_service_pause_internal(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv ) { POLICY_HND hSCM; WERROR result = WERR_GENERAL_FAILURE; @@ -329,16 +353,16 @@ static NTSTATUS rpc_service_pause_internal( const DOM_SID *domain_sid, const cha /* Open the Service Control Manager */ - result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); + result = rpccli_svcctl_open_scm(pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); if ( !W_ERROR_IS_OK(result) ) { d_printf("Failed to open Service Control Manager. [%s]\n", dos_errstr(result)); return werror_to_ntstatus(result); } - result = control_service( cli, mem_ctx, &hSCM, servicename, + result = control_service(pipe_hnd, mem_ctx, &hSCM, servicename, SVCCTL_CONTROL_PAUSE, SVCCTL_PAUSED ); - cli_svcctl_close_service( cli, mem_ctx, &hSCM ); + rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hSCM ); return werror_to_ntstatus(result); } @@ -346,9 +370,13 @@ static NTSTATUS rpc_service_pause_internal( const DOM_SID *domain_sid, const cha /******************************************************************** ********************************************************************/ -static NTSTATUS rpc_service_resume_internal( const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv ) +static NTSTATUS rpc_service_resume_internal(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv ) { POLICY_HND hSCM; WERROR result = WERR_GENERAL_FAILURE; @@ -363,16 +391,16 @@ static NTSTATUS rpc_service_resume_internal( const DOM_SID *domain_sid, const ch /* Open the Service Control Manager */ - result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); + result = rpccli_svcctl_open_scm(pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); if ( !W_ERROR_IS_OK(result) ) { d_printf("Failed to open Service Control Manager. [%s]\n", dos_errstr(result)); return werror_to_ntstatus(result); } - result = control_service( cli, mem_ctx, &hSCM, servicename, + result = control_service(pipe_hnd, mem_ctx, &hSCM, servicename, SVCCTL_CONTROL_CONTINUE, SVCCTL_RUNNING ); - cli_svcctl_close_service( cli, mem_ctx, &hSCM ); + rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hSCM ); return werror_to_ntstatus(result); } @@ -380,9 +408,13 @@ static NTSTATUS rpc_service_resume_internal( const DOM_SID *domain_sid, const ch /******************************************************************** ********************************************************************/ -static NTSTATUS rpc_service_start_internal( const DOM_SID *domain_sid, const char *domain_name, - struct cli_state *cli, TALLOC_CTX *mem_ctx, - int argc, const char **argv ) +static NTSTATUS rpc_service_start_internal(const DOM_SID *domain_sid, + const char *domain_name, + struct cli_state *cli, + struct rpc_pipe_client *pipe_hnd, + TALLOC_CTX *mem_ctx, + int argc, + const char **argv ) { POLICY_HND hSCM, hService; WERROR result = WERR_GENERAL_FAILURE; @@ -398,7 +430,7 @@ static NTSTATUS rpc_service_start_internal( const DOM_SID *domain_sid, const cha /* Open the Service Control Manager */ - result = cli_svcctl_open_scm( cli, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); + result = rpccli_svcctl_open_scm( pipe_hnd, mem_ctx, &hSCM, SC_RIGHT_MGR_ENUMERATE_SERVICE ); if ( !W_ERROR_IS_OK(result) ) { d_printf("Failed to open Service Control Manager. [%s]\n", dos_errstr(result)); return werror_to_ntstatus(result); @@ -406,7 +438,7 @@ static NTSTATUS rpc_service_start_internal( const DOM_SID *domain_sid, const cha /* Open the Service */ - result = cli_svcctl_open_service( cli, mem_ctx, &hSCM, &hService, + result = rpccli_svcctl_open_service(pipe_hnd, mem_ctx, &hSCM, &hService, servicename, SC_RIGHT_SVC_START ); if ( !W_ERROR_IS_OK(result) ) { @@ -416,13 +448,13 @@ static NTSTATUS rpc_service_start_internal( const DOM_SID *domain_sid, const cha /* get the status */ - result = cli_svcctl_start_service( cli, mem_ctx, &hService, NULL, 0 ); + result = rpccli_svcctl_start_service(pipe_hnd, mem_ctx, &hService, NULL, 0 ); if ( !W_ERROR_IS_OK(result) ) { d_printf("Query status request failed. [%s]\n", dos_errstr(result)); goto done; } - result = watch_service_state( cli, mem_ctx, &hSCM, servicename, SVCCTL_RUNNING, &state ); + result = watch_service_state(pipe_hnd, mem_ctx, &hSCM, servicename, SVCCTL_RUNNING, &state ); if ( W_ERROR_IS_OK(result) && (state == SVCCTL_RUNNING) ) d_printf("Successfully started service: %s\n", servicename ); @@ -430,9 +462,9 @@ static NTSTATUS rpc_service_start_internal( const DOM_SID *domain_sid, const cha d_printf("Failed to start service: %s [%s]\n", servicename, dos_errstr(result) ); done: - cli_svcctl_close_service( cli, mem_ctx, &hService ); - cli_svcctl_close_service( cli, mem_ctx, &hSCM ); - + rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hService ); + rpccli_svcctl_close_service(pipe_hnd, mem_ctx, &hSCM ); + return werror_to_ntstatus(result); } @@ -525,5 +557,3 @@ int net_rpc_service(int argc, const char **argv) return net_help_service( argc, argv ); } - - diff --git a/source3/utils/net_status.c b/source3/utils/net_status.c index d5845972730..960379b3838 100644 --- a/source3/utils/net_status.c +++ b/source3/utils/net_status.c @@ -31,7 +31,7 @@ static int show_session(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, memcpy(&sessionid, dbuf.dptr, sizeof(sessionid)); - if (!process_exists(sessionid.pid)) { + if (!process_exists_by_pid(sessionid.pid)) { return 0; } @@ -101,8 +101,8 @@ static int show_share(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, return 0; } - d_printf("%-10.10s %5d %-12s %s", - crec.name,(int)crec.pid, + d_printf("%-10.10s %s %-12s %s", + crec.name,procid_str_static(&crec.pid), crec.machine, asctime(LocalTime(&crec.start))); @@ -125,7 +125,7 @@ static int collect_pid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, memcpy(&sessionid, dbuf.dptr, sizeof(sessionid)); - if (!process_exists(sessionid.pid)) + if (!process_exists_by_pid(sessionid.pid)) return 0; ids->num_entries += 1; @@ -156,14 +156,15 @@ static int show_share_parseable(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, } for (i=0; inum_entries; i++) { - if (ids->entries[i].pid == crec.pid) { + struct process_id id = pid_to_procid(ids->entries[i].pid); + if (procid_equal(&id, &crec.pid)) { guest = False; break; } } - d_printf("%s\\%d\\%s\\%s\\%s\\%s\\%s", - crec.name,(int)crec.pid, + d_printf("%s\\%s\\%s\\%s\\%s\\%s\\%s", + crec.name,procid_str_static(&crec.pid), guest ? "" : uidtoname(ids->entries[i].uid), guest ? "" : gidtoname(ids->entries[i].gid), crec.machine, diff --git a/source3/utils/ntlm_auth.c b/source3/utils/ntlm_auth.c index 3fdd657a2da..4f3bb4d4146 100644 --- a/source3/utils/ntlm_auth.c +++ b/source3/utils/ntlm_auth.c @@ -465,6 +465,7 @@ static NTSTATUS ntlm_auth_start_ntlmssp_client(NTLMSSP_STATE **client_ntlmssp_st { NTSTATUS status; if ( (opt_username == NULL) || (opt_domain == NULL) ) { + status = NT_STATUS_UNSUCCESSFUL; DEBUG(1, ("Need username and domain for NTLMSSP\n")); return NT_STATUS_INVALID_PARAMETER; } @@ -693,7 +694,8 @@ static void manage_client_ntlmssp_request(enum stdio_helper_mode stdio_helper_mo data_blob_free(&reply); DEBUG(10, ("NTLMSSP challenge\n")); } else if (NT_STATUS_IS_OK(nt_status)) { - x_fprintf(x_stdout, "AF\n"); + char *reply_base64 = base64_encode_data_blob(reply); + x_fprintf(x_stdout, "AF %s\n", reply_base64); DEBUG(10, ("NTLMSSP OK!\n")); if (ntlmssp_state) ntlmssp_end(&ntlmssp_state); @@ -753,7 +755,7 @@ static void offer_gss_spnego_mechs(void) { /* Server negTokenInit (mech offerings) */ spnego.type = SPNEGO_NEG_TOKEN_INIT; - spnego.negTokenInit.mechTypes = SMB_XMALLOC_ARRAY(const char *, 3); + spnego.negTokenInit.mechTypes = SMB_XMALLOC_ARRAY(char *, 2); #ifdef HAVE_KRB5 spnego.negTokenInit.mechTypes[0] = smb_xstrdup(OID_KERBEROS5_OLD); spnego.negTokenInit.mechTypes[1] = smb_xstrdup(OID_NTLMSSP); @@ -793,6 +795,7 @@ static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode, DATA_BLOB token; NTSTATUS status; ssize_t len; + TALLOC_CTX *mem_ctx = talloc_init("manage_gss_spnego_request"); char *user = NULL; char *domain = NULL; @@ -857,6 +860,7 @@ static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode, return; } + status = NT_STATUS_UNSUCCESSFUL; if (strcmp(request.negTokenInit.mechTypes[0], OID_NTLMSSP) == 0) { if ( request.negTokenInit.mechToken.data == NULL ) { @@ -895,7 +899,6 @@ static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode, if (strcmp(request.negTokenInit.mechTypes[0], OID_KERBEROS5_OLD) == 0) { char *principal; - DATA_BLOB auth_data; DATA_BLOB ap_rep; DATA_BLOB session_key; @@ -910,11 +913,13 @@ static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode, response.negTokenTarg.mechListMIC = data_blob(NULL, 0); response.negTokenTarg.responseToken = data_blob(NULL, 0); - status = ads_verify_ticket(lp_realm(), + status = ads_verify_ticket(mem_ctx, lp_realm(), &request.negTokenInit.mechToken, - &principal, &auth_data, &ap_rep, + &principal, NULL, &ap_rep, &session_key); + talloc_destroy(mem_ctx); + /* Now in "principal" we have the name we are authenticated as. */ @@ -934,7 +939,6 @@ static void manage_gss_spnego_request(enum stdio_helper_mode stdio_helper_mode, user = SMB_STRDUP(principal); data_blob_free(&ap_rep); - data_blob_free(&auth_data); SAFE_FREE(principal); } @@ -1052,15 +1056,16 @@ static BOOL manage_client_ntlmssp_init(SPNEGO_DATA spnego) } spnego.type = SPNEGO_NEG_TOKEN_INIT; - spnego.negTokenInit.mechTypes = my_mechs; + spnego.negTokenInit.mechTypes = CONST_DISCARD(char **,my_mechs); spnego.negTokenInit.reqFlags = 0; spnego.negTokenInit.mechListMIC = null_blob; status = ntlmssp_update(client_ntlmssp_state, null_blob, &spnego.negTokenInit.mechToken); - if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) { - DEBUG(1, ("Expected MORE_PROCESSING_REQUIRED, got: %s\n", + if ( !(NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) || + NT_STATUS_IS_OK(status)) ) { + DEBUG(1, ("Expected OK or MORE_PROCESSING_REQUIRED, got: %s\n", nt_errstr(status))); ntlmssp_end(&client_ntlmssp_state); return False; @@ -1121,7 +1126,7 @@ static void manage_client_ntlmssp_targ(SPNEGO_DATA spnego) spnego.type = SPNEGO_NEG_TOKEN_TARG; spnego.negTokenTarg.negResult = SPNEGO_ACCEPT_INCOMPLETE; - spnego.negTokenTarg.supportedMech = OID_NTLMSSP; + spnego.negTokenTarg.supportedMech = (char *)OID_NTLMSSP; spnego.negTokenTarg.responseToken = request; spnego.negTokenTarg.mechListMIC = null_blob; @@ -1166,7 +1171,7 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego) spnego.negTokenInit.mechListMIC.length); principal[spnego.negTokenInit.mechListMIC.length] = '\0'; - retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5); + retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0); if (retval) { @@ -1189,7 +1194,7 @@ static BOOL manage_client_krb5_init(SPNEGO_DATA spnego) return False; } - retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5); + retval = cli_krb5_get_ticket(principal, 0, &tkt, &session_key_krb5, 0); if (retval) { DEBUG(10, ("Kinit suceeded, but getting a ticket failed: %s\n", error_message(retval))); @@ -1305,7 +1310,7 @@ static void manage_gss_spnego_client_request(enum stdio_helper_mode stdio_helper /* The server offers a list of mechanisms */ - const char **mechType = spnego.negTokenInit.mechTypes; + const char **mechType = (const char **)spnego.negTokenInit.mechTypes; while (*mechType != NULL) { diff --git a/source3/utils/pdbedit.c b/source3/utils/pdbedit.c index c88c0d75797..dacaa1e26f2 100644 --- a/source3/utils/pdbedit.c +++ b/source3/utils/pdbedit.c @@ -118,6 +118,27 @@ static int export_groups (struct pdb_context *in, struct pdb_context *out) { return 0; } +/********************************************************* + Add all currently available account policy from tdb to one backend + ********************************************************/ + +static int export_account_policies (struct pdb_context *in, struct pdb_context *out) +{ + int i; + + for (i=1; decode_account_policy_name(i) != NULL; i++) { + uint32 policy_value; + if (NT_STATUS_IS_ERR(in->pdb_get_account_policy(in, i, &policy_value))) { + fprintf(stderr, "Can't get account policy from tdb\n"); + return -1; + } + out->pdb_set_account_policy(out, i, policy_value); + } + + return 0; +} + + /********************************************************* Print info from sam structure **********************************************************/ @@ -652,6 +673,7 @@ int main (int argc, char **argv) static char *backend_in = NULL; static char *backend_out = NULL; static BOOL transfer_groups = False; + static BOOL transfer_account_policies = False; static BOOL force_initialised_password = False; static char *logon_script = NULL; static char *profile_path = NULL; @@ -683,8 +705,8 @@ int main (int argc, char **argv) {"drive", 'D', POPT_ARG_STRING, &home_drive, 0, "set home drive", NULL}, {"script", 'S', POPT_ARG_STRING, &logon_script, 0, "set logon script", NULL}, {"profile", 'p', POPT_ARG_STRING, &profile_path, 0, "set profile path", NULL}, - {"user-SID", 'U', POPT_ARG_STRING, &user_sid, 0, "set user SID or RID", NULL}, - {"group-SID", 'G', POPT_ARG_STRING, &group_sid, 0, "set group SID or RID", NULL}, + {"user SID", 'U', POPT_ARG_STRING, &user_sid, 0, "set user SID or RID", NULL}, + {"group SID", 'G', POPT_ARG_STRING, &group_sid, 0, "set group SID or RID", NULL}, {"create", 'a', POPT_ARG_NONE, &add_user, 0, "create user", NULL}, {"modify", 'r', POPT_ARG_NONE, &modify_user, 0, "modify user", NULL}, {"machine", 'm', POPT_ARG_NONE, &machine, 0, "account is a machine account", NULL}, @@ -693,6 +715,7 @@ int main (int argc, char **argv) {"import", 'i', POPT_ARG_STRING, &backend_in, 0, "import user accounts from this backend", NULL}, {"export", 'e', POPT_ARG_STRING, &backend_out, 0, "export user accounts to this backend", NULL}, {"group", 'g', POPT_ARG_NONE, &transfer_groups, 0, "use -i and -e for groups", NULL}, + {"policies", 'y', POPT_ARG_NONE, &transfer_account_policies, 0, "use -i and -e to move account policies between backends", NULL}, {"account-policy", 'P', POPT_ARG_STRING, &account_policy, 0,"value of an account policy (like maximum password age)",NULL}, {"value", 'C', POPT_ARG_LONG, &account_policy_value, 'C',"set the account policy to this value", NULL}, {"account-control", 'c', POPT_ARG_STRING, &account_control, 0, "Values of account control", NULL}, @@ -792,20 +815,22 @@ int main (int argc, char **argv) SAFE_FREE(apn); exit(1); } - if (!account_policy_get(field, &value)) { + if (!pdb_get_account_policy(field, &value)) { fprintf(stderr, "valid account policy, but unable to fetch value!\n"); - exit(1); + if (!account_policy_value_set) + exit(1); } + printf("account policy \"%s\" description: %s\n", account_policy, account_policy_get_desc(field)); if (account_policy_value_set) { - printf("account policy value for %s was %u\n", account_policy, value); - if (!account_policy_set(field, account_policy_value)) { + printf("account policy \"%s\" value was: %u\n", account_policy, value); + if (!pdb_set_account_policy(field, account_policy_value)) { fprintf(stderr, "valid account policy, but unable to set value!\n"); exit(1); } - printf("account policy value for %s is now %lu\n", account_policy, account_policy_value); + printf("account policy \"%s\" value is now: %lu\n", account_policy, account_policy_value); exit(0); } else { - printf("account policy value for %s is %u\n", account_policy, value); + printf("account policy \"%s\" value is: %u\n", account_policy, value); exit(0); } } @@ -829,7 +854,10 @@ int main (int argc, char **argv) } else { bout = bdef; } - if (transfer_groups) { + if (transfer_account_policies) { + if (!(checkparms & BIT_USER)) + return export_account_policies(bin, bout); + } else if (transfer_groups) { if (!(checkparms & BIT_USER)) return export_groups(bin, bout); } else { diff --git a/source3/utils/smbcacls.c b/source3/utils/smbcacls.c index 00000b5cfbe..36efcc247d5 100644 --- a/source3/utils/smbcacls.c +++ b/source3/utils/smbcacls.c @@ -64,6 +64,7 @@ static const struct perm_value standard_values[] = { }; static struct cli_state *global_hack_cli; +static struct rpc_pipe_client *global_pipe_hnd; static POLICY_HND pol; static BOOL got_policy_hnd; @@ -76,8 +77,10 @@ static BOOL cacls_open_policy_hnd(void) /* Initialise cli LSA connection */ if (!global_hack_cli) { + NTSTATUS ret; global_hack_cli = connect_one("IPC$"); - if (!cli_nt_session_open (global_hack_cli, PI_LSARPC)) { + global_pipe_hnd = cli_rpc_pipe_open_noauth(global_hack_cli, PI_LSARPC, &ret); + if (!global_pipe_hnd) { return False; } } @@ -89,7 +92,7 @@ static BOOL cacls_open_policy_hnd(void) /* Some systems don't support SEC_RIGHTS_MAXIMUM_ALLOWED, but NT sends 0x2000000 so we might as well do it too. */ - if (!NT_STATUS_IS_OK(cli_lsa_open_policy(global_hack_cli, global_hack_cli->mem_ctx, True, + if (!NT_STATUS_IS_OK(rpccli_lsa_open_policy(global_pipe_hnd, global_hack_cli->mem_ctx, True, GENERIC_EXECUTE_ACCESS, &pol))) { return False; } @@ -114,7 +117,7 @@ static void SidToString(fstring str, DOM_SID *sid) /* Ask LSA to convert the sid to a name */ if (!cacls_open_policy_hnd() || - !NT_STATUS_IS_OK(cli_lsa_lookup_sids(global_hack_cli, global_hack_cli->mem_ctx, + !NT_STATUS_IS_OK(rpccli_lsa_lookup_sids(global_pipe_hnd, global_hack_cli->mem_ctx, &pol, 1, sid, &domains, &names, &types)) || !domains || !domains[0] || !names || !names[0]) { @@ -141,7 +144,7 @@ static BOOL StringToSid(DOM_SID *sid, const char *str) } if (!cacls_open_policy_hnd() || - !NT_STATUS_IS_OK(cli_lsa_lookup_names(global_hack_cli, global_hack_cli->mem_ctx, + !NT_STATUS_IS_OK(rpccli_lsa_lookup_names(global_pipe_hnd, global_hack_cli->mem_ctx, &pol, 1, &str, &sids, &types))) { result = False; diff --git a/source3/utils/smbcontrol.c b/source3/utils/smbcontrol.c index c0de85cea5d..a0304eb89a9 100644 --- a/source3/utils/smbcontrol.c +++ b/source3/utils/smbcontrol.c @@ -34,7 +34,8 @@ static int num_replies; /* Used by message callback fns */ /* Send a message to a destination pid. Zero means broadcast smbd. */ -static BOOL send_message(pid_t pid, int msg_type, const void *buf, int len, +static BOOL send_message(struct process_id pid, int msg_type, + const void *buf, int len, BOOL duplicates) { TDB_CONTEXT *tdb; @@ -44,7 +45,7 @@ static BOOL send_message(pid_t pid, int msg_type, const void *buf, int len, if (!message_init()) return False; - if (pid != 0) + if (procid_to_pid(&pid) != 0) return message_send_pid(pid, msg_type, buf, len, duplicates); tdb = tdb_open_log(lock_path("connections.tdb"), 0, @@ -84,15 +85,17 @@ static void wait_replies(BOOL multiple_replies) /* Message handler callback that displays the PID and a string on stdout */ -static void print_pid_string_cb(int msg_type, pid_t pid, void *buf, size_t len) +static void print_pid_string_cb(int msg_type, struct process_id pid, void *buf, size_t len) { - printf("PID %u: %.*s", (unsigned int)pid, (int)len, (const char *)buf); + printf("PID %u: %.*s", (unsigned int)procid_to_pid(&pid), + (int)len, (const char *)buf); num_replies++; } /* Message handler callback that displays a string on stdout */ -static void print_string_cb(int msg_type, pid_t pid, void *buf, size_t len) +static void print_string_cb(int msg_type, struct process_id pid, + void *buf, size_t len) { printf("%.*s", (int)len, (const char *)buf); num_replies++; @@ -100,7 +103,8 @@ static void print_string_cb(int msg_type, pid_t pid, void *buf, size_t len) /* Send no message. Useful for testing. */ -static BOOL do_noop(const pid_t pid, const int argc, const char **argv) +static BOOL do_noop(const struct process_id pid, + const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol noop\n"); @@ -114,7 +118,8 @@ static BOOL do_noop(const pid_t pid, const int argc, const char **argv) /* Send a debug string */ -static BOOL do_debug(const pid_t pid, const int argc, const char **argv) +static BOOL do_debug(const struct process_id pid, + const int argc, const char **argv) { if (argc != 2) { fprintf(stderr, "Usage: smbcontrol debug " @@ -128,7 +133,8 @@ static BOOL do_debug(const pid_t pid, const int argc, const char **argv) /* Force a browser election */ -static BOOL do_election(const pid_t pid, const int argc, const char **argv) +static BOOL do_election(const struct process_id pid, + const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol force-election\n"); @@ -141,13 +147,15 @@ static BOOL do_election(const pid_t pid, const int argc, const char **argv) /* Ping a samba daemon process */ -static void pong_cb(int msg_type, pid_t pid, void *buf, size_t len) +static void pong_cb(int msg_type, struct process_id pid, void *buf, size_t len) { - printf("PONG from pid %u\n", (unsigned int)pid); + char *src_string = procid_str(NULL, &pid); + printf("PONG from pid %s\n", src_string); + talloc_free(src_string); num_replies++; } -static BOOL do_ping(const pid_t pid, const int argc, const char **argv) +static BOOL do_ping(const struct process_id pid, const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol ping\n"); @@ -161,7 +169,7 @@ static BOOL do_ping(const pid_t pid, const int argc, const char **argv) message_register(MSG_PONG, pong_cb); - wait_replies(pid == 0); + wait_replies(procid_to_pid(&pid) == 0); /* No replies were received within the timeout period */ @@ -175,7 +183,8 @@ static BOOL do_ping(const pid_t pid, const int argc, const char **argv) /* Set profiling options */ -static BOOL do_profile(const pid_t pid, const int argc, const char **argv) +static BOOL do_profile(const struct process_id pid, + const int argc, const char **argv) { int v; @@ -203,7 +212,7 @@ static BOOL do_profile(const pid_t pid, const int argc, const char **argv) /* Return the profiling level */ -static void profilelevel_cb(int msg_type, pid_t pid, void *buf, size_t len) +static void profilelevel_cb(int msg_type, struct process_id pid, void *buf, size_t len) { int level; const char *s; @@ -236,10 +245,11 @@ static void profilelevel_cb(int msg_type, pid_t pid, void *buf, size_t len) break; } - printf("Profiling %s on pid %u\n",s,(unsigned int)pid); + printf("Profiling %s on pid %u\n",s,(unsigned int)procid_to_pid(&pid)); } -static void profilelevel_rqst(int msg_type, pid_t pid, void *buf, size_t len) +static void profilelevel_rqst(int msg_type, struct process_id pid, + void *buf, size_t len) { int v = 0; @@ -248,7 +258,8 @@ static void profilelevel_rqst(int msg_type, pid_t pid, void *buf, size_t len) send_message(pid, MSG_PROFILELEVEL, &v, sizeof(int), False); } -static BOOL do_profilelevel(const pid_t pid, const int argc, const char **argv) +static BOOL do_profilelevel(const struct process_id pid, + const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol profilelevel\n"); @@ -263,7 +274,7 @@ static BOOL do_profilelevel(const pid_t pid, const int argc, const char **argv) message_register(MSG_PROFILELEVEL, profilelevel_cb); message_register(MSG_REQ_PROFILELEVEL, profilelevel_rqst); - wait_replies(pid == 0); + wait_replies(procid_to_pid(&pid) == 0); /* No replies were received within the timeout period */ @@ -277,7 +288,8 @@ static BOOL do_profilelevel(const pid_t pid, const int argc, const char **argv) /* Display debug level settings */ -static BOOL do_debuglevel(const pid_t pid, const int argc, const char **argv) +static BOOL do_debuglevel(const struct process_id pid, + const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol debuglevel\n"); @@ -291,7 +303,7 @@ static BOOL do_debuglevel(const pid_t pid, const int argc, const char **argv) message_register(MSG_DEBUGLEVEL, print_pid_string_cb); - wait_replies(pid == 0); + wait_replies(procid_to_pid(&pid) == 0); /* No replies were received within the timeout period */ @@ -305,7 +317,8 @@ static BOOL do_debuglevel(const pid_t pid, const int argc, const char **argv) /* Send a print notify message */ -static BOOL do_printnotify(const pid_t pid, const int argc, const char **argv) +static BOOL do_printnotify(const struct process_id pid, + const int argc, const char **argv) { const char *cmd; @@ -428,7 +441,8 @@ static BOOL do_printnotify(const pid_t pid, const int argc, const char **argv) return False; } - notify_printer_byname(argv[2], attribute, argv[4]); + notify_printer_byname(argv[2], attribute, + CONST_DISCARD(char *, argv[4])); goto send; } @@ -443,7 +457,8 @@ send: /* Close a share */ -static BOOL do_closeshare(const pid_t pid, const int argc, const char **argv) +static BOOL do_closeshare(const struct process_id pid, + const int argc, const char **argv) { if (argc != 2) { fprintf(stderr, "Usage: smbcontrol close-share " @@ -457,7 +472,8 @@ static BOOL do_closeshare(const pid_t pid, const int argc, const char **argv) /* Force a SAM synchronisation */ -static BOOL do_samsync(const pid_t pid, const int argc, const char **argv) +static BOOL do_samsync(const struct process_id pid, + const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol samsync\n"); @@ -470,7 +486,8 @@ static BOOL do_samsync(const pid_t pid, const int argc, const char **argv) /* Force a SAM replication */ -static BOOL do_samrepl(const pid_t pid, const int argc, const char **argv) +static BOOL do_samrepl(const struct process_id pid, + const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol samrepl\n"); @@ -483,7 +500,8 @@ static BOOL do_samrepl(const pid_t pid, const int argc, const char **argv) /* Display talloc pool usage */ -static BOOL do_poolusage(const pid_t pid, const int argc, const char **argv) +static BOOL do_poolusage(const struct process_id pid, + const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol pool-usage\n"); @@ -497,7 +515,7 @@ static BOOL do_poolusage(const pid_t pid, const int argc, const char **argv) message_register(MSG_POOL_USAGE, print_string_cb); - wait_replies(pid == 0); + wait_replies(procid_to_pid(&pid) == 0); /* No replies were received within the timeout period */ @@ -511,7 +529,8 @@ static BOOL do_poolusage(const pid_t pid, const int argc, const char **argv) /* Perform a dmalloc mark */ -static BOOL do_dmalloc_mark(const pid_t pid, const int argc, const char **argv) +static BOOL do_dmalloc_mark(const struct process_id pid, + const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol dmalloc-mark\n"); @@ -524,7 +543,8 @@ static BOOL do_dmalloc_mark(const pid_t pid, const int argc, const char **argv) /* Perform a dmalloc changed */ -static BOOL do_dmalloc_changed(const pid_t pid, const int argc, const char **argv) +static BOOL do_dmalloc_changed(const struct process_id pid, + const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol " @@ -538,7 +558,8 @@ static BOOL do_dmalloc_changed(const pid_t pid, const int argc, const char **arg /* Shutdown a server process */ -static BOOL do_shutdown(const pid_t pid, const int argc, const char **argv) +static BOOL do_shutdown(const struct process_id pid, + const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol shutdown\n"); @@ -550,7 +571,8 @@ static BOOL do_shutdown(const pid_t pid, const int argc, const char **argv) /* Notify a driver upgrade */ -static BOOL do_drvupgrade(const pid_t pid, const int argc, const char **argv) +static BOOL do_drvupgrade(const struct process_id pid, + const int argc, const char **argv) { if (argc != 2) { fprintf(stderr, "Usage: smbcontrol drvupgrade " @@ -562,7 +584,8 @@ static BOOL do_drvupgrade(const pid_t pid, const int argc, const char **argv) pid, MSG_DEBUG, argv[1], strlen(argv[1]) + 1, False); } -static BOOL do_reload_config(const pid_t pid, const int argc, const char **argv) +static BOOL do_reload_config(const struct process_id pid, + const int argc, const char **argv) { if (argc != 1) { fprintf(stderr, "Usage: smbcontrol reload-config\n"); @@ -583,8 +606,8 @@ static void my_make_nmb_name( struct nmb_name *n, const char *name, int type) push_ascii(n->scope, global_scope(), 64, STR_TERMINATE); } -static BOOL do_nodestatus(const pid_t pid, const int argc, - const char **argv) +static BOOL do_nodestatus(const struct process_id pid, + const int argc, const char **argv) { struct packet_struct p; @@ -623,7 +646,8 @@ static BOOL do_nodestatus(const pid_t pid, const int argc, static const struct { const char *name; /* Option name */ - BOOL (*fn)(const pid_t pid, const int argc, const char **argv); + BOOL (*fn)(const struct process_id pid, + const int argc, const char **argv); const char *help; /* Short help text */ } msg_types[] = { { "debug", do_debug, "Set debuglevel" }, @@ -674,33 +698,39 @@ static void usage(poptContext *pc) /* Return the pid number for a string destination */ -static pid_t parse_dest(const char *dest) +static struct process_id parse_dest(const char *dest) { + struct process_id result; pid_t pid; /* Zero is a special return value for broadcast smbd */ - if (strequal(dest, "smbd")) - return 0; + if (strequal(dest, "smbd")) { + return interpret_pid("0"); + } /* Try self - useful for testing */ - if (strequal(dest, "self")) - return sys_getpid(); + if (strequal(dest, "self")) { + return pid_to_procid(sys_getpid()); + } /* Check for numeric pid number */ - if ((pid = atoi(dest)) != 0) - return pid; + result = interpret_pid(dest); + if (procid_valid(&result)) { + return result; + } /* Look up other destinations in pidfile directory */ - if ((pid = pidfile_pid(dest)) != 0) - return pid; + if ((pid = pidfile_pid(dest)) != 0) { + return pid_to_procid(pid); + } fprintf(stderr,"Can't find pid for destination '%s'\n", dest); - return -1; + return result; } /* Execute smbcontrol command */ @@ -708,13 +738,15 @@ static pid_t parse_dest(const char *dest) static BOOL do_command(int argc, const char **argv) { const char *dest = argv[0], *command = argv[1]; - pid_t pid; + struct process_id pid; int i; /* Check destination */ - if ((pid = parse_dest(dest)) == -1) + pid = parse_dest(dest); + if (!procid_valid(&pid)) { return False; + } /* Check command */ diff --git a/source3/utils/smbcquotas.c b/source3/utils/smbcquotas.c index 81f7dd42bbc..c516fbb2187 100644 --- a/source3/utils/smbcquotas.c +++ b/source3/utils/smbcquotas.c @@ -34,7 +34,8 @@ static BOOL verbose; enum todo_values {NOOP_QUOTA=0,FS_QUOTA,USER_QUOTA,LIST_QUOTA,SET_QUOTA}; enum exit_values {EXIT_OK, EXIT_FAILED, EXIT_PARSE_ERROR}; -static struct cli_state *cli_ipc = NULL; +static struct cli_state *cli_ipc; +static struct rpc_pipe_client *global_pipe_hnd; static POLICY_HND pol; static BOOL got_policy_hnd; @@ -47,8 +48,10 @@ static BOOL cli_open_policy_hnd(void) /* Initialise cli LSA connection */ if (!cli_ipc) { + NTSTATUS ret; cli_ipc = connect_one("IPC$"); - if (!cli_nt_session_open (cli_ipc, PI_LSARPC)) { + global_pipe_hnd = cli_rpc_pipe_open_noauth(cli_ipc, PI_LSARPC, &ret); + if (!global_pipe_hnd) { return False; } } @@ -60,7 +63,7 @@ static BOOL cli_open_policy_hnd(void) /* Some systems don't support SEC_RIGHTS_MAXIMUM_ALLOWED, but NT sends 0x2000000 so we might as well do it too. */ - if (!NT_STATUS_IS_OK(cli_lsa_open_policy(cli_ipc, cli_ipc->mem_ctx, True, + if (!NT_STATUS_IS_OK(rpccli_lsa_open_policy(global_pipe_hnd, cli_ipc->mem_ctx, True, GENERIC_EXECUTE_ACCESS, &pol))) { return False; } @@ -85,7 +88,7 @@ static void SidToString(fstring str, DOM_SID *sid, BOOL _numeric) /* Ask LSA to convert the sid to a name */ if (!cli_open_policy_hnd() || - !NT_STATUS_IS_OK(cli_lsa_lookup_sids(cli_ipc, cli_ipc->mem_ctx, + !NT_STATUS_IS_OK(rpccli_lsa_lookup_sids(global_pipe_hnd, cli_ipc->mem_ctx, &pol, 1, sid, &domains, &names, &types)) || !domains || !domains[0] || !names || !names[0]) { @@ -112,7 +115,7 @@ static BOOL StringToSid(DOM_SID *sid, const char *str) } if (!cli_open_policy_hnd() || - !NT_STATUS_IS_OK(cli_lsa_lookup_names(cli_ipc, cli_ipc->mem_ctx, + !NT_STATUS_IS_OK(rpccli_lsa_lookup_names(global_pipe_hnd, cli_ipc->mem_ctx, &pol, 1, &str, &sids, &types))) { result = False; diff --git a/source3/utils/status.c b/source3/utils/status.c index 96e4bd266b9..4709cfbaee1 100644 --- a/source3/utils/status.c +++ b/source3/utils/status.c @@ -98,7 +98,7 @@ static BOOL Ucrit_addPid( pid_t pid ) return True; } -static void print_share_mode(share_mode_entry *e, char *fname) +static void print_share_mode(const struct share_mode_entry *e, char *fname) { static int count; if (count==0) { @@ -108,8 +108,8 @@ static void print_share_mode(share_mode_entry *e, char *fname) } count++; - if (Ucrit_checkPid(e->pid)) { - d_printf("%-5d ",(int)e->pid); + if (Ucrit_checkPid(procid_to_pid(&e->pid))) { + d_printf("%s ",procid_str_static(&e->pid)); switch (map_share_mode_to_deny_mode(e->share_access, e->private_options)) { case DENY_NONE: d_printf("DENY_NONE "); break; @@ -154,7 +154,7 @@ static void print_share_mode(share_mode_entry *e, char *fname) } } -static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, int pid, +static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, struct process_id pid, enum brl_type lock_type, br_off start, br_off size) { @@ -166,8 +166,8 @@ static void print_brl(SMB_DEV_T dev, SMB_INO_T ino, int pid, } count++; - d_printf("%6d %05x:%05x %s %9.0f %9.0f\n", - (int)pid, (int)dev, (int)ino, + d_printf("%s %05x:%05x %s %9.0f %9.0f\n", + procid_str_static(&pid), (int)dev, (int)ino, lock_type==READ_LOCK?"R":"W", (double)start, (double)size); } @@ -550,8 +550,8 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void *st return 0; } - d_printf("%-10s %5d %-12s %s", - crec.name,(int)crec.pid, + d_printf("%-10s %s %-12s %s", + crec.name,procid_str_static(&crec.pid), crec.machine, asctime(LocalTime(&crec.start))); @@ -568,7 +568,7 @@ static int traverse_sessionid(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, vo memcpy(&sessionid, dbuf.dptr, sizeof(sessionid)); - if (!process_exists(sessionid.pid) || !Ucrit_checkUid(sessionid.uid)) { + if (!process_exists_by_pid(sessionid.pid) || !Ucrit_checkUid(sessionid.uid)) { return 0; } diff --git a/source3/utils/testparm.c b/source3/utils/testparm.c index 2b72479ac07..b4561b58deb 100644 --- a/source3/utils/testparm.c +++ b/source3/utils/testparm.c @@ -206,7 +206,7 @@ via the %%o substitution. With encrypted passwords this is not possible.\n", lp_ poptContext pc; static const char *term_code = ""; static char *parameter_name = NULL; - static char *section_name = NULL; + static const char *section_name = NULL; static char *new_local_machine = NULL; const char *cname; const char *caddr; diff --git a/source3/web/diagnose.c b/source3/web/diagnose.c index d259717da0b..c7a7a3598ee 100644 --- a/source3/web/diagnose.c +++ b/source3/web/diagnose.c @@ -21,8 +21,6 @@ #include "includes.h" #include "web/swat_proto.h" -extern struct in_addr loopback_ip; - #ifdef WITH_WINBIND /* check to see if winbind is running by pinging it */ @@ -37,6 +35,7 @@ BOOL winbindd_running(void) response */ BOOL nmbd_running(void) { + extern struct in_addr loopback_ip; int fd, count, flags; struct in_addr *ip_list; @@ -61,6 +60,7 @@ BOOL nmbd_running(void) BOOL smbd_running(void) { static struct cli_state cli; + extern struct in_addr loopback_ip; if (!cli_initialise(&cli)) return False; diff --git a/source3/web/neg_lang.c b/source3/web/neg_lang.c index cc2924afde6..ca671822d87 100644 --- a/source3/web/neg_lang.c +++ b/source3/web/neg_lang.c @@ -54,8 +54,8 @@ struct pri_list { }; static int qsort_cmp_list(const void *x, const void *y) { - struct pri_list *a = CONST_DISCARD(struct pri_list *, x); - struct pri_list *b = CONST_DISCARD(struct pri_list *, y); + struct pri_list *a = (struct pri_list *)x; + struct pri_list *b = (struct pri_list *)y; if (a->pri > b->pri) return -1; if (a->pri == b->pri) return 0; return 1; diff --git a/source3/web/startstop.c b/source3/web/startstop.c index 9ffda5bb941..8f28748918f 100644 --- a/source3/web/startstop.c +++ b/source3/web/startstop.c @@ -121,11 +121,11 @@ void stop_winbindd(void) } #endif /* kill a specified process */ -void kill_pid(pid_t pid) +void kill_pid(struct process_id pid) { if (geteuid() != 0) return; - if (pid <= 0) return; + if (procid_to_pid(&pid) <= 0) return; - kill(pid, SIGTERM); + kill(procid_to_pid(&pid), SIGTERM); } diff --git a/source3/web/statuspage.c b/source3/web/statuspage.c index 871e07b5d06..edc03183730 100644 --- a/source3/web/statuspage.c +++ b/source3/web/statuspage.c @@ -28,14 +28,14 @@ PIDMAP { PIDMAP *next, *prev; - pid_t pid; + struct process_id pid; char *machine; }; static PIDMAP *pidmap; static int PID_or_Machine; /* 0 = show PID, else show Machine name */ -static pid_t smbd_pid; +static struct process_id smbd_pid; /* from 2nd call on, remove old list */ static void initPid2Machine (void) @@ -55,7 +55,7 @@ static void initPid2Machine (void) } /* add new PID <-> Machine name mapping */ -static void addPid2Machine (pid_t pid, char *machine) +static void addPid2Machine (struct process_id pid, char *machine) { /* show machine name rather PID on table "Open Files"? */ if (PID_or_Machine) { @@ -75,7 +75,7 @@ static void addPid2Machine (pid_t pid, char *machine) } /* lookup PID <-> Machine name mapping */ -static char *mapPid2Machine (pid_t pid) +static char *mapPid2Machine (struct process_id pid) { static char pidbuf [64]; PIDMAP *map; @@ -83,7 +83,7 @@ static char *mapPid2Machine (pid_t pid) /* show machine name rather PID on table "Open Files"? */ if (PID_or_Machine) { for (map = pidmap; map != NULL; map = map->next) { - if (pid == map->pid) { + if (procid_equal(&pid, &map->pid)) { if (map->machine == NULL) /* no machine name */ break; /* show PID */ @@ -93,7 +93,8 @@ static char *mapPid2Machine (pid_t pid) } /* PID not in list or machine name NULL? return pid as string */ - snprintf (pidbuf, sizeof (pidbuf) - 1, "%lu", (unsigned long)pid); + snprintf (pidbuf, sizeof (pidbuf) - 1, "%s", + procid_str_static(&pid)); return pidbuf; } @@ -105,7 +106,7 @@ static char *tstring(time_t t) return buf; } -static void print_share_mode(share_mode_entry *e, char *fname) +static void print_share_mode(const struct share_mode_entry *e, char *fname) { char *utf8_fname; int deny_mode = map_share_mode_to_deny_mode(e->share_access, @@ -167,7 +168,7 @@ static int traverse_fn1(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* st if (crec.cnum == -1 && process_exists(crec.pid)) { char buf[30]; - slprintf(buf,sizeof(buf)-1,"kill_%d", (int)crec.pid); + slprintf(buf,sizeof(buf)-1,"kill_%s", procid_str_static(&crec.pid)); if (cgi_variable(buf)) { kill_pid(crec.pid); sleep(SLEEP_TIME); @@ -186,18 +187,19 @@ static int traverse_fn2(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* st memcpy(&crec, dbuf.dptr, sizeof(crec)); - if (crec.cnum == -1 || !process_exists(crec.pid) || (crec.pid == smbd_pid)) + if (crec.cnum == -1 || !process_exists(crec.pid) || + procid_equal(&crec.pid, &smbd_pid)) return 0; addPid2Machine (crec.pid, crec.machine); - printf("%d%s%s%s\n", - (int)crec.pid, + printf("%s%s%s%s\n", + procid_str_static(&crec.pid), crec.machine,crec.addr, tstring(crec.start)); if (geteuid() == 0) { - printf("\n", - (int)crec.pid); + printf("\n", + procid_str_static(&crec.pid)); } printf("\n"); @@ -217,9 +219,9 @@ static int traverse_fn3(TDB_CONTEXT *tdb, TDB_DATA kbuf, TDB_DATA dbuf, void* st if (crec.cnum == -1 || !process_exists(crec.pid)) return 0; - printf("%s%s%s%d%s%s\n", + printf("%s%s%s%s%s%s\n", crec.name,uidtoname(crec.uid), - gidtoname(crec.gid),(int)crec.pid, + gidtoname(crec.gid),procid_str_static(&crec.pid), crec.machine, tstring(crec.start)); return 0; @@ -236,7 +238,7 @@ void status_page(void) int nr_running=0; BOOL waitup = False; - smbd_pid = pidfile_pid("smbd"); + smbd_pid = pid_to_procid(pidfile_pid("smbd")); if (cgi_variable("smbd_restart") || cgi_variable("all_restart")) { stop_smbd(); diff --git a/source3/web/swat.c b/source3/web/swat.c index 15612484a35..4082574e442 100644 --- a/source3/web/swat.c +++ b/source3/web/swat.c @@ -188,12 +188,12 @@ static const char* get_parm_translated( if(strcmp(pLabel, pTranslated) != 0) { pstr_sprintf(output, - " %s       %s
%s", + " %s       %s
%s", pAnchor, pHelp, pLabel, pTranslated); return output; } pstr_sprintf(output, - " %s       %s", + " %s %s", pAnchor, pHelp, pLabel); return output; } @@ -220,7 +220,7 @@ static void show_parameter(int snum, struct parm_struct *parm) ptr = lp_local_ptr(snum, ptr); } - printf("%s", get_parm_translated(stripspaceupper(parm->label), _("Help"), parm->label)); + printf("%s", get_parm_translated(stripspaceupper(parm->label), _("Help"), parm->label)); switch (parm->type) { case P_CHAR: printf("", @@ -230,7 +230,7 @@ static void show_parameter(int snum, struct parm_struct *parm) break; case P_LIST: - printf("label)); if ((char ***)ptr && *(char ***)ptr && **(char ***)ptr) { char **list = *(char ***)ptr; @@ -268,7 +268,7 @@ static void show_parameter(int snum, struct parm_struct *parm) case P_STRING: case P_USTRING: push_utf8_allocate(&utf8_s1, *(char **)ptr); - printf("", + printf("", make_parm_name(parm->label), fix_quotes(utf8_s1)); SAFE_FREE(utf8_s1); printf("", @@ -278,7 +278,7 @@ static void show_parameter(int snum, struct parm_struct *parm) case P_GSTRING: case P_UGSTRING: push_utf8_allocate(&utf8_s1, (char *)ptr); - printf("", + printf("", make_parm_name(parm->label), fix_quotes(utf8_s1)); SAFE_FREE(utf8_s1); printf("", @@ -523,42 +523,50 @@ static void commit_parameters(int snum) } /**************************************************************************** - spit out the html for a link with an image + generate html for rollovers ****************************************************************************/ -static void image_link(const char *name, const char *hlink, const char *src) +static void rollover_link(const char *name, const char *id, const char *page) { - printf("\"%s\"\n", - cgi_baseurl(), hlink, src, name); + if ( strcmp(page, id)==0 ) { + printf(" \"%s\"\n", + id, name); + } else { + printf(" \"%s\"\n", + cgi_baseurl(), id, id, id, id, id, id, id, name); + } } /**************************************************************************** display the main navigation controls at the top of each page along with a title ****************************************************************************/ -static void show_main_buttons(void) +static void show_main_buttons(const char *page) { char *p; - if ((p = cgi_user_name()) && strcmp(p, "root")) { - printf(_("Logged in as %s"), p); - printf("

\n"); - } + printf("

\n"); - image_link(_("Home"), "", "images/home.gif"); if (have_write_access) { - image_link(_("Globals"), "globals", "images/globals.gif"); - image_link(_("Shares"), "shares", "images/shares.gif"); - image_link(_("Printers"), "printers", "images/printers.gif"); - image_link(_("Wizard"), "wizard", "images/wizard.gif"); + rollover_link(_("Configure"), "conf", page); + rollover_link(_("Services"), "services", page); } - /* root always gets all buttons, otherwise look for -P */ + + /* root always gets all buttons, otherwise look for -P */ if ( have_write_access || (!passwd_only && have_read_access) ) { - image_link(_("Status"), "status", "images/status.gif"); - image_link(_("View Config"), "viewconfig", "images/viewconfig.gif"); + rollover_link(_("Status"), "status", page); + } + rollover_link(_("Password Management"), "passwd", page); + + printf("
\n\n"); + + /* Wrap the rest in a control div */ + printf("
\n\n"); + + if ((p = cgi_user_name()) && strcmp(p, "root")) { + printf(_("Logged in as %s"), p); + printf("

\n"); } - image_link(_("Password Management"), "passwd", "images/passwd.gif"); - printf("


\n"); } /**************************************************************************** @@ -576,11 +584,47 @@ static void ViewModeBoxes(int mode) } /**************************************************************************** - display a welcome page + display a welcome page (Read-only users under passwd only get a unique welcome) ****************************************************************************/ static void welcome_page(void) { - include_html("help/welcome.html"); + if (passwd_only && !have_write_access) { + include_html("help/welcome_passwd_only.html"); + } else { + include_html("help/welcome.html"); + } +} + +/**************************************************************************** + display help page +****************************************************************************/ +static void help_page(void) +{ + include_html("help/docs.html"); +} + +/**************************************************************************** + display shares and printers links from an overall services page +****************************************************************************/ +static void services_page(void) +{ + printf("
\n"); + printf("

File and Printer Shares

\n\n"); + printf("

Follow the links below to edit service-level parameters for file and printer shares.

\n"); + printf("
\n\n"); + + printf(" \n\n"); + + printf("
\n"); + printf(" \n"); + printf("
\n\n"); + + printf("
\n"); + printf("

Shares may also be added via the links above.

\n"); + printf("
\n\n"); } /**************************************************************************** @@ -648,7 +692,9 @@ static void rewritecfg_file(void) { commit_parameters(GLOBAL_SECTION_SNUM); save_reload(0); - printf("

%s

\n", _("Note: smb.conf file has been read and rewritten")); + printf("

Samba Configuration Saved

"); + printf("

%s

\n", _("Note: smb.conf file has been read and rewritten")); + printf("

Return to the previous page.\n"); } /**************************************************************************** @@ -760,7 +806,7 @@ static void wizard_page(void) printf("

\n"); if (have_write_access) { - printf("%s\n", _("The \"Rewrite smb.conf file\" button will clear the smb.conf file of all default values and of comments.")); + printf("%s\n", _("The "Rewrite smb.conf file" button will clear the smb.conf file of all default values and of comments.")); printf("%s", _("The same will happen if you press the commit button.")); printf("

\n"); printf("
"); @@ -820,14 +866,19 @@ static void wizard_page(void) /**************************************************************************** - display a globals editing page + display a conf page for editing global parameters ****************************************************************************/ -static void globals_page(void) +static void conf_page(void) { unsigned int parm_filter = FLAG_BASIC; int mode = 0; - printf("

%s

\n", _("Global Parameters")); + printf("
\n"); + printf("

Configuring Samba

\n\n"); + printf("

The following menu allows for editing of global parameters affecting your Samba configuration.

\n"); + printf("
\n\n"); + + printf(" \n\n"); if (cgi_variable("Commit")) { commit_parameters(GLOBAL_SECTION_SNUM); @@ -841,7 +892,7 @@ static void globals_page(void) if ( cgi_variable("AdvMode")) mode = 1; - printf("\n"); + printf("\n"); ViewModeBoxes( mode ); switch ( mode ) { @@ -885,6 +936,8 @@ static void shares_page(void) snum = lp_servicenumber(share); printf("

%s

\n", _("Share Parameters")); + + printf(" \n\n"); if (cgi_variable("Commit") && snum >= 0) { commit_parameters(snum); @@ -1226,6 +1279,8 @@ static void printers_page(void) snum = lp_servicenumber(share); printf("

%s

\n", _("Printer Parameters")); + + printf(" \n\n"); printf("

%s

\n", _("Important Note:")); printf(_("Printer names marked with [*] in the Choose Printer drop-down box ")); @@ -1395,29 +1450,32 @@ static void printers_page(void) have_read_access = (access(dyn_CONFIGFILE,R_OK) == 0); } - show_main_buttons(); - page = cgi_pathinfo(); - /* Root gets full functionality */ - if (have_read_access && strcmp(page, "globals")==0) { - globals_page(); + show_main_buttons(page); + + if (have_read_access && strcmp(page,"conf")==0) { + conf_page(); + } else if (have_read_access && strcmp(page,"viewconfig")==0) { + viewconfig_page(); + } else if (have_read_access && strcmp(page,"rewritecfg")==0) { + rewritecfg_file(); + } else if (have_read_access && strcmp(page,"services")==0) { + services_page(); } else if (have_read_access && strcmp(page,"shares")==0) { shares_page(); } else if (have_read_access && strcmp(page,"printers")==0) { printers_page(); } else if (have_read_access && strcmp(page,"status")==0) { status_page(); - } else if (have_read_access && strcmp(page,"viewconfig")==0) { - viewconfig_page(); } else if (strcmp(page,"passwd")==0) { passwd_page(); } else if (have_read_access && strcmp(page,"wizard")==0) { wizard_page(); } else if (have_read_access && strcmp(page,"wizard_params")==0) { wizard_params_page(); - } else if (have_read_access && strcmp(page,"rewritecfg")==0) { - rewritecfg_file(); + } else if (have_read_access && strcmp(page,"help")==0) { + help_page(); } else { welcome_page(); }