Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

337 lines
10 KiB

  1. /*++
  2. Copyright (c) 2000 Microsoft Corporation
  3. Module Name:
  4. dhcp.cpp
  5. Abstract:
  6. Code to allow RIS to automatically authorize for DHCP.
  7. Author:
  8. Hugh Leather (hughleat) 25-July-2000
  9. Revision History:
  10. --*/
  11. #include "pch.h"
  12. #include "dhcpapi.h"
  13. #include "dhcp.h"
  14. #include "setup.h"
  15. DEFINE_MODULE("DHCP");
  16. PSTR
  17. pSetupUnicodeToMultiByte(
  18. IN PCWSTR UnicodeString,
  19. IN UINT Codepage
  20. )
  21. /*++
  22. Routine Description:
  23. Convert a string from unicode to ansi.
  24. Arguments:
  25. UnicodeString - supplies string to be converted.
  26. Codepage - supplies codepage to be used for the conversion.
  27. Return Value:
  28. NULL if out of memory or invalid codepage.
  29. Caller can free buffer with pSetupFree().
  30. --*/
  31. {
  32. UINT WideCharCount;
  33. PSTR String;
  34. UINT StringBufferSize;
  35. UINT BytesInString;
  36. WideCharCount = lstrlenW(UnicodeString) + 1;
  37. //
  38. // Allocate maximally sized buffer.
  39. // If every unicode character is a double-byte
  40. // character, then the buffer needs to be the same size
  41. // as the unicode string. Otherwise it might be smaller,
  42. // as some unicode characters will translate to
  43. // single-byte characters.
  44. //
  45. StringBufferSize = WideCharCount * 2;
  46. String = (PSTR)TraceAlloc(LPTR, StringBufferSize);
  47. if(String == NULL) {
  48. return(NULL);
  49. }
  50. //
  51. // Perform the conversion.
  52. //
  53. BytesInString = WideCharToMultiByte(
  54. Codepage,
  55. 0, // default composite char behavior
  56. UnicodeString,
  57. WideCharCount,
  58. String,
  59. StringBufferSize,
  60. NULL,
  61. NULL
  62. );
  63. if(BytesInString == 0) {
  64. TraceFree(String);
  65. return(NULL);
  66. }
  67. return(String);
  68. }
  69. //////////////////////////////////////////////////////////////////////////////////////////////
  70. // Dhcp Authorization
  71. // ------------------
  72. // Authorization works like this:
  73. // S <- List of authorized servers (from call to DhcpEnumServers)
  74. // I <- IP addresses for this machine (from gethostaddr( 0 ))
  75. // c <- fully qualified physical DNS name of local machine (from GetComputerNameEx)
  76. // for each i such that i is a member of I and i is not a member of S do
  77. // Authorize( i, c ) (by a call to DhcpAddServer)
  78. //
  79. // Aurguments
  80. // hDlg
  81. // Parent window (only used for displaying message boxes modally). Can be NULL.
  82. //
  83. // Returns
  84. // Whatever error code is first generated (or ERROR_SUCCESS if none). A message box will
  85. // be displayed if there is an error.
  86. //
  87. // Used By
  88. // This code is only used by dialogs.cpp
  89. //////////////////////////////////////////////////////////////////////////////////////////////
  90. HRESULT AuthorizeDhcp( HWND hDlg ) {
  91. DWORD err = ERROR_SUCCESS;
  92. PWSTR FullDllPath = NULL;
  93. PWSTR computer_name = NULL;
  94. // Have to use a dll for dhcp authorization function.
  95. // This code loads them.
  96. HMODULE module = NULL;
  97. DWORD ( __stdcall *EnumServersFn )( DWORD, void* , DHCP_SERVER_INFO_ARRAY** ,void* ,void* );
  98. DWORD ( __stdcall *AddServerFn )( DWORD, void* , DHCP_SERVER_INFO* ,void* ,void* );
  99. FullDllPath = (PWSTR)TraceAlloc(LPTR, MAX_PATH*sizeof(WCHAR));
  100. if( !FullDllPath ) {
  101. err = ERROR_NOT_ENOUGH_MEMORY;
  102. DebugMsg( "No Memory!\n" );
  103. goto fail;
  104. }
  105. if( !ExpandEnvironmentStrings(L"%systemroot%\\system32\\dhcpsapi.dll", FullDllPath, MAX_PATH) ) {
  106. err = GetLastError();
  107. DebugMsg( "ExpandEnvironmentStrings failed! (0x%x)\n", err );
  108. goto fail;
  109. }
  110. module = LoadLibrary(FullDllPath);
  111. if (!module) {
  112. err = GetLastError();
  113. DebugMsg( "LoadLibrary(dhcpsapi) failed, ec = %d\n", err );
  114. goto fail;
  115. }
  116. EnumServersFn = ( DWORD ( __stdcall * )( DWORD, void* , DHCP_SERVER_INFO_ARRAY** ,void* ,void* )) GetProcAddress( module, "DhcpEnumServers" );
  117. if( !EnumServersFn ) {
  118. err = GetLastError();
  119. DebugMsg( "GetProcAddress(DhcpEnumServers) failed, ec = %d\n", err );
  120. goto fail;
  121. }
  122. AddServerFn = ( DWORD ( __stdcall * )( DWORD, void* , DHCP_SERVER_INFO* ,void* ,void* )) GetProcAddress( module, "DhcpAddServer" );
  123. if( !AddServerFn ) {
  124. err = GetLastError();
  125. DebugMsg( "GetProcAddress(DhcpAddServer) failed, ec = %d\n", err );
  126. goto fail;
  127. }
  128. // We need the list of ip addresses associated with this machine. This we do through sockets.
  129. HOSTENT* host;
  130. #if 0
  131. DWORD ip;
  132. ip = 0;
  133. host = gethostbyaddr(( const char* )&ip, sizeof( DWORD ), AF_INET );
  134. if( host == NULL ) {
  135. err = WSAGetLastError();
  136. DebugMsg( "gethostbyaddr failed, ec = %d\n", err );
  137. goto fail;
  138. }
  139. if( host->h_addrtype != AF_INET || host->h_length != sizeof( DWORD )) {
  140. err = E_FAIL;
  141. DebugMsg( "gethostbyaddr returned invalid data\n" );
  142. goto fail;
  143. }
  144. #endif
  145. // We get the entire list of dhcp servers.
  146. DHCP_SERVER_INFO_ARRAY* _servers;
  147. if(( err = EnumServersFn( 0, NULL, &_servers, NULL, NULL )) != ERROR_SUCCESS ) {
  148. //
  149. // if this API fails, it will fail with a private DCHP error code that has
  150. // no win32 mapping. So set the error code to something generic and
  151. // reasonable.
  152. //
  153. DebugMsg( "DhcpEnumServers failed, ec = %d\n", err );
  154. err = ERROR_DS_GENERIC_ERROR;
  155. goto fail;
  156. }
  157. // We will need the name of the machine if we have to authorize it. Get the physical name as I'm not sure I trust what happens in the
  158. // clustered case.
  159. DWORD computer_name_len = 0;
  160. if ( !GetComputerNameEx( ComputerNamePhysicalDnsFullyQualified, computer_name, &computer_name_len ) &&
  161. ERROR_MORE_DATA == GetLastError() )
  162. {
  163. computer_name = (PWSTR)TraceAlloc(LPTR, computer_name_len * sizeof(WCHAR));
  164. if ( NULL == computer_name )
  165. {
  166. err = ERROR_NOT_ENOUGH_MEMORY;
  167. DebugMsg( "new failed, ec = %d\n", err );
  168. goto fail;
  169. }
  170. if( !GetComputerNameEx( ComputerNamePhysicalDnsFullyQualified, computer_name, &computer_name_len ))
  171. {
  172. err = GetLastError();
  173. DebugMsg( "GetComputerNameEx failed, ec = %d\n", err );
  174. goto fail;
  175. }
  176. DebugMsg( "ComputerName = %s\n", computer_name );
  177. }
  178. else // shoudn�t hit this unless there are serious problems with the system.
  179. {
  180. err = GetLastError();
  181. DebugMsg( "GetComputerNameEx failed, ec = %d\n", err );
  182. goto fail;
  183. }
  184. #if 1
  185. char ComputerNameA[400];
  186. DWORD ip;
  187. WideCharToMultiByte(CP_ACP,
  188. 0, // default composite char behavior
  189. computer_name,
  190. -1,
  191. ComputerNameA,
  192. 400,
  193. NULL,
  194. NULL
  195. );
  196. host = gethostbyname( ComputerNameA );
  197. if( host == NULL ) {
  198. err = WSAGetLastError();
  199. DebugMsg( "gethostbyaddr failed, ec = %d\n", err );
  200. goto fail;
  201. }
  202. if( host->h_addrtype != AF_INET || host->h_length != sizeof( DWORD )) {
  203. err = ERROR_FUNCTION_FAILED;
  204. DebugMsg( "gethostbyaddr returned invalid data\n" );
  205. goto fail;
  206. }
  207. #endif
  208. // Cool now that we have all of that jazz, we can check that each of our ip addresses is authorized.
  209. for( PCHAR* i = host->h_addr_list; *i != 0; ++i ) {
  210. ip = ntohl( *( DWORD* )*i );
  211. DebugMsg( "searching server list for %d.%d.%d.%d\n",
  212. ip & 0xFF,
  213. (ip >> 8) & 0xFF,
  214. (ip >> 16) & 0xFF,
  215. (ip >> 24) & 0xFF );
  216. BOOL this_address_authorized = FALSE;
  217. for( unsigned j = 0; j < _servers->NumElements; ++j ) {
  218. DebugMsg( "server list entry: %d.%d.%d.%d\n",
  219. _servers->Servers[ j ].ServerAddress & 0xFF,
  220. (_servers->Servers[ j ].ServerAddress >> 8) & 0xFF,
  221. (_servers->Servers[ j ].ServerAddress >> 16) & 0xFF,
  222. (_servers->Servers[ j ].ServerAddress >> 24) & 0xFF );
  223. if( _servers->Servers[ j ].ServerAddress == ip ) {
  224. DebugMsg("found a match in list\n");
  225. this_address_authorized = TRUE;
  226. err = ERROR_SUCCESS;
  227. break;
  228. }
  229. }
  230. if( !this_address_authorized ) {
  231. // Authorize it!
  232. DHCP_SERVER_INFO server_info = { 0 };
  233. server_info.ServerAddress = ip;
  234. server_info.ServerName = computer_name;
  235. DebugMsg("authorizing %s (%d.%d.%d.%d)\n",
  236. server_info.ServerName,
  237. server_info.ServerAddress & 0xFF,
  238. (server_info.ServerAddress >> 8) & 0xFF,
  239. (server_info.ServerAddress >> 16) & 0xFF,
  240. (server_info.ServerAddress >> 24) & 0xFF);
  241. err = AddServerFn( 0, NULL, &server_info, NULL, NULL );
  242. if( err != ERROR_SUCCESS ) {
  243. //
  244. // if this API fails, it will fail with a private DCHP error code that has
  245. // no win32 mapping. So set the error code to something generic and
  246. // reasonable.
  247. //
  248. DebugMsg("DhcpAddServer failed, ec = %d\n",
  249. err
  250. );
  251. err = ERROR_DS_GENERIC_ERROR;
  252. goto fail;
  253. }
  254. } else {
  255. DebugMsg("skipping authorization of interface, it's already authorized\n");
  256. }
  257. }
  258. err = ERROR_SUCCESS;
  259. goto exit;
  260. fail :
  261. MessageBoxFromStrings(
  262. hDlg,
  263. IDS_AUTHORIZING_DHCP,
  264. IDS_AUTHORIZE_DHCP_FAILURE,
  265. MB_OK | MB_ICONERROR );
  266. exit :
  267. if (computer_name) {
  268. TraceFree(computer_name);
  269. computer_name = NULL;
  270. }
  271. if (module) {
  272. FreeLibrary(module);
  273. }
  274. if (FullDllPath) {
  275. TraceFree(FullDllPath);
  276. }
  277. return HRESULT_FROM_WIN32( err );
  278. }