Source code of Windows XP (NT5)
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.

312 lines
9.7 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. PSTR p;
  37. WideCharCount = lstrlenW(UnicodeString) + 1;
  38. //
  39. // Allocate maximally sized buffer.
  40. // If every unicode character is a double-byte
  41. // character, then the buffer needs to be the same size
  42. // as the unicode string. Otherwise it might be smaller,
  43. // as some unicode characters will translate to
  44. // single-byte characters.
  45. //
  46. StringBufferSize = WideCharCount * 2;
  47. String = new char[StringBufferSize];
  48. if(String == NULL) {
  49. return(NULL);
  50. }
  51. //
  52. // Perform the conversion.
  53. //
  54. BytesInString = WideCharToMultiByte(
  55. Codepage,
  56. 0, // default composite char behavior
  57. UnicodeString,
  58. WideCharCount,
  59. String,
  60. StringBufferSize,
  61. NULL,
  62. NULL
  63. );
  64. if(BytesInString == 0) {
  65. delete(String);
  66. return(NULL);
  67. }
  68. return(String);
  69. }
  70. //////////////////////////////////////////////////////////////////////////////////////////////
  71. // Dhcp Authorization
  72. // ------------------
  73. // Authorization works like this:
  74. // S <- List of authorized servers (from call to DhcpEnumServers)
  75. // I <- IP addresses for this machine (from gethostaddr( 0 ))
  76. // c <- fully qualified physical DNS name of local machine (from GetComputerNameEx)
  77. // for each i such that i is a member of I and i is not a member of S do
  78. // Authorize( i, c ) (by a call to DhcpAddServer)
  79. //
  80. // Aurguments
  81. // hDlg
  82. // Parent window (only used for displaying message boxes modally). Can be NULL.
  83. //
  84. // Returns
  85. // Whatever error code is first generated (or ERROR_SUCCESS if none). A message box will
  86. // be displayed if there is an error.
  87. //
  88. // Used By
  89. // This code is only used by dialogs.cpp
  90. //////////////////////////////////////////////////////////////////////////////////////////////
  91. HRESULT AuthorizeDhcp( HWND hDlg ) {
  92. DWORD err;
  93. PWCHAR computer_name = 0;
  94. // Have to use a dll for dhcp authorization function.
  95. // This code loads them.
  96. HMODULE module;
  97. DWORD ( __stdcall *EnumServersFn )( DWORD, void* , DHCP_SERVER_INFO_ARRAY** ,void* ,void* );
  98. DWORD ( __stdcall *AddServerFn )( DWORD, void* , DHCP_SERVER_INFO* ,void* ,void* );
  99. module = LoadLibraryA( "dhcpsapi.dll" );
  100. if( module ) {
  101. EnumServersFn = ( DWORD ( __stdcall * )( DWORD, void* , DHCP_SERVER_INFO_ARRAY** ,void* ,void* )) GetProcAddress( module, "DhcpEnumServers" );
  102. if( !EnumServersFn ) {
  103. err = GetLastError();
  104. DebugMsg( "GetProcAddress(DhcpEnumServers) failed, ec = %d\n", err );
  105. goto fail;
  106. }
  107. AddServerFn = ( DWORD ( __stdcall * )( DWORD, void* , DHCP_SERVER_INFO* ,void* ,void* )) GetProcAddress( module, "DhcpAddServer" );
  108. if( !AddServerFn ) {
  109. err = GetLastError();
  110. DebugMsg( "GetProcAddress(DhcpAddServer) failed, ec = %d\n", err );
  111. goto fail;
  112. }
  113. }
  114. else {
  115. err = GetLastError();
  116. DebugMsg( "LoadLibrary failed, ec = %d\n", err );
  117. goto fail;
  118. }
  119. // We need the list of ip addresses associated with this machine. This we do through sockets.
  120. HOSTENT* host;
  121. #if 0
  122. DWORD ip;
  123. ip = 0;
  124. host = gethostbyaddr(( const char* )&ip, sizeof( DWORD ), AF_INET );
  125. if( host == NULL ) {
  126. err = WSAGetLastError();
  127. DebugMsg( "gethostbyaddr failed, ec = %d\n", err );
  128. goto fail;
  129. }
  130. if( host->h_addrtype != AF_INET || host->h_length != sizeof( DWORD )) {
  131. err = E_FAIL;
  132. DebugMsg( "gethostbyaddr returned invalid data\n" );
  133. goto fail;
  134. }
  135. #endif
  136. // We get the entire list of dhcp servers.
  137. DHCP_SERVER_INFO_ARRAY* _servers;
  138. if(( err = EnumServersFn( 0, NULL, &_servers, NULL, NULL )) != ERROR_SUCCESS ) {
  139. //
  140. // if this API fails, it will fail with a private DCHP error code that has
  141. // no win32 mapping. So set the error code to something generic and
  142. // reasonable.
  143. //
  144. DebugMsg( "DhcpEnumServers failed, ec = %d\n", err );
  145. err = ERROR_DS_GENERIC_ERROR;
  146. goto fail;
  147. }
  148. // 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
  149. // clustered case.
  150. DWORD computer_name_len;
  151. computer_name_len = MAX_COMPUTERNAME_LENGTH * 2; // Allow for extra DNS characters.
  152. computer_name = new WCHAR[ MAX_COMPUTERNAME_LENGTH * 2 ];
  153. if (!computer_name) {
  154. err = ERROR_NOT_ENOUGH_MEMORY;
  155. DebugMsg( "new failed, ec = %d\n", err );
  156. goto fail;
  157. }
  158. if( !GetComputerNameEx( ComputerNamePhysicalDnsFullyQualified, computer_name, &computer_name_len )) {
  159. err = GetLastError();
  160. if( err == ERROR_MORE_DATA ) {
  161. delete [] computer_name;
  162. computer_name = new WCHAR[ computer_name_len ];
  163. if (!computer_name) {
  164. err = ERROR_NOT_ENOUGH_MEMORY;
  165. DebugMsg( "new failed, ec = %d\n", err );
  166. goto fail;
  167. }
  168. if( !GetComputerNameEx( ComputerNamePhysicalDnsFullyQualified, computer_name, &computer_name_len )) {
  169. err = GetLastError();
  170. DebugMsg( "GetComputerNameEx failed, ec = %d\n", err );
  171. goto fail;
  172. }
  173. }
  174. else goto fail;
  175. }
  176. DebugMsg( "ComputerName = %s\n", computer_name );
  177. #if 1
  178. char ComputerNameA[400];
  179. DWORD ip;
  180. WideCharToMultiByte(CP_ACP,
  181. 0, // default composite char behavior
  182. computer_name,
  183. -1,
  184. ComputerNameA,
  185. 400,
  186. NULL,
  187. NULL
  188. );
  189. host = gethostbyname( ComputerNameA );
  190. if( host == NULL ) {
  191. err = WSAGetLastError();
  192. DebugMsg( "gethostbyaddr failed, ec = %d\n", err );
  193. goto fail;
  194. }
  195. if( host->h_addrtype != AF_INET || host->h_length != sizeof( DWORD )) {
  196. err = E_FAIL;
  197. DebugMsg( "gethostbyaddr returned invalid data\n" );
  198. goto fail;
  199. }
  200. #endif
  201. // Cool now that we have all of that jazz, we can check that each of our ip addresses is authorized.
  202. for( PCHAR* i = host->h_addr_list; *i != 0; ++i ) {
  203. ip = ntohl( *( DWORD* )*i );
  204. DebugMsg( "searching server list for %d.%d.%d.%d\n",
  205. ip & 0xFF,
  206. (ip >> 8) & 0xFF,
  207. (ip >> 16) & 0xFF,
  208. (ip >> 24) & 0xFF );
  209. BOOL this_address_authorized = FALSE;
  210. for( unsigned j = 0; j < _servers->NumElements; ++j ) {
  211. DebugMsg( "server list entry: %d.%d.%d.%d\n",
  212. _servers->Servers[ j ].ServerAddress & 0xFF,
  213. (_servers->Servers[ j ].ServerAddress >> 8) & 0xFF,
  214. (_servers->Servers[ j ].ServerAddress >> 16) & 0xFF,
  215. (_servers->Servers[ j ].ServerAddress >> 24) & 0xFF );
  216. if( _servers->Servers[ j ].ServerAddress == ip ) {
  217. DebugMsg("found a match in list\n");
  218. this_address_authorized = TRUE;
  219. err = ERROR_SUCCESS;
  220. break;
  221. }
  222. }
  223. if( !this_address_authorized ) {
  224. // Authorize it!
  225. DHCP_SERVER_INFO server_info = { 0 };
  226. server_info.ServerAddress = ip;
  227. server_info.ServerName = computer_name;
  228. DebugMsg("authorizing %s (%d.%d.%d.%d)\n",
  229. server_info.ServerName,
  230. server_info.ServerAddress & 0xFF,
  231. (server_info.ServerAddress >> 8) & 0xFF,
  232. (server_info.ServerAddress >> 16) & 0xFF,
  233. (server_info.ServerAddress >> 24) & 0xFF);
  234. err = AddServerFn( 0, NULL, &server_info, NULL, NULL );
  235. if( err != ERROR_SUCCESS ) {
  236. //
  237. // if this API fails, it will fail with a private DCHP error code that has
  238. // no win32 mapping. So set the error code to something generic and
  239. // reasonable.
  240. //
  241. DebugMsg("DhcpAddServer failed, ec = %d\n",
  242. err
  243. );
  244. err = ERROR_DS_GENERIC_ERROR;
  245. goto fail;
  246. }
  247. } else {
  248. DebugMsg("skipping authorization of interface, it's already authorized\n");
  249. }
  250. }
  251. err = ERROR_SUCCESS;
  252. goto exit;
  253. fail :
  254. MessageBoxFromStrings(
  255. hDlg,
  256. IDS_AUTHORIZING_DHCP,
  257. IDS_AUTHORIZE_DHCP_FAILURE,
  258. MB_OK | MB_ICONERROR );
  259. exit :
  260. if (computer_name) {
  261. delete [] computer_name;
  262. }
  263. return HRESULT_FROM_WIN32( err );
  264. }