diff options
| author | Greg Hudson <ghudson@mit.edu> | 2010-11-25 20:28:30 +0000 |
|---|---|---|
| committer | Greg Hudson <ghudson@mit.edu> | 2010-11-25 20:28:30 +0000 |
| commit | 530043377ee6f39b9ca95c13f6260602e6fe7674 (patch) | |
| tree | 28fd4b42c486d7097c4cd537d90042bb5fda3852 /src/ccapi/server | |
| parent | e9dd6e21afc9af2237e9ae5590ad5a67e52fb24e (diff) | |
| download | krb5-530043377ee6f39b9ca95c13f6260602e6fe7674.tar.gz krb5-530043377ee6f39b9ca95c13f6260602e6fe7674.tar.xz krb5-530043377ee6f39b9ca95c13f6260602e6fe7674.zip | |
Fix Windows build
Repair the Windows build. Tested with the prepare-on-Unix method.
Some specific changes include:
* Removed the IPC finalizer (no longer used after r20787) from
ccapi/lib/ccapi_ipc.c, as it was creating a difficult dependency
chain for the pingtest build in ccapi/test. Also updated pingtest
to use the k5_ipc_stream interfaces since cci_stream is gone.
* Reverted the apparently non-functional r20277.
* klist -V prints just "Kerberos for Windows", since it has no access
to PACKAGE_NAME and PACKAGE_VERSION from autoconf. This should be
addressed correctly.
* krb5, telnet, gssftp, and NIM are removed from the build.
* Some files had CRLFs; these were replaced with LFs and the
svn:eol-style property set on the files. Otherwise the CRLFs became
CRCRLFs after the zip transfer.
* Windows does not have opendir/readdir, so added Windows code to
prof_parse.c for includedir. Probable fodder for a libkrb5support
portability shim.
ticket: 6826
target_version: 1.9
tags: pullup
git-svn-id: svn://anonsvn.mit.edu/krb5/trunk@24533 dc483132-0cff-0310-8789-dd5450dbe970
Diffstat (limited to 'src/ccapi/server')
| -rw-r--r-- | src/ccapi/server/win/Makefile.in | 218 | ||||
| -rw-r--r-- | src/ccapi/server/win/Server.sln | 40 | ||||
| -rw-r--r-- | src/ccapi/server/win/Server.vcproj | 454 | ||||
| -rw-r--r-- | src/ccapi/server/win/WorkItem.cpp | 252 | ||||
| -rw-r--r-- | src/ccapi/server/win/WorkQueue.cpp | 122 | ||||
| -rw-r--r-- | src/ccapi/server/win/ccs_os_server.cpp | 1926 |
6 files changed, 1506 insertions, 1506 deletions
diff --git a/src/ccapi/server/win/Makefile.in b/src/ccapi/server/win/Makefile.in index 3d8da6d223..36909b85eb 100644 --- a/src/ccapi/server/win/Makefile.in +++ b/src/ccapi/server/win/Makefile.in @@ -1,109 +1,109 @@ -# makefile: Constructs the Kerberos for Windows CCAPI server.
-
-#BUILDTOP is krb5/src and is relative to krb5/src/ccapi/server/win, for making Makefile.
-BUILDTOP=..\..\..\
-CCAPI = $(BUILDTOP)\CCAPI
-CO = $(CCAPI)\common
-COWIN = $(CCAPI)\common\win
-CCUTIL = $(CCAPI)\common\win\OldCC
-SRVDIR = $(CCAPI)\server
-SRVWIN = $(SRVDIR)\win
-POSIX = $(BUILDTOP)\lib\krb5\posix
-SRCTMP = $(SRVWIN)\srctmp
-
-!if defined(KRB5_KFW_COMPILE)
-KFWINC= /I$(BUILDTOP)\..\..\krbcc\include
-!endif
-
-OBJS = $(OUTPRE)cci_array_internal.$(OBJEXT) \
- $(OUTPRE)cci_cred_union.$(OBJEXT) \
- $(OUTPRE)cci_debugging.$(OBJEXT) \
- $(OUTPRE)cci_identifier.$(OBJEXT) \
- $(OUTPRE)cci_message.$(OBJEXT) \
- $(OUTPRE)cci_os_debugging.$(OBJEXT) \
- $(OUTPRE)cci_os_identifier.$(OBJEXT) \
- $(OUTPRE)ccs_array.$(OBJEXT) \
- $(OUTPRE)ccs_cache_collection.$(OBJEXT) \
- $(OUTPRE)ccs_callback.$(OBJEXT) \
- $(OUTPRE)ccs_ccache.$(OBJEXT) \
- $(OUTPRE)ccs_ccache_iterator.$(OBJEXT) \
- $(OUTPRE)ccs_client.$(OBJEXT) \
- $(OUTPRE)ccs_credentials.$(OBJEXT) \
- $(OUTPRE)ccs_credentials_iterator.$(OBJEXT) \
- $(OUTPRE)ccs_list.$(OBJEXT) \
- $(OUTPRE)ccs_list_internal.$(OBJEXT) \
- $(OUTPRE)ccs_lock.$(OBJEXT) \
- $(OUTPRE)ccs_lock_state.$(OBJEXT) \
- $(OUTPRE)ccs_os_pipe.$(OBJEXT) \
- $(OUTPRE)ccs_os_server.$(OBJEXT) \
- $(OUTPRE)ccs_pipe.$(OBJEXT) \
- $(OUTPRE)ccs_reply_c.$(OBJEXT) \
- $(OUTPRE)ccs_request_proc.$(OBJEXT) \
- $(OUTPRE)ccs_server.$(OBJEXT) \
- $(OUTPRE)ccs_win_pipe.$(OBJEXT) \
- $(OUTPRE)ccs_request_s.$(OBJEXT) \
- $(OUTPRE)ccutils.$(OBJEXT) \
- $(OUTPRE)init.$(OBJEXT) \
- $(OUTPRE)opts.$(OBJEXT) \
- $(OUTPRE)secure.$(OBJEXT) \
- $(OUTPRE)tls.$(OBJEXT) \
- $(OUTPRE)util.$(OBJEXT) \
- $(OUTPRE)win-utils.$(OBJEXT) \
- $(OUTPRE)WorkItem.$(OBJEXT) \
- $(OUTPRE)WorkQueue.$(OBJEXT)
-
-##### Options
-
-# Because all the sources are pulled together into the temp directory SRCTMP,
-# the only includes we need are to directories outside of ccapi.
-LOCALINCLUDES = /I..\$(BUILDTOP) /I..\$(BUILDTOP)\include /I..\$(BUILDTOP)\include\krb5 $(KFWINC) \
- -I..\$(BUILDTOP)\util\et /I.
-MIDLI = /I..\$(BUILDTOP)\include
-
-CPPFLAGS = $(CPPFLAGS) /EHsc -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 \
--D_WIN32_WINNT=0x0501 -D_CRT_SECURE_NO_WARNINGS
-
-##### Linker
-LINK = link
-LIBS = ..\$(SLIB) rpcrt4.lib advapi32.lib ws2_32.lib user32.lib
-LFLAGS = /nologo $(LOPTS)
-
-
-all:: Makefile copysrc midl $(OUTPRE)ccapiserver.exe finish
-
-ccs_request.h ccs_request_c.c ccs_request_s.c : ccs_request.idl ccs_request.acf
- midl $(MIDL_OPTIMIZATION) $(MIDLI) -oldnames -cpp_cmd $(CC) -cpp_opt "-E" \
- ccs_request.idl
-
-ccs_reply.h ccs_reply_c.c ccs_reply_s.c : ccs_reply.idl ccs_reply.acf
- midl $(MIDL_OPTIMIZATION) $(MIDLI) -oldnames -cpp_cmd $(CC) -cpp_opt "-E" \
- ccs_reply.idl
-
-copysrc :
- echo "Copying all sources needed to build ccapiserver.exe to $(SRCTMP)"
- if NOT exist $(SRCTMP)\nul mkdir $(SRCTMP)
- xcopy /D/Y $(CO)\*.* $(SRCTMP)
- xcopy /D/Y $(COWIN)\*.* $(SRCTMP)
- xcopy /D/Y $(CCUTIL)\*.* $(SRCTMP)
- xcopy /D/Y $(SRVDIR)\*.* $(SRCTMP)
- xcopy /D/Y $(SRVWIN)\*.* $(SRCTMP)
- cd $(SRCTMP)
- if NOT exist $(OUTPRE)\nul mkdir $(OUTPRE)
-
-midl : ccs_request.h ccs_reply.h
-
-$(OUTPRE)ccapiserver.exe: $(OBJS)
- $(LINK) $(LFLAGS) /map:$*.map /out:$@ $(OBJS) $(LIBS) $(conlibsdll) $(conflags)
-
-finish :
- @echo "Finished building ccapiserver.exe"
- cd
-
-clean::
- if exist $(OUTPRE)*.exe del $(OUTPRE)*.exe
- if exist $(OUTPRE)*.obj del $(OUTPRE)*.obj
- if exist $(OUTPRE)*.res del $(OUTPRE)*.res
- if exist $(OUTPRE)*.map del $(OUTPRE)*.map
- if exist $(OUTPRE)*.pdb del $(OUTPRE)*.pdb
- if exist *.err del *.err
- if exist $(SRCTMP) rm -rf $(SRCTMP)
+# makefile: Constructs the Kerberos for Windows CCAPI server. + +#BUILDTOP is krb5/src and is relative to krb5/src/ccapi/server/win, for making Makefile. +BUILDTOP=..\..\.. +CCAPI = $(BUILDTOP)\CCAPI +CO = $(CCAPI)\common +COWIN = $(CCAPI)\common\win +CCUTIL = $(CCAPI)\common\win\OldCC +SRVDIR = $(CCAPI)\server +SRVWIN = $(SRVDIR)\win +POSIX = $(BUILDTOP)\lib\krb5\posix +SRCTMP = $(SRVWIN)\srctmp + +!if defined(KRB5_KFW_COMPILE) +KFWINC= /I$(BUILDTOP)\..\..\krbcc\include +!endif + +OBJS = $(OUTPRE)cci_array_internal.$(OBJEXT) \ + $(OUTPRE)cci_cred_union.$(OBJEXT) \ + $(OUTPRE)cci_debugging.$(OBJEXT) \ + $(OUTPRE)cci_identifier.$(OBJEXT) \ + $(OUTPRE)cci_message.$(OBJEXT) \ + $(OUTPRE)cci_os_debugging.$(OBJEXT) \ + $(OUTPRE)cci_os_identifier.$(OBJEXT) \ + $(OUTPRE)ccs_array.$(OBJEXT) \ + $(OUTPRE)ccs_cache_collection.$(OBJEXT) \ + $(OUTPRE)ccs_callback.$(OBJEXT) \ + $(OUTPRE)ccs_ccache.$(OBJEXT) \ + $(OUTPRE)ccs_ccache_iterator.$(OBJEXT) \ + $(OUTPRE)ccs_client.$(OBJEXT) \ + $(OUTPRE)ccs_credentials.$(OBJEXT) \ + $(OUTPRE)ccs_credentials_iterator.$(OBJEXT) \ + $(OUTPRE)ccs_list.$(OBJEXT) \ + $(OUTPRE)ccs_list_internal.$(OBJEXT) \ + $(OUTPRE)ccs_lock.$(OBJEXT) \ + $(OUTPRE)ccs_lock_state.$(OBJEXT) \ + $(OUTPRE)ccs_os_pipe.$(OBJEXT) \ + $(OUTPRE)ccs_os_server.$(OBJEXT) \ + $(OUTPRE)ccs_pipe.$(OBJEXT) \ + $(OUTPRE)ccs_reply_c.$(OBJEXT) \ + $(OUTPRE)ccs_request_proc.$(OBJEXT) \ + $(OUTPRE)ccs_server.$(OBJEXT) \ + $(OUTPRE)ccs_win_pipe.$(OBJEXT) \ + $(OUTPRE)ccs_request_s.$(OBJEXT) \ + $(OUTPRE)ccutils.$(OBJEXT) \ + $(OUTPRE)init.$(OBJEXT) \ + $(OUTPRE)opts.$(OBJEXT) \ + $(OUTPRE)secure.$(OBJEXT) \ + $(OUTPRE)tls.$(OBJEXT) \ + $(OUTPRE)util.$(OBJEXT) \ + $(OUTPRE)win-utils.$(OBJEXT) \ + $(OUTPRE)WorkItem.$(OBJEXT) \ + $(OUTPRE)WorkQueue.$(OBJEXT) + +##### Options + +# Because all the sources are pulled together into the temp directory SRCTMP, +# the only includes we need are to directories outside of ccapi. +LOCALINCLUDES = /I..\$(BUILDTOP) /I..\$(BUILDTOP)\include /I..\$(BUILDTOP)\include\krb5 $(KFWINC) \ + -I..\$(BUILDTOP)\util\et /I. +MIDLI = /I..\$(BUILDTOP)\include + +CPPFLAGS = $(CPPFLAGS) /EHsc -D_CRTAPI1=_cdecl -D_CRTAPI2=_cdecl -DWINVER=0x0501 \ +-D_WIN32_WINNT=0x0501 -D_CRT_SECURE_NO_WARNINGS + +##### Linker +LINK = link +LIBS = ..\$(SLIB) rpcrt4.lib advapi32.lib ws2_32.lib user32.lib +LFLAGS = /nologo $(LOPTS) + + +all:: Makefile copysrc midl $(OUTPRE)ccapiserver.exe finish + +ccs_request.h ccs_request_c.c ccs_request_s.c : ccs_request.idl ccs_request.acf + midl $(MIDL_OPTIMIZATION) $(MIDLI) -oldnames -cpp_cmd $(CC) -cpp_opt "-E" \ + ccs_request.idl + +ccs_reply.h ccs_reply_c.c ccs_reply_s.c : ccs_reply.idl ccs_reply.acf + midl $(MIDL_OPTIMIZATION) $(MIDLI) -oldnames -cpp_cmd $(CC) -cpp_opt "-E" \ + ccs_reply.idl + +copysrc : + echo "Copying all sources needed to build ccapiserver.exe to $(SRCTMP)" + if NOT exist $(SRCTMP)\nul mkdir $(SRCTMP) + xcopy /D/Y $(CO)\*.* $(SRCTMP) + xcopy /D/Y $(COWIN)\*.* $(SRCTMP) + xcopy /D/Y $(CCUTIL)\*.* $(SRCTMP) + xcopy /D/Y $(SRVDIR)\*.* $(SRCTMP) + xcopy /D/Y $(SRVWIN)\*.* $(SRCTMP) + cd $(SRCTMP) + if NOT exist $(OUTPRE)\nul mkdir $(OUTPRE) + +midl : ccs_request.h ccs_reply.h + +$(OUTPRE)ccapiserver.exe: $(OBJS) + $(LINK) $(LFLAGS) /map:$*.map /out:$@ $(OBJS) $(LIBS) $(conlibsdll) $(conflags) + +finish : + @echo "Finished building ccapiserver.exe" + cd + +clean:: + if exist $(OUTPRE)*.exe del $(OUTPRE)*.exe + if exist $(OUTPRE)*.obj del $(OUTPRE)*.obj + if exist $(OUTPRE)*.res del $(OUTPRE)*.res + if exist $(OUTPRE)*.map del $(OUTPRE)*.map + if exist $(OUTPRE)*.pdb del $(OUTPRE)*.pdb + if exist *.err del *.err + if exist $(SRCTMP) rm -rf $(SRCTMP) diff --git a/src/ccapi/server/win/Server.sln b/src/ccapi/server/win/Server.sln index 64cc7f08c9..ea1bd455f6 100644 --- a/src/ccapi/server/win/Server.sln +++ b/src/ccapi/server/win/Server.sln @@ -1,20 +1,20 @@ -
-Microsoft Visual Studio Solution File, Format Version 9.00
-# Visual Studio 2005
-Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Server", "Server.vcproj", "{114DCD80-6D13-4AAA-9510-B51CE6D94C1C}"
-EndProject
-Global
- GlobalSection(SolutionConfigurationPlatforms) = preSolution
- Debug|Win32 = Debug|Win32
- Release|Win32 = Release|Win32
- EndGlobalSection
- GlobalSection(ProjectConfigurationPlatforms) = postSolution
- {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Debug|Win32.ActiveCfg = Debug|Win32
- {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Debug|Win32.Build.0 = Debug|Win32
- {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Release|Win32.ActiveCfg = Release|Win32
- {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Release|Win32.Build.0 = Release|Win32
- EndGlobalSection
- GlobalSection(SolutionProperties) = preSolution
- HideSolutionNode = FALSE
- EndGlobalSection
-EndGlobal
+ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Server", "Server.vcproj", "{114DCD80-6D13-4AAA-9510-B51CE6D94C1C}" +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Debug|Win32.ActiveCfg = Debug|Win32 + {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Debug|Win32.Build.0 = Debug|Win32 + {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Release|Win32.ActiveCfg = Release|Win32 + {114DCD80-6D13-4AAA-9510-B51CE6D94C1C}.Release|Win32.Build.0 = Release|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/src/ccapi/server/win/Server.vcproj b/src/ccapi/server/win/Server.vcproj index 39db361d8e..626c7a3c78 100644 --- a/src/ccapi/server/win/Server.vcproj +++ b/src/ccapi/server/win/Server.vcproj @@ -1,227 +1,227 @@ -<?xml version="1.0" encoding="UTF-8"?>
-<VisualStudioProject
- ProjectType="Visual C++"
- Version="8.00"
- Name="Server"
- ProjectGUID="{114DCD80-6D13-4AAA-9510-B51CE6D94C1C}"
- RootNamespace="Server"
- Keyword="MakeFileProj"
- >
- <Platforms>
- <Platform
- Name="Win32"
- />
- </Platforms>
- <ToolFiles>
- </ToolFiles>
- <Configurations>
- <Configuration
- Name="Debug|Win32"
- OutputDirectory="Debug"
- IntermediateDirectory="Debug"
- ConfigurationType="0"
- >
- <Tool
- Name="VCNMakeTool"
- BuildCommandLine="nmake"
- ReBuildCommandLine="nmake"
- CleanCommandLine="nmake clean"
- Output=""
- PreprocessorDefinitions="WIN32;_DEBUG;"
- IncludeSearchPath=""
- ForcedIncludes=""
- AssemblySearchPath=""
- ForcedUsingAssemblies=""
- CompileAsManaged=""
- />
- </Configuration>
- <Configuration
- Name="Release|Win32"
- OutputDirectory="Release"
- IntermediateDirectory="Release"
- ConfigurationType="0"
- >
- <Tool
- Name="VCNMakeTool"
- BuildCommandLine="nmake"
- ReBuildCommandLine="nmake"
- CleanCommandLine="nmake clean"
- Output=""
- PreprocessorDefinitions="WIN32;NDEBUG;"
- IncludeSearchPath=""
- ForcedIncludes=""
- AssemblySearchPath=""
- ForcedUsingAssemblies=""
- CompileAsManaged=""
- />
- </Configuration>
- </Configurations>
- <References>
- </References>
- <Files>
- <Filter
- Name="Header Files"
- Filter="h;hpp;hxx;hm;inl;inc;xsd"
- UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
- >
- <File
- RelativePath="..\..\common\cci_debugging.h"
- >
- </File>
- <File
- RelativePath="..\..\common\cci_os_debugging.h"
- >
- </File>
- <File
- RelativePath="..\..\common\cci_stream.h"
- >
- </File>
- <File
- RelativePath=".\ccs_reply.h"
- >
- </File>
- <File
- RelativePath=".\ccs_request.h"
- >
- </File>
- <File
- RelativePath="..\ccs_server.h"
- >
- </File>
- <File
- RelativePath="..\..\common\win\ccutil\ccutils.h"
- >
- </File>
- <File
- RelativePath="..\..\common\win\ccutil\init.hxx"
- >
- </File>
- <File
- RelativePath="..\..\..\include\k5-platform.h"
- >
- </File>
- <File
- RelativePath="..\..\common\win\ccutil\secure.hxx"
- >
- </File>
- <File
- RelativePath="..\..\common\win\ccutil\util.h"
- >
- </File>
- <File
- RelativePath="..\..\common\win\win-utils.h"
- >
- </File>
- <File
- RelativePath=".\workitem.h"
- >
- </File>
- <File
- RelativePath=".\WorkQueue.h"
- >
- </File>
- </Filter>
- <Filter
- Name="Resource Files"
- Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx"
- UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
- >
- </Filter>
- <Filter
- Name="Source Files"
- Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
- UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
- >
- <File
- RelativePath="..\..\common\cci_debugging.c"
- >
- </File>
- <File
- RelativePath="..\..\common\win\cci_os_debugging.c"
- >
- </File>
- <File
- RelativePath="..\..\common\cci_stream.c"
- >
- </File>
- <File
- RelativePath="..\ccs_lock.c"
- >
- </File>
- <File
- RelativePath=".\ccs_os_pipe.c"
- >
- </File>
- <File
- RelativePath=".\ccs_os_server.cpp"
- >
- </File>
- <File
- RelativePath="..\..\common\win\ccs_reply.Idl"
- >
- </File>
- <File
- RelativePath=".\ccs_reply_c.c"
- >
- </File>
- <File
- RelativePath=".\ccs_reply_s.c"
- >
- </File>
- <File
- RelativePath="..\..\common\win\ccs_request.idl"
- >
- </File>
- <File
- RelativePath=".\ccs_request_c.c"
- >
- </File>
- <File
- RelativePath=".\ccs_request_proc.c"
- >
- </File>
- <File
- RelativePath=".\ccs_request_s.cpp"
- >
- </File>
- <File
- RelativePath="..\ccs_server.c"
- >
- </File>
- <File
- RelativePath="..\..\common\win\ccutil\ccutils.c"
- >
- </File>
- <File
- RelativePath="..\..\common\win\ccutil\init.cxx"
- >
- </File>
- <File
- RelativePath="..\..\common\win\ccutil\secure.cxx"
- >
- </File>
- <File
- RelativePath="..\..\common\win\ccutil\util.cxx"
- >
- </File>
- <File
- RelativePath="..\..\common\win\win-utils.c"
- >
- </File>
- <File
- RelativePath=".\WorkItem.cpp"
- >
- </File>
- <File
- RelativePath=".\WorkQueue.cpp"
- >
- </File>
- </Filter>
- <File
- RelativePath="..\..\common\win\ccs_reply.Acf"
- >
- </File>
- </Files>
- <Globals>
- </Globals>
-</VisualStudioProject>
+<?xml version="1.0" encoding="UTF-8"?> +<VisualStudioProject + ProjectType="Visual C++" + Version="8.00" + Name="Server" + ProjectGUID="{114DCD80-6D13-4AAA-9510-B51CE6D94C1C}" + RootNamespace="Server" + Keyword="MakeFileProj" + > + <Platforms> + <Platform + Name="Win32" + /> + </Platforms> + <ToolFiles> + </ToolFiles> + <Configurations> + <Configuration + Name="Debug|Win32" + OutputDirectory="Debug" + IntermediateDirectory="Debug" + ConfigurationType="0" + > + <Tool + Name="VCNMakeTool" + BuildCommandLine="nmake" + ReBuildCommandLine="nmake" + CleanCommandLine="nmake clean" + Output="" + PreprocessorDefinitions="WIN32;_DEBUG;" + IncludeSearchPath="" + ForcedIncludes="" + AssemblySearchPath="" + ForcedUsingAssemblies="" + CompileAsManaged="" + /> + </Configuration> + <Configuration + Name="Release|Win32" + OutputDirectory="Release" + IntermediateDirectory="Release" + ConfigurationType="0" + > + <Tool + Name="VCNMakeTool" + BuildCommandLine="nmake" + ReBuildCommandLine="nmake" + CleanCommandLine="nmake clean" + Output="" + PreprocessorDefinitions="WIN32;NDEBUG;" + IncludeSearchPath="" + ForcedIncludes="" + AssemblySearchPath="" + ForcedUsingAssemblies="" + CompileAsManaged="" + /> + </Configuration> + </Configurations> + <References> + </References> + <Files> + <Filter + Name="Header Files" + Filter="h;hpp;hxx;hm;inl;inc;xsd" + UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}" + > + <File + RelativePath="..\..\common\cci_debugging.h" + > + </File> + <File + RelativePath="..\..\common\cci_os_debugging.h" + > + </File> + <File + RelativePath="..\..\common\cci_stream.h" + > + </File> + <File + RelativePath=".\ccs_reply.h" + > + </File> + <File + RelativePath=".\ccs_request.h" + > + </File> + <File + RelativePath="..\ccs_server.h" + > + </File> + <File + RelativePath="..\..\common\win\ccutil\ccutils.h" + > + </File> + <File + RelativePath="..\..\common\win\ccutil\init.hxx" + > + </File> + <File + RelativePath="..\..\..\include\k5-platform.h" + > + </File> + <File + RelativePath="..\..\common\win\ccutil\secure.hxx" + > + </File> + <File + RelativePath="..\..\common\win\ccutil\util.h" + > + </File> + <File + RelativePath="..\..\common\win\win-utils.h" + > + </File> + <File + RelativePath=".\workitem.h" + > + </File> + <File + RelativePath=".\WorkQueue.h" + > + </File> + </Filter> + <Filter + Name="Resource Files" + Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx" + UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}" + > + </Filter> + <Filter + Name="Source Files" + Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx" + UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}" + > + <File + RelativePath="..\..\common\cci_debugging.c" + > + </File> + <File + RelativePath="..\..\common\win\cci_os_debugging.c" + > + </File> + <File + RelativePath="..\..\common\cci_stream.c" + > + </File> + <File + RelativePath="..\ccs_lock.c" + > + </File> + <File + RelativePath=".\ccs_os_pipe.c" + > + </File> + <File + RelativePath=".\ccs_os_server.cpp" + > + </File> + <File + RelativePath="..\..\common\win\ccs_reply.Idl" + > + </File> + <File + RelativePath=".\ccs_reply_c.c" + > + </File> + <File + RelativePath=".\ccs_reply_s.c" + > + </File> + <File + RelativePath="..\..\common\win\ccs_request.idl" + > + </File> + <File + RelativePath=".\ccs_request_c.c" + > + </File> + <File + RelativePath=".\ccs_request_proc.c" + > + </File> + <File + RelativePath=".\ccs_request_s.cpp" + > + </File> + <File + RelativePath="..\ccs_server.c" + > + </File> + <File + RelativePath="..\..\common\win\ccutil\ccutils.c" + > + </File> + <File + RelativePath="..\..\common\win\ccutil\init.cxx" + > + </File> + <File + RelativePath="..\..\common\win\ccutil\secure.cxx" + > + </File> + <File + RelativePath="..\..\common\win\ccutil\util.cxx" + > + </File> + <File + RelativePath="..\..\common\win\win-utils.c" + > + </File> + <File + RelativePath=".\WorkItem.cpp" + > + </File> + <File + RelativePath=".\WorkQueue.cpp" + > + </File> + </Filter> + <File + RelativePath="..\..\common\win\ccs_reply.Acf" + > + </File> + </Files> + <Globals> + </Globals> +</VisualStudioProject> diff --git a/src/ccapi/server/win/WorkItem.cpp b/src/ccapi/server/win/WorkItem.cpp index 1b1725a8aa..22e209de9f 100644 --- a/src/ccapi/server/win/WorkItem.cpp +++ b/src/ccapi/server/win/WorkItem.cpp @@ -1,126 +1,126 @@ -/*
- * $Header$
- *
- * Copyright 2008 Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
- */
-
-#include <string.h>
-#include "assert.h"
-
-#pragma warning (disable : 4996)
-
-#include "win-utils.h"
-#include "WorkItem.h"
-
-extern "C" {
-#include "cci_debugging.h"
- }
-
-// CountedBuffer makes a copy of the data. Each CountedBuffer must be deleted.
-
-void deleteBuffer(char** buf) {
- if (*buf) {
- delete [](*buf);
- *buf = NULL;
- }
- }
-
-// WorkItem contains a CountedBuffer which must be deleted,
-// so each WorkItem must be deleted.
-WorkItem::WorkItem(k5_ipc_stream buf, WIN_PIPE* pipe, const long type, const long sst)
-: _buf(buf), _rpcmsg(type), _pipe(pipe), _sst(sst) { }
-
-WorkItem::WorkItem(const WorkItem& item) : _buf(NULL), _rpcmsg(0), _pipe(NULL), _sst(0) {
-
- k5_ipc_stream _buf = NULL;
- krb5int_ipc_stream_new(&_buf);
- krb5int_ipc_stream_write(_buf,
- krb5int_ipc_stream_data(item.payload()),
- krb5int_ipc_stream_size(item.payload()) );
- WorkItem(_buf, item._pipe, item._rpcmsg, item._sst);
- }
-
-WorkItem::WorkItem() : _buf(NULL), _rpcmsg(CCMSG_INVALID), _pipe(NULL), _sst(0) { }
-
-WorkItem::~WorkItem() {
- if (_buf) krb5int_ipc_stream_release(_buf);
- if (_pipe) ccs_win_pipe_release(_pipe);
- }
-
-const k5_ipc_stream WorkItem::take_payload() {
- k5_ipc_stream temp = payload();
- _buf = NULL;
- return temp;
- }
-
-WIN_PIPE* WorkItem::take_pipe() {
- WIN_PIPE* temp = pipe();
- _pipe = NULL;
- return temp;
- }
-
-WorkList::WorkList() {
- assert(InitializeCriticalSectionAndSpinCount(&cs, 0x80000400));
- }
-
-WorkList::~WorkList() {
- // Delete any WorkItems in the queue:
- WorkItem* item;
- cci_debug_printf("%s", __FUNCTION__);
- char buf[2048];
- char* pbuf = (char*)buf;
- while (remove(&item)) {
- cci_debug_printf("WorkList::~WorkList() deleting %s", item->print(pbuf));
- delete item;
- }
-
- DeleteCriticalSection(&cs);
- }
-
-char* WorkItem::print(char* buf) {
- sprintf(buf, "WorkItem msg#:%d sst:%ld pipe:<%s>/0x%X", _rpcmsg, _sst,
- ccs_win_pipe_getUuid(_pipe), ccs_win_pipe_getHandle(_pipe));
- return buf;
- }
-
-int WorkList::add(WorkItem* item) {
- EnterCriticalSection(&cs);
- wl.push_front(item);
- LeaveCriticalSection(&cs);
- return 1;
- }
-
-int WorkList::remove(WorkItem** item) {
- bool bEmpty;
-
- bEmpty = wl.empty() & 1;
-
- if (!bEmpty) {
- EnterCriticalSection(&cs);
- *item = wl.back();
- wl.pop_back();
- LeaveCriticalSection(&cs);
- }
-
- return !bEmpty;
- }
+/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include <string.h> +#include "assert.h" + +#pragma warning (disable : 4996) + +#include "win-utils.h" +#include "WorkItem.h" + +extern "C" { +#include "cci_debugging.h" + } + +// CountedBuffer makes a copy of the data. Each CountedBuffer must be deleted. + +void deleteBuffer(char** buf) { + if (*buf) { + delete [](*buf); + *buf = NULL; + } + } + +// WorkItem contains a CountedBuffer which must be deleted, +// so each WorkItem must be deleted. +WorkItem::WorkItem(k5_ipc_stream buf, WIN_PIPE* pipe, const long type, const long sst) +: _buf(buf), _rpcmsg(type), _pipe(pipe), _sst(sst) { } + +WorkItem::WorkItem(const WorkItem& item) : _buf(NULL), _rpcmsg(0), _pipe(NULL), _sst(0) { + + k5_ipc_stream _buf = NULL; + krb5int_ipc_stream_new(&_buf); + krb5int_ipc_stream_write(_buf, + krb5int_ipc_stream_data(item.payload()), + krb5int_ipc_stream_size(item.payload()) ); + WorkItem(_buf, item._pipe, item._rpcmsg, item._sst); + } + +WorkItem::WorkItem() : _buf(NULL), _rpcmsg(CCMSG_INVALID), _pipe(NULL), _sst(0) { } + +WorkItem::~WorkItem() { + if (_buf) krb5int_ipc_stream_release(_buf); + if (_pipe) ccs_win_pipe_release(_pipe); + } + +const k5_ipc_stream WorkItem::take_payload() { + k5_ipc_stream temp = payload(); + _buf = NULL; + return temp; + } + +WIN_PIPE* WorkItem::take_pipe() { + WIN_PIPE* temp = pipe(); + _pipe = NULL; + return temp; + } + +WorkList::WorkList() { + assert(InitializeCriticalSectionAndSpinCount(&cs, 0x80000400)); + } + +WorkList::~WorkList() { + // Delete any WorkItems in the queue: + WorkItem* item; + cci_debug_printf("%s", __FUNCTION__); + char buf[2048]; + char* pbuf = (char*)buf; + while (remove(&item)) { + cci_debug_printf("WorkList::~WorkList() deleting %s", item->print(pbuf)); + delete item; + } + + DeleteCriticalSection(&cs); + } + +char* WorkItem::print(char* buf) { + sprintf(buf, "WorkItem msg#:%d sst:%ld pipe:<%s>/0x%X", _rpcmsg, _sst, + ccs_win_pipe_getUuid(_pipe), ccs_win_pipe_getHandle(_pipe)); + return buf; + } + +int WorkList::add(WorkItem* item) { + EnterCriticalSection(&cs); + wl.push_front(item); + LeaveCriticalSection(&cs); + return 1; + } + +int WorkList::remove(WorkItem** item) { + bool bEmpty; + + bEmpty = wl.empty() & 1; + + if (!bEmpty) { + EnterCriticalSection(&cs); + *item = wl.back(); + wl.pop_back(); + LeaveCriticalSection(&cs); + } + + return !bEmpty; + } diff --git a/src/ccapi/server/win/WorkQueue.cpp b/src/ccapi/server/win/WorkQueue.cpp index f16ad117e4..cc12054a10 100644 --- a/src/ccapi/server/win/WorkQueue.cpp +++ b/src/ccapi/server/win/WorkQueue.cpp @@ -1,61 +1,61 @@ -/*
- * $Header$
- *
- * Copyright 2008 Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
- */
-
-extern "C" {
- #include "cci_debugging.h"
- }
-
-#include "WorkItem.h"
-
-WorkList worklist;
-
-/* C interfaces: */
-EXTERN_C bool worklist_isEmpty() {
- return worklist.isEmpty();
- }
-
-EXTERN_C int worklist_add( const long rpcmsg,
- const ccs_pipe_t pipe,
- const k5_ipc_stream stream,
- const time_t serverStartTime) {
- return worklist.add(new WorkItem(stream, pipe, rpcmsg, serverStartTime) );
- }
-
-EXTERN_C int worklist_remove(long* rpcmsg,
- ccs_pipe_t* pipe,
- k5_ipc_stream* stream,
- time_t* sst) {
- WorkItem* item = NULL;
- cc_int32 err = worklist.remove(&item);
-
- *rpcmsg = item->type();
- *pipe = item->take_pipe();
- *stream = item->take_payload();
- *sst = item->sst();
- delete item;
- return err;
- }
-
+/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +extern "C" { + #include "cci_debugging.h" + } + +#include "WorkItem.h" + +WorkList worklist; + +/* C interfaces: */ +EXTERN_C bool worklist_isEmpty() { + return worklist.isEmpty(); + } + +EXTERN_C int worklist_add( const long rpcmsg, + const ccs_pipe_t pipe, + const k5_ipc_stream stream, + const time_t serverStartTime) { + return worklist.add(new WorkItem(stream, pipe, rpcmsg, serverStartTime) ); + } + +EXTERN_C int worklist_remove(long* rpcmsg, + ccs_pipe_t* pipe, + k5_ipc_stream* stream, + time_t* sst) { + WorkItem* item = NULL; + cc_int32 err = worklist.remove(&item); + + *rpcmsg = item->type(); + *pipe = item->take_pipe(); + *stream = item->take_payload(); + *sst = item->sst(); + delete item; + return err; + } + diff --git a/src/ccapi/server/win/ccs_os_server.cpp b/src/ccapi/server/win/ccs_os_server.cpp index b22fdfa9b9..e0695876d6 100644 --- a/src/ccapi/server/win/ccs_os_server.cpp +++ b/src/ccapi/server/win/ccs_os_server.cpp @@ -1,963 +1,963 @@ -/*
- * $Header$
- *
- * Copyright 2008 Massachusetts Institute of Technology.
- * All Rights Reserved.
- *
- * Export of this software from the United States of America may
- * require a specific license from the United States Government.
- * It is the responsibility of any person or organization contemplating
- * export to obtain such a license before exporting.
- *
- * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and
- * distribute this software and its documentation for any purpose and
- * without fee is hereby granted, provided that the above copyright
- * notice appear in all copies and that both that copyright notice and
- * this permission notice appear in supporting documentation, and that
- * the name of M.I.T. not be used in advertising or publicity pertaining
- * to distribution of the software without specific, written prior
- * permission. Furthermore if you modify this software you must label
- * your software as modified software and not distribute it in such a
- * fashion that it might be confused with the original M.I.T. software.
- * M.I.T. makes no representations about the suitability of
- * this software for any purpose. It is provided "as is" without express
- * or implied warranty.
- */
-
-#include "process.h"
-#include "windows.h"
-
-extern "C" {
-#include "ccs_common.h"
-#include "ccs_os_notify.h"
-#include "ccs_os_server.h"
-#include "ccs_reply.h"
-#include "ccs_request.h"
-#include "win-utils.h"
-#include "ccutils.h"
- }
-
-#include "WorkQueue.h"
-#include "util.h"
-#include "opts.hxx"
-#include "init.hxx"
-
-#pragma warning (disable : 4996)
-
-BOOL bListen = TRUE; /* Why aren't bool and true defined? */
-const char* sessID = NULL; /* The logon session we are running on behalf of. */
-time_t _sst = 0;
-unsigned char* pszNetworkAddress = NULL;
-unsigned char* pszStringBinding = NULL;
-BOOL bRpcHandleInited = FALSE;
-_RPC_ASYNC_STATE* rpcState = NULL;
-
-/* Thread procedures can take only one void* argument. We put all the args we want
- to pass into this struct and then pass a pointer to the struct: */
-struct RpcRcvArgs {
- char* networkAddress;
- unsigned char* protocolSequence;
- unsigned char* sessID; /* Used for this server's endpoint */
- unsigned char* uuid; /* Used for client's UUID */
- ParseOpts::Opts* opts;
- RPC_STATUS status;
- } rpcargs = { NULL, /* pszNetworkAddress */
- (unsigned char*)"ncalrpc", /* pszProtocolSequence */
- NULL, /* sessID placeholder */
- NULL, /* uuid placeholder */
- NULL }; /* Opts placeholder */
-
-/* Command line format:
- argv[0] Program name
- argv[1] session ID to use
- argv[2] "D" Debug: go into infinite loop in ccs_os_server_initialize so process
- can be attached in debugger.
- Any other value: continue
- */
-#define N_FIXED_ARGS 3
-#define SERVER_REPLY_RPC_HANDLE ccs_reply_IfHandle
-
-/* Forward declarations: */
-void receiveLoop(void* rpcargs);
-void connectionListener(void* rpcargs);
-void Usage(const char* argv0);
-void printError(TCHAR* msg);
-void setMySST() {_sst = time(&_sst);}
-time_t getMySST() {return _sst;}
-RPC_STATUS send_connection_reply(ccs_pipe_t in_pipe);
-void RPC_ENTRY clientListener( _RPC_ASYNC_STATE*,
- void* Context,
- RPC_ASYNC_EVENT Event);
-RPC_STATUS RPC_ENTRY sec_callback( IN RPC_IF_ID *Interface,
- IN void *Context);
-RPC_STATUS send_init(char* clientUUID);
-//DWORD alloc_name(LPSTR* pname, LPSTR postfix);
-
-
-/* The layout of the rest of this module:
-
- The four entrypoints defined in ccs_os_server.h:
- ccs_os_server_initialize
- cc_int32 ccs_os_server_cleanup
- cc_int32 ccs_os_server_listen_loop
- cc_int32 ccs_os_server_send_reply
-
- Other routines needed by those four.
- */
-
-/* ------------------------------------------------------------------------ */
-
-cc_int32 ccs_os_server_initialize (int argc, const char *argv[]) {
- cc_int32 err = 0;
- ParseOpts::Opts opts = { 0 };
- ParseOpts PO;
- BOOL bAdjustedShutdown = FALSE;
- HMODULE hKernel32 = GetModuleHandle("kernel32");
-
- if (!err) {
- sessID = argv[1];
- setMySST();
-
- opts.cMinCalls = 1;
- opts.cMaxCalls = 20;
- opts.fDontWait = TRUE;
-
-#ifdef CCAPI_TEST_OPTIONS
- PO.SetValidOpts("kemnfubc");
-#else
- PO.SetValidOpts("kc");
-#endif
-
- PO.Parse(opts, argc, (char**)argv);
-
-// while(*argv[2] == 'D') {} /* Hang here to attach process with debugger. */
-
- if (hKernel32) {
- typedef BOOL (WINAPI *FP_SetProcessShutdownParameters)(DWORD, DWORD);
- FP_SetProcessShutdownParameters pSetProcessShutdownParameters =
- (FP_SetProcessShutdownParameters)
- GetProcAddress(hKernel32, "SetProcessShutdownParameters");
- if (pSetProcessShutdownParameters) {
- bAdjustedShutdown = pSetProcessShutdownParameters(100, 0);
- }
- }
- cci_debug_printf("%s Shutdown Parameters",
- bAdjustedShutdown ? "Adjusted" : "Did not adjust");
-
- err = Init::Initialize();
- }
-
-// if (!err) {
-// if (opts.bShutdown) {
-// status = shutdown_server(opts.pszEndpoint);
-// }
-// }
-// else {
-// status = startup_server(opts);
-// }
-
- if (err) {
- Init::Cleanup();
- fprintf( stderr, "An error occured while %s the server (%u)\n",
- opts.bShutdown ? "shutting down" : "starting/running",
- err);
- exit(cci_check_error (err));
- }
-
- return cci_check_error (err);
- }
-
-/* ------------------------------------------------------------------------ */
-
-cc_int32 ccs_os_server_cleanup (int argc, const char *argv[]) {
- cc_int32 err = 0;
-
- cci_debug_printf("%s for user <%s> shutting down.", argv[0], argv[1]);
-
- return cci_check_error (err);
- }
-
-/* ------------------------------------------------------------------------ */
-
-/* This function takes work items off the work queue and executes them.
- * This is the one and only place where the multi-threaded Windows code
- * calls into the single-threaded common code.
- *
- * The actual 'listening' for requests from clients happens after receiveloop
- * establishes the RPC endpoint the clients will connect to and the RPC procedures
- * put the work items into the work queue.
- */
-cc_int32 ccs_os_server_listen_loop (int argc, const char *argv[]) {
- cc_int32 err = 0;
- uintptr_t threadStatus;
- unsigned int loopCounter = 0;
-
- ParseOpts::Opts opts = { 0 };
- ParseOpts PO;
-
- opts.cMinCalls = 1;
- opts.cMaxCalls = 20;
- opts.fDontWait = TRUE;
-
-#ifdef CCAPI_TEST_OPTIONS
- PO.SetValidOpts("kemnfubc");
-#else
- PO.SetValidOpts("kc");
-#endif
- PO.Parse(opts, argc, (char**)argv);
-
-
- //++ debug stuff
- #define INFO_BUFFER_SIZE 32767
- TCHAR infoBuf[INFO_BUFFER_SIZE];
- DWORD bufCharCount = INFO_BUFFER_SIZE;
- // Get and display the user name.
- bufCharCount = INFO_BUFFER_SIZE;
- if( !GetUserName( infoBuf, &bufCharCount ) ) printError( TEXT("GetUserName") );
- //--
-
- /* Sending the reply from within the request RPC handler doesn't seem to work.
- So we listen for requests in a separate thread and put the requests in a
- queue. */
- rpcargs.sessID = (unsigned char*)sessID;
- rpcargs.opts = &opts;
- threadStatus = _beginthread(receiveLoop, 0, (void*)&rpcargs);
-
- /* We handle the queue entries here. Work loop: */
- while (TRUE) {
- loopCounter++;
- if (worklist_isEmpty() & 1) {
- SleepEx(1000, TRUE);
- }
- else if (TRUE) { // Take next WorkItem from the queue:
- k5_ipc_stream buf = NULL;
- long rpcmsg = CCMSG_INVALID;
- time_t serverStartTime = 0xDEADDEAD;
- RPC_STATUS status = 0;
- char* uuid = NULL;
- k5_ipc_stream stream = NULL;
- ccs_pipe_t pipe = NULL;
- ccs_pipe_t pipe2 = NULL;
-
- if (worklist_remove(&rpcmsg, &pipe, &buf, &serverStartTime)) {
- uuid = ccs_win_pipe_getUuid(pipe);
-#if 0
- cci_debug_printf("%s: processing WorkItem msg:%ld pipeUUID:<%s> pipeHandle:0x%X SST:%ld",
- __FUNCTION__, rpcmsg, uuid, ccs_win_pipe_getHandle(pipe), serverStartTime);
-#endif
- if (serverStartTime <= getMySST()) {
- switch (rpcmsg) {
- case CCMSG_CONNECT: {
- cci_debug_printf(" Processing CONNECT");
- rpcargs.uuid = (unsigned char*)uuid;
-
- // Even if a disconnect message is received before this code finishes,
- // it won't be dequeued and processed until after this code finishes.
- // So we can add the client after starting the connection listener.
- connectionListener((void*)&rpcargs);
- status = rpcargs.status;
-
- if (!status) {
- status = ccs_server_add_client(pipe);
- }
- if (!status) {status = send_connection_reply(pipe);}
- break;
- }
- case CCMSG_DISCONNECT: {
- cci_debug_printf(" Processing DISCONNECT");
- if (!status) {
- status = ccs_server_remove_client(pipe);
- }
- break;
- }
- case CCMSG_REQUEST:
- cci_debug_printf(" Processing REQUEST");
- ccs_pipe_copy(&pipe2, pipe);
- // Dispatch message here, setting both pipes to the client UUID:
- err = ccs_server_handle_request (pipe, pipe2, buf);
- break;
- case CCMSG_PING:
- cci_debug_printf(" Processing PING");
- err = krb5int_ipc_stream_new (&stream);
- err = krb5int_ipc_stream_write(stream, "This is a test of the emergency broadcasting system", 52);
- err = ccs_os_server_send_reply(pipe, stream);
- break;
- default:
- cci_debug_printf("Huh? Received invalid message type %ld from UUID:<%s>",
- rpcmsg, uuid);
- break;
- }
- if (buf) krb5int_ipc_stream_release(buf);
- /* Don't free uuid, which was allocated here. A pointer to it is in the
- rpcargs struct which was passed to connectionListener which will be
- received by ccapi_listen when the client exits. ccapi_listen needs
- the uuid to know which client to disconnect.
- */
- }
- // Server's start time is different from what the client thinks.
- // That means the server has rebooted since the client connected.
- else {
- cci_debug_printf("Whoops! Server has rebooted since client established connection.");
- }
- }
- else {cci_debug_printf("Huh? Queue not empty but no item to remove.");}
- }
- }
-
- return cci_check_error (err);
- }
-
-/* ------------------------------------------------------------------------ */
-
-cc_int32 ccs_os_server_send_reply (ccs_pipe_t in_pipe,
- k5_ipc_stream in_reply_stream) {
-
- /* ccs_pipe_t in_reply_pipe is a char* reply endpoint.
- k5_ipc_stream in_reply_stream is the data to be sent.
- */
-
- cc_int32 err = 0;
- char* uuid = ccs_win_pipe_getUuid(in_pipe);
- HANDLE h = ccs_win_pipe_getHandle(in_pipe);
-
- if (!err) {
- err = send_init(uuid); // Sets RPC handle to be used.
- }
-
- if (!err) {
- RpcTryExcept {
- long status;
- ccs_rpc_request_reply( // make call with user message
- CCMSG_REQUEST_REPLY, /* Message type */
- (unsigned char*)&h, /* client's tspdata* */
- (unsigned char*)uuid,
- getMySST(),
- krb5int_ipc_stream_size(in_reply_stream), /* Length of buffer */
- (const unsigned char*)krb5int_ipc_stream_data(in_reply_stream), /* Data buffer */
- &status ); /* Return code */
- }
- RpcExcept(1) {
- cci_check_error(RpcExceptionCode());
- }
- RpcEndExcept
- }
-
- /* The calls to the remote procedures are complete. */
- /* Free whatever we allocated: */
- err = RpcBindingFree(&SERVER_REPLY_RPC_HANDLE);
-
- return cci_check_error (err);
- }
-
-
-/* Windows-specific routines: */
-
-void Usage(const char* argv0) {
- printf("Usage:\n");
- printf("%s [m maxcalls] [n mincalls] [f dontwait] [h|?]]\n", argv0);
- printf(" CCAPI server process.\n");
- printf(" h|? whow usage message. <\n");
- }
-
-/* ------------------------------------------------------------------------ */
-/* The receive thread repeatedly issues RpcServerListen.
- When a message arrives, it is handled in the RPC procedure.
- */
-void receiveLoop(void* rpcargs) {
-
- struct RpcRcvArgs* rcvargs = (struct RpcRcvArgs*)rpcargs;
- RPC_STATUS status = FALSE;
- unsigned char* pszSecurity = NULL;
- LPSTR endpoint = NULL;
- LPSTR event_name = NULL;
- PSECURITY_DESCRIPTOR psd = NULL;
- HANDLE hEvent = 0;
- Init::InitInfo info;
-
- cci_debug_printf("THREAD BEGIN: %s", __FUNCTION__);
-
- status = Init::Info(info);
-
- /* Build complete RPC endpoint using previous CCAPI implementation: */
- if (!status) {
- if (!rcvargs->opts->pszEndpoint) {
- if (!status) {
- status = alloc_name(&endpoint, "ep", isNT());
- }
-
- if (!status) {
- status = alloc_name(&event_name, "startup", isNT());
- }
-
- if (!status) {
- hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, event_name);
- // We ignore any error opening the event because we do not know who started us.
- // [Comment paraphrased from previous implementation, whence it was copied.]
- }
- }
- else {
- endpoint = rcvargs->opts->pszEndpoint;
- }
- }
-
- cci_debug_printf("%s Registering endpoint %s", __FUNCTION__, endpoint);
-
- if (!status && isNT()) {
- status = alloc_own_security_descriptor_NT(&psd);
- }
-
- if (!status) {
- status = RpcServerUseProtseqEp(rcvargs->protocolSequence,
- rcvargs->opts->cMaxCalls,
- (RPC_CSTR)endpoint,
- rcvargs->opts->bDontProtect ? 0 : psd); // SD
- }
-
- if (!status) {
- status = RpcServerRegisterAuthInfo(0, // server principal
- RPC_C_AUTHN_WINNT,
- 0,
- 0);
- }
-
- while (bListen && !status) {
- cci_debug_printf("%s is listening ...", __FUNCTION__);
-
- if (!info.isNT) {
- status = RpcServerRegisterIf(ccs_request_ServerIfHandle, // interface
- NULL, // MgrTypeUuid
- NULL); // MgrEpv; null means use default
- }
- else {
- status = info.fRpcServerRegisterIfEx(ccs_request_ServerIfHandle, // interface
- NULL, // MgrTypeUuid
- NULL, // MgrEpv; 0 means default
- RPC_IF_ALLOW_SECURE_ONLY,
- rcvargs->opts->cMaxCalls,
- rcvargs->opts->bSecCallback ?
- (RPC_IF_CALLBACK_FN*)sec_callback : 0 );
- }
-
- if (!status) {
- status = RpcServerListen(rcvargs->opts->cMinCalls,
- rcvargs->opts->cMaxCalls,
- rcvargs->opts->fDontWait);
- }
-
- if (!status) {
- if (rcvargs->opts->fDontWait) {
- if (hEvent) SetEvent(hEvent); // Ignore any error -- SetEvent is an optimization.
- status = RpcMgmtWaitServerListen();
- }
- }
- }
-
- if (status) { // Cleanup in case of errors:
- if (hEvent) CloseHandle(hEvent);
- free_alloc_p(&event_name);
- free_alloc_p(&psd);
- if (endpoint && (endpoint != rcvargs->opts->pszEndpoint))
- free_alloc_p(&endpoint);
- }
-
- _endthread();
- } // End receiveLoop
-
-
-#if 0
-
- return status;
-}
-#endif
-
-
-
-/* ------------------------------------------------------------------------ */
-/* The connection listener thread waits forever for a call to the CCAPI_CLIENT_<UUID>
- endpoint, ccapi_listen function to complete. If the call completes or gets an
- RPC exception, it means the client has disappeared.
-
- A separate connectionListener is started for each client that has connected to the server.
- */
-
-void connectionListener(void* rpcargs) {
-
- struct RpcRcvArgs* rcvargs = (struct RpcRcvArgs*)rpcargs;
- RPC_STATUS status = FALSE;
- char* endpoint;
- unsigned char* pszOptions = NULL;
- unsigned char * pszUuid = NULL;
-
- endpoint = clientEndpoint((char*)rcvargs->uuid);
- rpcState = (RPC_ASYNC_STATE*)malloc(sizeof(RPC_ASYNC_STATE));
- status = RpcAsyncInitializeHandle(rpcState, sizeof(RPC_ASYNC_STATE));
- cci_debug_printf("");
- cci_debug_printf("%s About to LISTEN to <%s>", __FUNCTION__, endpoint);
-
- rpcState->UserInfo = rcvargs->uuid;
- rpcState->NotificationType = RpcNotificationTypeApc;
- rpcState->u.APC.NotificationRoutine = clientListener;
- rpcState->u.APC.hThread = 0;
-
- /* [If in use] Free previous binding: */
- if (bRpcHandleInited) {
- // Free previous binding (could have been used to call ccapi_listen
- // in a different client thread).
- // Don't check result or update status.
- RpcStringFree(&pszStringBinding);
- RpcBindingFree(&SERVER_REPLY_RPC_HANDLE);
- bRpcHandleInited = FALSE;
- }
-
- /* Set up binding to the client's endpoint: */
- if (!status) {
- status = RpcStringBindingCompose(
- pszUuid,
- pszProtocolSequence,
- pszNetworkAddress,
- (RPC_CSTR)endpoint,
- pszOptions,
- &pszStringBinding);
- }
-
- /* Set the binding handle that will be used to bind to the server. */
- if (!status) {
- status = RpcBindingFromStringBinding(pszStringBinding, &SERVER_REPLY_RPC_HANDLE);
- }
- if (!status) {bRpcHandleInited = TRUE;}
-
- RpcTryExcept {
- cci_debug_printf(" Calling remote procedure ccapi_listen");
- ccapi_listen(rpcState, SERVER_REPLY_RPC_HANDLE, CCMSG_LISTEN, &status);
- /* Asynchronous call will return immediately. */
- }
- RpcExcept(1) {
- status = cci_check_error(RpcExceptionCode());
- }
- RpcEndExcept
-
- rcvargs->status = status;
- } // End connectionListener
-
-
-void RPC_ENTRY clientListener(
- _RPC_ASYNC_STATE* pAsync,
- void* Context,
- RPC_ASYNC_EVENT Event
- ) {
-
- ccs_pipe_t pipe = ccs_win_pipe_new((char*)pAsync->UserInfo, NULL);
-
- cci_debug_printf("%s(0x%X, ...) async routine for <0x%X:%s>!",
- __FUNCTION__, pAsync, pAsync->UserInfo, pAsync->UserInfo);
-
- worklist_add( CCMSG_DISCONNECT,
- pipe,
- NULL, /* No payload with connect request */
- (const time_t)0 ); /* No server session number with connect request */
- }
-
-
-void printError( TCHAR* msg ) {
- DWORD eNum;
- TCHAR sysMsg[256];
- TCHAR* p;
-
- eNum = GetLastError( );
- FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM |
- FORMAT_MESSAGE_IGNORE_INSERTS,
- NULL, eNum,
- MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
- sysMsg, 256, NULL );
-
- // Trim the end of the line and terminate it with a null
- p = sysMsg;
- while( ( *p > 31 ) || ( *p == 9 ) )
- ++p;
- do { *p-- = 0; } while( ( p >= sysMsg ) &&
- ( ( *p == '.' ) || ( *p < 33 ) ) );
-
- // Display the message
- cci_debug_printf("%s failed with error %d (%s)", msg, eNum, sysMsg);
- }
-
-
-RPC_STATUS send_init(char* clientUUID) {
- RPC_STATUS status;
- unsigned char * pszUuid = NULL;
- unsigned char * pszOptions = NULL;
-
- /* Use a convenience function to concatenate the elements of */
- /* the string binding into the proper sequence. */
- status = RpcStringBindingCompose(pszUuid,
- pszProtocolSequence,
- pszNetworkAddress,
- (unsigned char*)clientEndpoint(clientUUID),
- pszOptions,
- &pszStringBinding);
- if (status) {return (status);}
-
- /* Set the binding handle that will be used to bind to the RPC server [the 'client']. */
- status = RpcBindingFromStringBinding(pszStringBinding, &SERVER_REPLY_RPC_HANDLE);
- return (status);
- }
-
-RPC_STATUS send_finish() {
- RPC_STATUS status;
- /* Can't shut down client -- it runs listen function which */
- /* server uses to detect the client going away. */
-
- /* The calls to the remote procedures are complete. */
- /* Free the string and the binding handle */
- status = RpcStringFree(&pszStringBinding); // remote calls done; unbind
- if (status) {return (status);}
-
- status = RpcBindingFree(&SERVER_REPLY_RPC_HANDLE); // remote calls done; unbind
-
- return (status);
- }
-
-RPC_STATUS send_connection_reply(ccs_pipe_t in_pipe) {
- char* uuid = ccs_win_pipe_getUuid (in_pipe);
- HANDLE h = ccs_win_pipe_getHandle(in_pipe);
- RPC_STATUS status = send_init(uuid);
-
- RpcTryExcept {
- ccs_rpc_connect_reply( // make call with user message
- CCMSG_CONNECT_REPLY, /* Message type */
- (unsigned char*)&h, /* client's tspdata* */
- (unsigned char*)uuid,
- getMySST(), /* Server's session number = it's start time */
- &status ); /* Return code */
- }
- RpcExcept(1) {
- cci_check_error(RpcExceptionCode());
- }
- RpcEndExcept
-
- status = send_finish();
- return (status);
- }
-
-#if 0
-DWORD alloc_name(LPSTR* pname, LPSTR postfix) {
- DWORD len = strlen(sessID) + 1 + strlen(postfix) + 1;
-
- *pname = (LPSTR)malloc(len);
- if (!*pname) return GetLastError();
- _snprintf(*pname, len, "%s.%s", sessID, postfix);
- return 0;
- }
-#endif
-
-RPC_STATUS GetPeerName( RPC_BINDING_HANDLE hClient,
- LPTSTR pszClientName,
- int iMaxLen) {
- RPC_STATUS Status = RPC_S_OK;
- RPC_BINDING_HANDLE hServer = NULL;
- PTBYTE pszStringBinding = NULL;
- PTBYTE pszClientNetAddr = NULL;
- PTBYTE pszProtSequence = NULL;
-
- memset(pszClientName, 0, iMaxLen * sizeof(TCHAR));
-
- __try {
- // Create a partially bound server handle from the client handle.
- Status = RpcBindingServerFromClient (hClient, &hServer);
- if (Status != RPC_S_OK) __leave;
-
- // Get the partially bound server string binding and parse it.
- Status = RpcBindingToStringBinding (hServer,
- &pszStringBinding);
- if (Status != RPC_S_OK) __leave;
-
- // String binding only contains protocol sequence and client
- // address, and is not currently implemented for named pipes.
- Status = RpcStringBindingParse (pszStringBinding, NULL,
- &pszProtSequence, &pszClientNetAddr,
- NULL, NULL);
- if (Status != RPC_S_OK)
- __leave;
- int iLen = lstrlen(pszClientName) + 1;
- if (iMaxLen < iLen)
- Status = RPC_S_BUFFER_TOO_SMALL;
- lstrcpyn(pszClientName, (LPCTSTR)pszClientNetAddr, iMaxLen);
- }
- __finally {
- if (pszProtSequence)
- RpcStringFree (&pszProtSequence);
-
- if (pszClientNetAddr)
- RpcStringFree (&pszClientNetAddr);
-
- if (pszStringBinding)
- RpcStringFree (&pszStringBinding);
-
- if (hServer)
- RpcBindingFree (&hServer);
- }
- return Status;
-}
-
-struct client_auth_info {
- RPC_AUTHZ_HANDLE authz_handle;
- unsigned char* server_principal; // need to RpcFreeString this
- ULONG authn_level;
- ULONG authn_svc;
- ULONG authz_svc;
-};
-
-RPC_STATUS
-GetClientId(
- RPC_BINDING_HANDLE hClient,
- char* client_id,
- int max_len,
- client_auth_info* info
- )
-{
- RPC_AUTHZ_HANDLE authz_handle = 0;
- unsigned char* server_principal = 0;
- ULONG authn_level = 0;
- ULONG authn_svc = 0;
- ULONG authz_svc = 0;
- RPC_STATUS status = 0;
-
- memset(client_id, 0, max_len);
-
- if (info) {
- memset(info, 0, sizeof(client_auth_info));
- }
-
- status = RpcBindingInqAuthClient(hClient, &authz_handle,
- info ? &server_principal : 0,
- &authn_level, &authn_svc, &authz_svc);
- if (status == RPC_S_OK)
- {
- if (info) {
- info->server_principal = server_principal;
- info->authz_handle = authz_handle;
- info->authn_level = authn_level;
- info->authn_svc = authn_svc;
- info->authz_svc = authz_svc;
- }
-
- if (authn_svc == RPC_C_AUTHN_WINNT) {
- WCHAR* username = (WCHAR*)authz_handle;
- int len = lstrlenW(username) + 1;
- if (max_len < len)
- status = RPC_S_BUFFER_TOO_SMALL;
- _snprintf(client_id, max_len, "%S", username);
- } else {
- status = RPC_S_UNKNOWN_AUTHN_SERVICE;
- }
- }
- return status;
-}
-
-char*
-rpc_error_to_string(
- RPC_STATUS status
- )
-{
- switch(status) {
- case RPC_S_OK:
- return "OK";
- case RPC_S_INVALID_BINDING:
- return "Invalid binding";
- case RPC_S_WRONG_KIND_OF_BINDING:
- return "Wrong binding";
- case RPC_S_BINDING_HAS_NO_AUTH:
- RpcRaiseException(RPC_S_BINDING_HAS_NO_AUTH);
- return "Binding has no auth";
- default:
- return "BUG: I am confused";
- }
-}
-
-void
-print_client_info(
- RPC_STATUS peer_status,
- const char* peer_name,
- RPC_STATUS client_status,
- const char* client_id,
- client_auth_info* info
- )
-{
- if (peer_status == RPC_S_OK || peer_status == RPC_S_BUFFER_TOO_SMALL) {
- cci_debug_printf("%s Peer Name is \"%s\"", __FUNCTION__, peer_name);
- } else {
- cci_debug_printf("%s Error %u getting Peer Name (%s)",
- __FUNCTION__, peer_status, rpc_error_to_string(peer_status));
- }
-
- if (client_status == RPC_S_OK || client_status == RPC_S_BUFFER_TOO_SMALL) {
- if (info) {
- cci_debug_printf("%s Client Auth Info"
- "\tServer Principal: %s\n"
- "\tAuthentication Level: %d\n"
- "\tAuthentication Service: %d\n"
- "\tAuthorization Service: %d\n",
- __FUNCTION__,
- info->server_principal,
- info->authn_level,
- info->authn_svc,
- info->authz_svc);
- }
- cci_debug_printf("%s Client ID is \"%s\"", __FUNCTION__, client_id);
- } else {
- cci_debug_printf("%s Error getting Client Info (%u = %s)",
- __FUNCTION__, client_status, rpc_error_to_string(client_status));
- }
-}
-
-DWORD sid_check() {
- DWORD status = 0;
- HANDLE hToken_c = 0;
- HANDLE hToken_s = 0;
- PTOKEN_USER ptu_c = 0;
- PTOKEN_USER ptu_s = 0;
- DWORD len = 0;
- BOOL bImpersonate = FALSE;
-
- // Note GetUserName will fail while impersonating at identify
- // level. The workaround is to impersonate, OpenThreadToken,
- // revert, call GetTokenInformation, and finally, call
- // LookupAccountSid.
-
- // XXX - Note: This workaround does not appear to work.
- // OpenThreadToken fails with error 1346: "Either a requid
- // impersonation level was not provided or the provided
- // impersonation level is invalid".
-
- status = RpcImpersonateClient(0);
-
- if (!status) {
- bImpersonate = TRUE;
- if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken_c))
- status = GetLastError();
- }
-
- if (!status) {
- status = RpcRevertToSelf();
- }
-
- if (!status) {
- bImpersonate = FALSE;
-
- len = 0;
- GetTokenInformation(hToken_c, TokenUser, ptu_c, 0, &len);
- if (len == 0) status = 1;
- }
-
- if (!status) {
- if (!(ptu_c = (PTOKEN_USER)LocalAlloc(0, len)))
- status = GetLastError();
- }
-
- if (!status) {
- if (!GetTokenInformation(hToken_c, TokenUser, ptu_c, len, &len))
- status = GetLastError();
- }
-
- if (!status) {
- if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken_s))
- status = GetLastError();
- }
-
- if (!status) {
- len = 0;
- GetTokenInformation(hToken_s, TokenUser, ptu_s, 0, &len);
- if (len == 0) status = GetLastError();
- }
-
- if (!status) {
- if (!(ptu_s = (PTOKEN_USER)LocalAlloc(0, len)))
- status = GetLastError();
- }
-
- if (!status) {
- if (!GetTokenInformation(hToken_s, TokenUser, ptu_s, len, &len))
- status = GetLastError();
- }
-
- if (!EqualSid(ptu_s->User.Sid, ptu_c->User.Sid))
- status = RPC_S_ACCESS_DENIED;
-
-/* Cleanup: */
- if (!hToken_c && !bImpersonate)
- cci_debug_printf("%s Cannot impersonate (%u)", __FUNCTION__, status);
- else if (!hToken_c)
- cci_debug_printf("%s Failed to open client token (%u)", __FUNCTION__, status);
- else if (bImpersonate)
- cci_debug_printf("%s Failed to revert (%u)", __FUNCTION__, status);
- else if (!ptu_c)
- cci_debug_printf("%s Failed to get client token user info (%u)",
- __FUNCTION__, status);
- else if (!hToken_s)
- cci_debug_printf("%s Failed to open server token (%u)", __FUNCTION__, status);
- else if (!ptu_s)
- cci_debug_printf("%s Failed to get server token user info (%u)",
- __FUNCTION__, status);
- else if (status == RPC_S_ACCESS_DENIED)
- cci_debug_printf("%s SID **does not** match!", __FUNCTION__);
- else if (status == RPC_S_OK)
- cci_debug_printf("%s SID matches!", __FUNCTION__);
- else
- if (status) {
- cci_debug_printf("%s unrecognized error %u", __FUNCTION__, status);
- abort();
- }
-
- if (bImpersonate) RpcRevertToSelf();
- if (hToken_c && hToken_c != INVALID_HANDLE_VALUE)
- CloseHandle(hToken_c);
- if (ptu_c) LocalFree(ptu_c);
- if (hToken_s && hToken_s != INVALID_HANDLE_VALUE)
- CloseHandle(hToken_s);
- if (ptu_s) LocalFree(ptu_s);
- if (status) cci_debug_printf("%s returning %u", __FUNCTION__, status);
- return status;
- }
-
-RPC_STATUS RPC_ENTRY sec_callback( IN RPC_IF_ID *Interface,
- IN void *Context) {
- char peer_name[1024];
- char client_name[1024];
- RPC_STATUS peer_status;
- RPC_STATUS client_status;
-
- cci_debug_printf("%s", __FUNCTION__);
- peer_status = GetPeerName(Context, peer_name, sizeof(peer_name));
- client_status = GetClientId(Context, client_name, sizeof(client_name), 0);
- print_client_info(peer_status, peer_name, client_status, client_name, 0);
- DWORD sid_status = sid_check();
- cci_debug_printf("%s returning (%u)", __FUNCTION__, sid_status);
- return sid_status;
- }
-
-
-
-/*********************************************************************/
-/* MIDL allocate and free */
-/*********************************************************************/
-
-extern "C" void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) {
- return(malloc(len));
- }
-
-extern "C" void __RPC_USER midl_user_free(void __RPC_FAR * ptr) {
- free(ptr);
- }
-
-/* stubs */
-extern "C" cc_int32
-ccs_os_notify_cache_collection_changed (ccs_cache_collection_t cc)
-{
- return 0;
-}
-
-extern "C" cc_int32
-ccs_os_notify_ccache_changed (ccs_cache_collection_t cc, const char *name)
-{
- return 0;
-}
+/* + * $Header$ + * + * Copyright 2008 Massachusetts Institute of Technology. + * All Rights Reserved. + * + * Export of this software from the United States of America may + * require a specific license from the United States Government. + * It is the responsibility of any person or organization contemplating + * export to obtain such a license before exporting. + * + * WITHIN THAT CONSTRAINT, permission to use, copy, modify, and + * distribute this software and its documentation for any purpose and + * without fee is hereby granted, provided that the above copyright + * notice appear in all copies and that both that copyright notice and + * this permission notice appear in supporting documentation, and that + * the name of M.I.T. not be used in advertising or publicity pertaining + * to distribution of the software without specific, written prior + * permission. Furthermore if you modify this software you must label + * your software as modified software and not distribute it in such a + * fashion that it might be confused with the original M.I.T. software. + * M.I.T. makes no representations about the suitability of + * this software for any purpose. It is provided "as is" without express + * or implied warranty. + */ + +#include "process.h" +#include "windows.h" + +extern "C" { +#include "ccs_common.h" +#include "ccs_os_notify.h" +#include "ccs_os_server.h" +#include "ccs_reply.h" +#include "ccs_request.h" +#include "win-utils.h" +#include "ccutils.h" + } + +#include "WorkQueue.h" +#include "util.h" +#include "opts.hxx" +#include "init.hxx" + +#pragma warning (disable : 4996) + +BOOL bListen = TRUE; /* Why aren't bool and true defined? */ +const char* sessID = NULL; /* The logon session we are running on behalf of. */ +time_t _sst = 0; +unsigned char* pszNetworkAddress = NULL; +unsigned char* pszStringBinding = NULL; +BOOL bRpcHandleInited = FALSE; +_RPC_ASYNC_STATE* rpcState = NULL; + +/* Thread procedures can take only one void* argument. We put all the args we want + to pass into this struct and then pass a pointer to the struct: */ +struct RpcRcvArgs { + char* networkAddress; + unsigned char* protocolSequence; + unsigned char* sessID; /* Used for this server's endpoint */ + unsigned char* uuid; /* Used for client's UUID */ + ParseOpts::Opts* opts; + RPC_STATUS status; + } rpcargs = { NULL, /* pszNetworkAddress */ + (unsigned char*)"ncalrpc", /* pszProtocolSequence */ + NULL, /* sessID placeholder */ + NULL, /* uuid placeholder */ + NULL }; /* Opts placeholder */ + +/* Command line format: + argv[0] Program name + argv[1] session ID to use + argv[2] "D" Debug: go into infinite loop in ccs_os_server_initialize so process + can be attached in debugger. + Any other value: continue + */ +#define N_FIXED_ARGS 3 +#define SERVER_REPLY_RPC_HANDLE ccs_reply_IfHandle + +/* Forward declarations: */ +void receiveLoop(void* rpcargs); +void connectionListener(void* rpcargs); +void Usage(const char* argv0); +void printError(TCHAR* msg); +void setMySST() {_sst = time(&_sst);} +time_t getMySST() {return _sst;} +RPC_STATUS send_connection_reply(ccs_pipe_t in_pipe); +void RPC_ENTRY clientListener( _RPC_ASYNC_STATE*, + void* Context, + RPC_ASYNC_EVENT Event); +RPC_STATUS RPC_ENTRY sec_callback( IN RPC_IF_ID *Interface, + IN void *Context); +RPC_STATUS send_init(char* clientUUID); +//DWORD alloc_name(LPSTR* pname, LPSTR postfix); + + +/* The layout of the rest of this module: + + The four entrypoints defined in ccs_os_server.h: + ccs_os_server_initialize + cc_int32 ccs_os_server_cleanup + cc_int32 ccs_os_server_listen_loop + cc_int32 ccs_os_server_send_reply + + Other routines needed by those four. + */ + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_server_initialize (int argc, const char *argv[]) { + cc_int32 err = 0; + ParseOpts::Opts opts = { 0 }; + ParseOpts PO; + BOOL bAdjustedShutdown = FALSE; + HMODULE hKernel32 = GetModuleHandle("kernel32"); + + if (!err) { + sessID = argv[1]; + setMySST(); + + opts.cMinCalls = 1; + opts.cMaxCalls = 20; + opts.fDontWait = TRUE; + +#ifdef CCAPI_TEST_OPTIONS + PO.SetValidOpts("kemnfubc"); +#else + PO.SetValidOpts("kc"); +#endif + + PO.Parse(opts, argc, (char**)argv); + +// while(*argv[2] == 'D') {} /* Hang here to attach process with debugger. */ + + if (hKernel32) { + typedef BOOL (WINAPI *FP_SetProcessShutdownParameters)(DWORD, DWORD); + FP_SetProcessShutdownParameters pSetProcessShutdownParameters = + (FP_SetProcessShutdownParameters) + GetProcAddress(hKernel32, "SetProcessShutdownParameters"); + if (pSetProcessShutdownParameters) { + bAdjustedShutdown = pSetProcessShutdownParameters(100, 0); + } + } + cci_debug_printf("%s Shutdown Parameters", + bAdjustedShutdown ? "Adjusted" : "Did not adjust"); + + err = Init::Initialize(); + } + +// if (!err) { +// if (opts.bShutdown) { +// status = shutdown_server(opts.pszEndpoint); +// } +// } +// else { +// status = startup_server(opts); +// } + + if (err) { + Init::Cleanup(); + fprintf( stderr, "An error occured while %s the server (%u)\n", + opts.bShutdown ? "shutting down" : "starting/running", + err); + exit(cci_check_error (err)); + } + + return cci_check_error (err); + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_server_cleanup (int argc, const char *argv[]) { + cc_int32 err = 0; + + cci_debug_printf("%s for user <%s> shutting down.", argv[0], argv[1]); + + return cci_check_error (err); + } + +/* ------------------------------------------------------------------------ */ + +/* This function takes work items off the work queue and executes them. + * This is the one and only place where the multi-threaded Windows code + * calls into the single-threaded common code. + * + * The actual 'listening' for requests from clients happens after receiveloop + * establishes the RPC endpoint the clients will connect to and the RPC procedures + * put the work items into the work queue. + */ +cc_int32 ccs_os_server_listen_loop (int argc, const char *argv[]) { + cc_int32 err = 0; + uintptr_t threadStatus; + unsigned int loopCounter = 0; + + ParseOpts::Opts opts = { 0 }; + ParseOpts PO; + + opts.cMinCalls = 1; + opts.cMaxCalls = 20; + opts.fDontWait = TRUE; + +#ifdef CCAPI_TEST_OPTIONS + PO.SetValidOpts("kemnfubc"); +#else + PO.SetValidOpts("kc"); +#endif + PO.Parse(opts, argc, (char**)argv); + + + //++ debug stuff + #define INFO_BUFFER_SIZE 32767 + TCHAR infoBuf[INFO_BUFFER_SIZE]; + DWORD bufCharCount = INFO_BUFFER_SIZE; + // Get and display the user name. + bufCharCount = INFO_BUFFER_SIZE; + if( !GetUserName( infoBuf, &bufCharCount ) ) printError( TEXT("GetUserName") ); + //-- + + /* Sending the reply from within the request RPC handler doesn't seem to work. + So we listen for requests in a separate thread and put the requests in a + queue. */ + rpcargs.sessID = (unsigned char*)sessID; + rpcargs.opts = &opts; + threadStatus = _beginthread(receiveLoop, 0, (void*)&rpcargs); + + /* We handle the queue entries here. Work loop: */ + while (TRUE) { + loopCounter++; + if (worklist_isEmpty() & 1) { + SleepEx(1000, TRUE); + } + else if (TRUE) { // Take next WorkItem from the queue: + k5_ipc_stream buf = NULL; + long rpcmsg = CCMSG_INVALID; + time_t serverStartTime = 0xDEADDEAD; + RPC_STATUS status = 0; + char* uuid = NULL; + k5_ipc_stream stream = NULL; + ccs_pipe_t pipe = NULL; + ccs_pipe_t pipe2 = NULL; + + if (worklist_remove(&rpcmsg, &pipe, &buf, &serverStartTime)) { + uuid = ccs_win_pipe_getUuid(pipe); +#if 0 + cci_debug_printf("%s: processing WorkItem msg:%ld pipeUUID:<%s> pipeHandle:0x%X SST:%ld", + __FUNCTION__, rpcmsg, uuid, ccs_win_pipe_getHandle(pipe), serverStartTime); +#endif + if (serverStartTime <= getMySST()) { + switch (rpcmsg) { + case CCMSG_CONNECT: { + cci_debug_printf(" Processing CONNECT"); + rpcargs.uuid = (unsigned char*)uuid; + + // Even if a disconnect message is received before this code finishes, + // it won't be dequeued and processed until after this code finishes. + // So we can add the client after starting the connection listener. + connectionListener((void*)&rpcargs); + status = rpcargs.status; + + if (!status) { + status = ccs_server_add_client(pipe); + } + if (!status) {status = send_connection_reply(pipe);} + break; + } + case CCMSG_DISCONNECT: { + cci_debug_printf(" Processing DISCONNECT"); + if (!status) { + status = ccs_server_remove_client(pipe); + } + break; + } + case CCMSG_REQUEST: + cci_debug_printf(" Processing REQUEST"); + ccs_pipe_copy(&pipe2, pipe); + // Dispatch message here, setting both pipes to the client UUID: + err = ccs_server_handle_request (pipe, pipe2, buf); + break; + case CCMSG_PING: + cci_debug_printf(" Processing PING"); + err = krb5int_ipc_stream_new (&stream); + err = krb5int_ipc_stream_write(stream, "This is a test of the emergency broadcasting system", 52); + err = ccs_os_server_send_reply(pipe, stream); + break; + default: + cci_debug_printf("Huh? Received invalid message type %ld from UUID:<%s>", + rpcmsg, uuid); + break; + } + if (buf) krb5int_ipc_stream_release(buf); + /* Don't free uuid, which was allocated here. A pointer to it is in the + rpcargs struct which was passed to connectionListener which will be + received by ccapi_listen when the client exits. ccapi_listen needs + the uuid to know which client to disconnect. + */ + } + // Server's start time is different from what the client thinks. + // That means the server has rebooted since the client connected. + else { + cci_debug_printf("Whoops! Server has rebooted since client established connection."); + } + } + else {cci_debug_printf("Huh? Queue not empty but no item to remove.");} + } + } + + return cci_check_error (err); + } + +/* ------------------------------------------------------------------------ */ + +cc_int32 ccs_os_server_send_reply (ccs_pipe_t in_pipe, + k5_ipc_stream in_reply_stream) { + + /* ccs_pipe_t in_reply_pipe is a char* reply endpoint. + k5_ipc_stream in_reply_stream is the data to be sent. + */ + + cc_int32 err = 0; + char* uuid = ccs_win_pipe_getUuid(in_pipe); + HANDLE h = ccs_win_pipe_getHandle(in_pipe); + + if (!err) { + err = send_init(uuid); // Sets RPC handle to be used. + } + + if (!err) { + RpcTryExcept { + long status; + ccs_rpc_request_reply( // make call with user message + CCMSG_REQUEST_REPLY, /* Message type */ + (unsigned char*)&h, /* client's tspdata* */ + (unsigned char*)uuid, + getMySST(), + krb5int_ipc_stream_size(in_reply_stream), /* Length of buffer */ + (const unsigned char*)krb5int_ipc_stream_data(in_reply_stream), /* Data buffer */ + &status ); /* Return code */ + } + RpcExcept(1) { + cci_check_error(RpcExceptionCode()); + } + RpcEndExcept + } + + /* The calls to the remote procedures are complete. */ + /* Free whatever we allocated: */ + err = RpcBindingFree(&SERVER_REPLY_RPC_HANDLE); + + return cci_check_error (err); + } + + +/* Windows-specific routines: */ + +void Usage(const char* argv0) { + printf("Usage:\n"); + printf("%s [m maxcalls] [n mincalls] [f dontwait] [h|?]]\n", argv0); + printf(" CCAPI server process.\n"); + printf(" h|? whow usage message. <\n"); + } + +/* ------------------------------------------------------------------------ */ +/* The receive thread repeatedly issues RpcServerListen. + When a message arrives, it is handled in the RPC procedure. + */ +void receiveLoop(void* rpcargs) { + + struct RpcRcvArgs* rcvargs = (struct RpcRcvArgs*)rpcargs; + RPC_STATUS status = FALSE; + unsigned char* pszSecurity = NULL; + LPSTR endpoint = NULL; + LPSTR event_name = NULL; + PSECURITY_DESCRIPTOR psd = NULL; + HANDLE hEvent = 0; + Init::InitInfo info; + + cci_debug_printf("THREAD BEGIN: %s", __FUNCTION__); + + status = Init::Info(info); + + /* Build complete RPC endpoint using previous CCAPI implementation: */ + if (!status) { + if (!rcvargs->opts->pszEndpoint) { + if (!status) { + status = alloc_name(&endpoint, "ep", isNT()); + } + + if (!status) { + status = alloc_name(&event_name, "startup", isNT()); + } + + if (!status) { + hEvent = OpenEvent(EVENT_MODIFY_STATE, FALSE, event_name); + // We ignore any error opening the event because we do not know who started us. + // [Comment paraphrased from previous implementation, whence it was copied.] + } + } + else { + endpoint = rcvargs->opts->pszEndpoint; + } + } + + cci_debug_printf("%s Registering endpoint %s", __FUNCTION__, endpoint); + + if (!status && isNT()) { + status = alloc_own_security_descriptor_NT(&psd); + } + + if (!status) { + status = RpcServerUseProtseqEp(rcvargs->protocolSequence, + rcvargs->opts->cMaxCalls, + (RPC_CSTR)endpoint, + rcvargs->opts->bDontProtect ? 0 : psd); // SD + } + + if (!status) { + status = RpcServerRegisterAuthInfo(0, // server principal + RPC_C_AUTHN_WINNT, + 0, + 0); + } + + while (bListen && !status) { + cci_debug_printf("%s is listening ...", __FUNCTION__); + + if (!info.isNT) { + status = RpcServerRegisterIf(ccs_request_ServerIfHandle, // interface + NULL, // MgrTypeUuid + NULL); // MgrEpv; null means use default + } + else { + status = info.fRpcServerRegisterIfEx(ccs_request_ServerIfHandle, // interface + NULL, // MgrTypeUuid + NULL, // MgrEpv; 0 means default + RPC_IF_ALLOW_SECURE_ONLY, + rcvargs->opts->cMaxCalls, + rcvargs->opts->bSecCallback ? + (RPC_IF_CALLBACK_FN*)sec_callback : 0 ); + } + + if (!status) { + status = RpcServerListen(rcvargs->opts->cMinCalls, + rcvargs->opts->cMaxCalls, + rcvargs->opts->fDontWait); + } + + if (!status) { + if (rcvargs->opts->fDontWait) { + if (hEvent) SetEvent(hEvent); // Ignore any error -- SetEvent is an optimization. + status = RpcMgmtWaitServerListen(); + } + } + } + + if (status) { // Cleanup in case of errors: + if (hEvent) CloseHandle(hEvent); + free_alloc_p(&event_name); + free_alloc_p(&psd); + if (endpoint && (endpoint != rcvargs->opts->pszEndpoint)) + free_alloc_p(&endpoint); + } + + _endthread(); + } // End receiveLoop + + +#if 0 + + return status; +} +#endif + + + +/* ------------------------------------------------------------------------ */ +/* The connection listener thread waits forever for a call to the CCAPI_CLIENT_<UUID> + endpoint, ccapi_listen function to complete. If the call completes or gets an + RPC exception, it means the client has disappeared. + + A separate connectionListener is started for each client that has connected to the server. + */ + +void connectionListener(void* rpcargs) { + + struct RpcRcvArgs* rcvargs = (struct RpcRcvArgs*)rpcargs; + RPC_STATUS status = FALSE; + char* endpoint; + unsigned char* pszOptions = NULL; + unsigned char * pszUuid = NULL; + + endpoint = clientEndpoint((char*)rcvargs->uuid); + rpcState = (RPC_ASYNC_STATE*)malloc(sizeof(RPC_ASYNC_STATE)); + status = RpcAsyncInitializeHandle(rpcState, sizeof(RPC_ASYNC_STATE)); + cci_debug_printf(""); + cci_debug_printf("%s About to LISTEN to <%s>", __FUNCTION__, endpoint); + + rpcState->UserInfo = rcvargs->uuid; + rpcState->NotificationType = RpcNotificationTypeApc; + rpcState->u.APC.NotificationRoutine = clientListener; + rpcState->u.APC.hThread = 0; + + /* [If in use] Free previous binding: */ + if (bRpcHandleInited) { + // Free previous binding (could have been used to call ccapi_listen + // in a different client thread). + // Don't check result or update status. + RpcStringFree(&pszStringBinding); + RpcBindingFree(&SERVER_REPLY_RPC_HANDLE); + bRpcHandleInited = FALSE; + } + + /* Set up binding to the client's endpoint: */ + if (!status) { + status = RpcStringBindingCompose( + pszUuid, + pszProtocolSequence, + pszNetworkAddress, + (RPC_CSTR)endpoint, + pszOptions, + &pszStringBinding); + } + + /* Set the binding handle that will be used to bind to the server. */ + if (!status) { + status = RpcBindingFromStringBinding(pszStringBinding, &SERVER_REPLY_RPC_HANDLE); + } + if (!status) {bRpcHandleInited = TRUE;} + + RpcTryExcept { + cci_debug_printf(" Calling remote procedure ccapi_listen"); + ccapi_listen(rpcState, SERVER_REPLY_RPC_HANDLE, CCMSG_LISTEN, &status); + /* Asynchronous call will return immediately. */ + } + RpcExcept(1) { + status = cci_check_error(RpcExceptionCode()); + } + RpcEndExcept + + rcvargs->status = status; + } // End connectionListener + + +void RPC_ENTRY clientListener( + _RPC_ASYNC_STATE* pAsync, + void* Context, + RPC_ASYNC_EVENT Event + ) { + + ccs_pipe_t pipe = ccs_win_pipe_new((char*)pAsync->UserInfo, NULL); + + cci_debug_printf("%s(0x%X, ...) async routine for <0x%X:%s>!", + __FUNCTION__, pAsync, pAsync->UserInfo, pAsync->UserInfo); + + worklist_add( CCMSG_DISCONNECT, + pipe, + NULL, /* No payload with connect request */ + (const time_t)0 ); /* No server session number with connect request */ + } + + +void printError( TCHAR* msg ) { + DWORD eNum; + TCHAR sysMsg[256]; + TCHAR* p; + + eNum = GetLastError( ); + FormatMessage( FORMAT_MESSAGE_FROM_SYSTEM | + FORMAT_MESSAGE_IGNORE_INSERTS, + NULL, eNum, + MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), + sysMsg, 256, NULL ); + + // Trim the end of the line and terminate it with a null + p = sysMsg; + while( ( *p > 31 ) || ( *p == 9 ) ) + ++p; + do { *p-- = 0; } while( ( p >= sysMsg ) && + ( ( *p == '.' ) || ( *p < 33 ) ) ); + + // Display the message + cci_debug_printf("%s failed with error %d (%s)", msg, eNum, sysMsg); + } + + +RPC_STATUS send_init(char* clientUUID) { + RPC_STATUS status; + unsigned char * pszUuid = NULL; + unsigned char * pszOptions = NULL; + + /* Use a convenience function to concatenate the elements of */ + /* the string binding into the proper sequence. */ + status = RpcStringBindingCompose(pszUuid, + pszProtocolSequence, + pszNetworkAddress, + (unsigned char*)clientEndpoint(clientUUID), + pszOptions, + &pszStringBinding); + if (status) {return (status);} + + /* Set the binding handle that will be used to bind to the RPC server [the 'client']. */ + status = RpcBindingFromStringBinding(pszStringBinding, &SERVER_REPLY_RPC_HANDLE); + return (status); + } + +RPC_STATUS send_finish() { + RPC_STATUS status; + /* Can't shut down client -- it runs listen function which */ + /* server uses to detect the client going away. */ + + /* The calls to the remote procedures are complete. */ + /* Free the string and the binding handle */ + status = RpcStringFree(&pszStringBinding); // remote calls done; unbind + if (status) {return (status);} + + status = RpcBindingFree(&SERVER_REPLY_RPC_HANDLE); // remote calls done; unbind + + return (status); + } + +RPC_STATUS send_connection_reply(ccs_pipe_t in_pipe) { + char* uuid = ccs_win_pipe_getUuid (in_pipe); + HANDLE h = ccs_win_pipe_getHandle(in_pipe); + RPC_STATUS status = send_init(uuid); + + RpcTryExcept { + ccs_rpc_connect_reply( // make call with user message + CCMSG_CONNECT_REPLY, /* Message type */ + (unsigned char*)&h, /* client's tspdata* */ + (unsigned char*)uuid, + getMySST(), /* Server's session number = it's start time */ + &status ); /* Return code */ + } + RpcExcept(1) { + cci_check_error(RpcExceptionCode()); + } + RpcEndExcept + + status = send_finish(); + return (status); + } + +#if 0 +DWORD alloc_name(LPSTR* pname, LPSTR postfix) { + DWORD len = strlen(sessID) + 1 + strlen(postfix) + 1; + + *pname = (LPSTR)malloc(len); + if (!*pname) return GetLastError(); + _snprintf(*pname, len, "%s.%s", sessID, postfix); + return 0; + } +#endif + +RPC_STATUS GetPeerName( RPC_BINDING_HANDLE hClient, + LPTSTR pszClientName, + int iMaxLen) { + RPC_STATUS Status = RPC_S_OK; + RPC_BINDING_HANDLE hServer = NULL; + PTBYTE pszStringBinding = NULL; + PTBYTE pszClientNetAddr = NULL; + PTBYTE pszProtSequence = NULL; + + memset(pszClientName, 0, iMaxLen * sizeof(TCHAR)); + + __try { + // Create a partially bound server handle from the client handle. + Status = RpcBindingServerFromClient (hClient, &hServer); + if (Status != RPC_S_OK) __leave; + + // Get the partially bound server string binding and parse it. + Status = RpcBindingToStringBinding (hServer, + &pszStringBinding); + if (Status != RPC_S_OK) __leave; + + // String binding only contains protocol sequence and client + // address, and is not currently implemented for named pipes. + Status = RpcStringBindingParse (pszStringBinding, NULL, + &pszProtSequence, &pszClientNetAddr, + NULL, NULL); + if (Status != RPC_S_OK) + __leave; + int iLen = lstrlen(pszClientName) + 1; + if (iMaxLen < iLen) + Status = RPC_S_BUFFER_TOO_SMALL; + lstrcpyn(pszClientName, (LPCTSTR)pszClientNetAddr, iMaxLen); + } + __finally { + if (pszProtSequence) + RpcStringFree (&pszProtSequence); + + if (pszClientNetAddr) + RpcStringFree (&pszClientNetAddr); + + if (pszStringBinding) + RpcStringFree (&pszStringBinding); + + if (hServer) + RpcBindingFree (&hServer); + } + return Status; +} + +struct client_auth_info { + RPC_AUTHZ_HANDLE authz_handle; + unsigned char* server_principal; // need to RpcFreeString this + ULONG authn_level; + ULONG authn_svc; + ULONG authz_svc; +}; + +RPC_STATUS +GetClientId( + RPC_BINDING_HANDLE hClient, + char* client_id, + int max_len, + client_auth_info* info + ) +{ + RPC_AUTHZ_HANDLE authz_handle = 0; + unsigned char* server_principal = 0; + ULONG authn_level = 0; + ULONG authn_svc = 0; + ULONG authz_svc = 0; + RPC_STATUS status = 0; + + memset(client_id, 0, max_len); + + if (info) { + memset(info, 0, sizeof(client_auth_info)); + } + + status = RpcBindingInqAuthClient(hClient, &authz_handle, + info ? &server_principal : 0, + &authn_level, &authn_svc, &authz_svc); + if (status == RPC_S_OK) + { + if (info) { + info->server_principal = server_principal; + info->authz_handle = authz_handle; + info->authn_level = authn_level; + info->authn_svc = authn_svc; + info->authz_svc = authz_svc; + } + + if (authn_svc == RPC_C_AUTHN_WINNT) { + WCHAR* username = (WCHAR*)authz_handle; + int len = lstrlenW(username) + 1; + if (max_len < len) + status = RPC_S_BUFFER_TOO_SMALL; + _snprintf(client_id, max_len, "%S", username); + } else { + status = RPC_S_UNKNOWN_AUTHN_SERVICE; + } + } + return status; +} + +char* +rpc_error_to_string( + RPC_STATUS status + ) +{ + switch(status) { + case RPC_S_OK: + return "OK"; + case RPC_S_INVALID_BINDING: + return "Invalid binding"; + case RPC_S_WRONG_KIND_OF_BINDING: + return "Wrong binding"; + case RPC_S_BINDING_HAS_NO_AUTH: + RpcRaiseException(RPC_S_BINDING_HAS_NO_AUTH); + return "Binding has no auth"; + default: + return "BUG: I am confused"; + } +} + +void +print_client_info( + RPC_STATUS peer_status, + const char* peer_name, + RPC_STATUS client_status, + const char* client_id, + client_auth_info* info + ) +{ + if (peer_status == RPC_S_OK || peer_status == RPC_S_BUFFER_TOO_SMALL) { + cci_debug_printf("%s Peer Name is \"%s\"", __FUNCTION__, peer_name); + } else { + cci_debug_printf("%s Error %u getting Peer Name (%s)", + __FUNCTION__, peer_status, rpc_error_to_string(peer_status)); + } + + if (client_status == RPC_S_OK || client_status == RPC_S_BUFFER_TOO_SMALL) { + if (info) { + cci_debug_printf("%s Client Auth Info" + "\tServer Principal: %s\n" + "\tAuthentication Level: %d\n" + "\tAuthentication Service: %d\n" + "\tAuthorization Service: %d\n", + __FUNCTION__, + info->server_principal, + info->authn_level, + info->authn_svc, + info->authz_svc); + } + cci_debug_printf("%s Client ID is \"%s\"", __FUNCTION__, client_id); + } else { + cci_debug_printf("%s Error getting Client Info (%u = %s)", + __FUNCTION__, client_status, rpc_error_to_string(client_status)); + } +} + +DWORD sid_check() { + DWORD status = 0; + HANDLE hToken_c = 0; + HANDLE hToken_s = 0; + PTOKEN_USER ptu_c = 0; + PTOKEN_USER ptu_s = 0; + DWORD len = 0; + BOOL bImpersonate = FALSE; + + // Note GetUserName will fail while impersonating at identify + // level. The workaround is to impersonate, OpenThreadToken, + // revert, call GetTokenInformation, and finally, call + // LookupAccountSid. + + // XXX - Note: This workaround does not appear to work. + // OpenThreadToken fails with error 1346: "Either a requid + // impersonation level was not provided or the provided + // impersonation level is invalid". + + status = RpcImpersonateClient(0); + + if (!status) { + bImpersonate = TRUE; + if (!OpenThreadToken(GetCurrentThread(), TOKEN_QUERY, FALSE, &hToken_c)) + status = GetLastError(); + } + + if (!status) { + status = RpcRevertToSelf(); + } + + if (!status) { + bImpersonate = FALSE; + + len = 0; + GetTokenInformation(hToken_c, TokenUser, ptu_c, 0, &len); + if (len == 0) status = 1; + } + + if (!status) { + if (!(ptu_c = (PTOKEN_USER)LocalAlloc(0, len))) + status = GetLastError(); + } + + if (!status) { + if (!GetTokenInformation(hToken_c, TokenUser, ptu_c, len, &len)) + status = GetLastError(); + } + + if (!status) { + if (!OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY, &hToken_s)) + status = GetLastError(); + } + + if (!status) { + len = 0; + GetTokenInformation(hToken_s, TokenUser, ptu_s, 0, &len); + if (len == 0) status = GetLastError(); + } + + if (!status) { + if (!(ptu_s = (PTOKEN_USER)LocalAlloc(0, len))) + status = GetLastError(); + } + + if (!status) { + if (!GetTokenInformation(hToken_s, TokenUser, ptu_s, len, &len)) + status = GetLastError(); + } + + if (!EqualSid(ptu_s->User.Sid, ptu_c->User.Sid)) + status = RPC_S_ACCESS_DENIED; + +/* Cleanup: */ + if (!hToken_c && !bImpersonate) + cci_debug_printf("%s Cannot impersonate (%u)", __FUNCTION__, status); + else if (!hToken_c) + cci_debug_printf("%s Failed to open client token (%u)", __FUNCTION__, status); + else if (bImpersonate) + cci_debug_printf("%s Failed to revert (%u)", __FUNCTION__, status); + else if (!ptu_c) + cci_debug_printf("%s Failed to get client token user info (%u)", + __FUNCTION__, status); + else if (!hToken_s) + cci_debug_printf("%s Failed to open server token (%u)", __FUNCTION__, status); + else if (!ptu_s) + cci_debug_printf("%s Failed to get server token user info (%u)", + __FUNCTION__, status); + else if (status == RPC_S_ACCESS_DENIED) + cci_debug_printf("%s SID **does not** match!", __FUNCTION__); + else if (status == RPC_S_OK) + cci_debug_printf("%s SID matches!", __FUNCTION__); + else + if (status) { + cci_debug_printf("%s unrecognized error %u", __FUNCTION__, status); + abort(); + } + + if (bImpersonate) RpcRevertToSelf(); + if (hToken_c && hToken_c != INVALID_HANDLE_VALUE) + CloseHandle(hToken_c); + if (ptu_c) LocalFree(ptu_c); + if (hToken_s && hToken_s != INVALID_HANDLE_VALUE) + CloseHandle(hToken_s); + if (ptu_s) LocalFree(ptu_s); + if (status) cci_debug_printf("%s returning %u", __FUNCTION__, status); + return status; + } + +RPC_STATUS RPC_ENTRY sec_callback( IN RPC_IF_ID *Interface, + IN void *Context) { + char peer_name[1024]; + char client_name[1024]; + RPC_STATUS peer_status; + RPC_STATUS client_status; + + cci_debug_printf("%s", __FUNCTION__); + peer_status = GetPeerName(Context, peer_name, sizeof(peer_name)); + client_status = GetClientId(Context, client_name, sizeof(client_name), 0); + print_client_info(peer_status, peer_name, client_status, client_name, 0); + DWORD sid_status = sid_check(); + cci_debug_printf("%s returning (%u)", __FUNCTION__, sid_status); + return sid_status; + } + + + +/*********************************************************************/ +/* MIDL allocate and free */ +/*********************************************************************/ + +extern "C" void __RPC_FAR * __RPC_USER midl_user_allocate(size_t len) { + return(malloc(len)); + } + +extern "C" void __RPC_USER midl_user_free(void __RPC_FAR * ptr) { + free(ptr); + } + +/* stubs */ +extern "C" cc_int32 +ccs_os_notify_cache_collection_changed (ccs_cache_collection_t cc) +{ + return 0; +} + +extern "C" cc_int32 +ccs_os_notify_ccache_changed (ccs_cache_collection_t cc, const char *name) +{ + return 0; +} |
