Connecting to Secure Sites

Having a secure website is essential if you are using HTTP to connect to, say, a corporate database. Windows NT and 2000 websites can be secured using the following:

  1. Clear Text Authentication. The username and password are sent down as an HTTP header, visible to others unless secure sockets are used.

  2. NTLM (NT LAN Manager) Authentication. A challenge-response scheme that bases the challenge on the username.

If an HTTP request fails authentication, an error 401 will be returned if the error originates in a web server, or 407 for a proxy server authentication failure. These errors are returned in HTTP headers from the server. If your application receives a 401 or 407 error, a valid username and password should be supplied.

The type of authentication can be configured in Microsoft Internet Information Server (IIS) for each website or virtual directory on a server. Further, an anonymous login can be specified, so that an unrecognized user can login using the specified login. This login name is usually based on the server name, for example, IUSR_MYSERVER, where MYSERVER is the name of the server IIS is installed on. With IIS, once the type of authentication has been configured, NTFS security is applied to the files in the website, and this controls who has what type of access to the files or directories.

The following two methods can be used to handle authentication errors:

  • Using the function InternetErrorDlg to prompt the user to supply a username and password

  • Using HttpQueryInfo to interrogate the HTTP headers returned from the request and calling InternetSetOption to set the username and password

You will need to specify the INTERNET_FLAG_KEEP_CONNECTION option when calling HttpOpenRequest so that the security options can be maintained between HTTP requests.

hHttpRequest = HttpOpenRequest(hHttpSession,
  NULL,    // verb is 'GET'
  crackedURL.lpszUrlPath,
  NULL,    // default version
  NULL,    // no referrer
  NULL,    // only accept text/* files
  INTERNET_FLAG_KEEP_CONNECTION,
  0);      // no context for call backs

One of the problems with using authentication with IIS is finding out which user is making the HTTP requests. Therefore, when testing your authentication code you should turn on logging, and look for the requests in the IIS logs. In the following examples, the first request was made with no username specified (-), and the second used "Administrator."

192.168.0.221, -, 28/02/00, 14:52:41, W3SVC1, SPL_WEB, 192.168.0.2, 71,
363, 761, 401, 5, GET, / site, -,
192.168.0.221, administrator, 28/02/00, 14:52:49, W3SVC1, SPL_WEB,
192.168.0.2, 1502, 414, 300, 302, 0, GET, /site/, -,

Authentication with InternetErrorDlg

The function InternetErrorDlg can be used in a variety of ways to correct errors with HTTP requests. For example, the function can be used to prompt the user for a username and password in the event of an authentication error.

The code fragment in Listing 8.3 calls HttpSendRequest, and then calls InternetErrorDlg with the following options:

  • FLAGS_ERROR_UI_FILTER_FOR_ERRORS— Scans the returned headers for errors

  • FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS— Saves changes (such as the supplied username and password) in the HTTP headers associated with the hHttpRequest handle

  • FLAGS_ERROR_UI_FLAGS_GENERATE_DATA— Generates data to correct the errors, such as prompting the user for the username and password

Table 8.9. InternetErrorDlg—Displays error dialog for specified error code or corrects errors returned in HTTP headers
InternetErrorDlg 
HWND hWndWindow handle used as the parent for any dialogs that are displayed.
HINTERNET hRequestRequest handle from HttpSendRequest.
DWORD dwErrorError code for the problem to be rectified.
DWORD dwFlagsFlags specifying type of action to take.
LPVOID *lppvDataData structure pointer specific for type of error being handled, or NULL for none.
DWORD Return ValueERROR_SUCCESS for success.
 ERROR_CANCELLED if user cancelled dialog box.
 ERROR_INTERNET_FORCE_RETRY if HttpRequest should be resent.

Listing 8.3. Correcting authentication errors with InternetErrorDlg
resend:
  if(!HttpSendRequest(hHttpRequest,
    NULL, 0,       // no headers
    0, 0))      // no optional data
  {
    cout ≪ _T("Could not send request ")
         ≪ GetLastError();
    goto cleanUp;
  }
  DWORD dwErrorCode, dwError;
  dwErrorCode = hHttpRequest ? ERROR_SUCCESS :
      GetLastError();
  dwError = InternetErrorDlg(GetFocus(),
      hHttpRequest,
      dwErrorCode,
      FLAGS_ERROR_UI_FILTER_FOR_ERRORS |
      FLAGS_ERROR_UI_FLAGS_CHANGE_OPTIONS |
      FLAGS_ERROR_UI_FLAGS_GENERATE_DATA,
      NULL);
  if (dwError == ERROR_INTERNET_FORCE_RETRY)
    goto resend;
// now read the data from the request
// using InternetReadFile.

Notice that when an authentication error is detected, the call to HttpSendRequeststill succeeds. If corrective action is not taken the Internet server will return an error message that will be read by InternetReadFile.

Authentication with InternetSetOption

Authentication with InternetErrorDlg will display a dialog prompting for a username and password. In many situations, your application may already know the username and password to use and therefore should not prompt the user. In this situation, HttpQueryInfo is used to determine if the HTTP headers sent from the server contain authentication error information, and InternetSetOption sets the username and password for the request (Listing 8.4).

Listing 8.4. Correcting authentication errors with InternetSetOption
DWORD dwStatus, dwStatusSize;
  dwStatusSize = sizeof(DWORD);
  if(!HttpQueryInfo(hHttpRequest,
      HTTP_QUERY_FLAG_NUMBER |
      HTTP_QUERY_STATUS_CODE,
      &dwStatus, &dwStatusSize, NULL))
  {
      cout ≪ _T("Could not query info")
           ≪ GetLastError();
  }
  // Server Authentication Required
  if(dwStatus == HTTP_STATUS_DENIED)
  {
   // Set strUsername and strPassword
   InternetSetOption(hHttpRequest,
        INTERNET_OPTION_USERNAME,
        szUser, wcslen(szUser) + 1);
   InternetSetOption(hHttpRequest,
        INTERNET_OPTION_PASSWORD,
        szPassword, wcslen(szUser) + 1);
}

HttpQueryInfo is passed the following flags:

  • HTTP_QUERY_FLAG_NUMBER— Return the requested data as a DWORD

  • HTTP_QUERY_STATUS_CODE— Return the status (error) code associated with the request

A pointer to the DWORD dwStatus is passed, and this variable will contain the status number on return. Notice that dwStatusSize is initialized with the size of a DWORD. The variable dwStatus will contain the value HTTP_STATUS_DENIED (which is the value 401) if a server authentication error occurred.

HttpQueryInfo can be used to return all sorts of HTTP header information such as the length of the content to be returned (HTTP_QUERY_CONTENT_LENGTH) or its language (HTTP_QUERY_CONTENT_LANGUAGE), date when the content is deemed to have expired (HTTP_QUERY_EXPIRES), or the host and port number of the server (HTTP_QUERY_HOST).

Table 8.10. HttpQueryInfo—Extracts information from HTTP headers
HttpQueryInfo 
HINTERNET hRequestRequest handle to get headers for
DWORD dwInfoLevelConstant indicating what type of header information to obtain
LPVOID lpBufferPointer to a buffer in which data will be returned
LPDWORD lpdwBufferLengthLength of lpBuffer on entry, number of bytes placed in lpBuffer on return
LPDWORD lpdwIndexHeader index to return when dwInfoLevel may have more than one header
BOOL Return ValueTRUE on success, FALSE for failure

The function InternetSetOption is used to set the username and password into the HTTP headers for the request (Table 8.11).

Table 8.11. InternetSetOption—Sets value into HTTP header
InternetSetOption 
HINTERNET hInternetRequest handle
DWORD dwOptionConstant indicating value to be set, e.g. INTERNET_OPTION_USERNAME
LPVOID lpBufferPointer to buffer containing value
DWORD dwBufferLengthNumber of bytes of data to set
BOOL Return ValueTRUE on success, FALSE for failure

The function can be used to set other options, such as the following:

  • The timeout value (INTERNET_OPTION_CONNECT_TIMEOUT)

  • The proxy name (INTERNET_OPTION_PROXY)

  • The user agent name (INTERNET_OPTION_USER_AGENT)

If you do not have access to a secure Internet site using NTLM, try connecting to http://www.softwarepaths.com/WinCEProgramming/Secure/Default.htm. This resource can be accessed with the user name "wince" and password "device."

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.230.82