Are you a world traveler? ZoneTick is a cool utility that'll help you stay in touch over multiple time zones!
 
Basic Authentication  
Nik Okuntseff  Windows 2000 Security Programming 

Basic Authentication

Basic Authentication Scheme is defined in section 11.1 of RFC 2068 (HTTP 1.1 Protocol). Here is its entire content:

### Extract from RFC 2068.

11.1 Basic Authentication Scheme

   The "basic" authentication scheme is based on the model that the user
   agent must authenticate itself with a user-ID and a password for each
   realm. The realm value should be considered an opaque string which
   can only be compared for equality with other realms on that server.
   The server will service the request only if it can validate the
   user-ID and password for the protection space of the Request-URI.
   There are no optional authentication parameters.

   Upon receipt of an unauthorized request for a URI within the
   protection space, the server MAY respond with a challenge like the
   following:

          WWW-Authenticate: Basic realm="WallyWorld"

   where "WallyWorld" is the string assigned by the server to identify
   the protection space of the Request-URI.

   To receive authorization, the client sends the userid and password,
   separated by a single colon (":") character, within a base64  encoded
   string in the credentials.

          basic-credentials = "Basic" SP basic-cookie
          basic-cookie   = <base64 [7] encoding of user-pass,
                           except not limited to 76 char/line>
          user-pass   = userid ":" password
          userid      = *<TEXT excluding ":">
          password    = *TEXT

   Userids might be case sensitive.

   If the user agent wishes to send the userid "Aladdin" and password
   "open sesame", it would use the following header field:

          Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

   See section 15 for security considerations associated with Basic
   authentication.

### End of extract.

Browser Behaviour for Virtual Directories with Basic Authentication

What happens when a browser is pointed to a URL with basic authentication? First it tries to access the URL anonymously. Refer to network traffic captures (described in the end of this section) to observe actual data sent over the network between the browser and IIS. IIS returns error code 401 (Access Denied), informs the client that it supports basic authentication schema for the resource in the "WWW-Authenticate: Basic" header, then immediately disconnects the socket. The browser then asks user to enter user name and password (see Figure below).


Intenet Esplorer 5.00.3103.1000 asks user for authentication information.

The browser then opens another socket for communication with the web server, embeds authentication info in the Authorization header and sends another HTTP GET request. IIS logs a user onto the machine using his/her user name and password. The thread that handles the request obtains security context of a user, and tries to access a resource as if actually being this user. If NTFS permissions allow for access, then IIS replies with resource data.

I have created a small code sample that uses basic authentication schema to get a web page from a web server. This sample is called HttpBasicClient. It is a little bit different from HttpAnonymousClient already described above. The difference is that I insert the Authorization header into the GET request. Take a look at its main function.

#include <winsock.h>
#include "comm.h"
#include "http.h"

#define BUFSIZE (64*1024)

// Main.
int main(int argc, char *argv[])
{
  SOCKET s;
  unsigned long cbRead;
  unsigned long cbSize = BUFSIZE;
  char achData[BUFSIZE];

  // Change as necessary.
  char * pszServer = "localhost";  // Notice that this might be an IP address, such as 
                                // 10.1.5.148 or a resolvable full name of the machine
                                // such as webserver.mycompany.com.
  char * pszDoc = "/1/1.htm";

  // Initialize Winsock.
  if (!InitWinsock())
	return -1;

  // Connect to server.
  if (!ConnectSocket(pszServer, &s)) 
    return -1;

  // Build an HTTP GET request with basic authentication info.
  buildBasicGet(achData, &cbSize, pszDoc);
  if (!SendBytes(s, (unsigned char *) achData, strlen(achData)))
  	return -1;

  // Receive data from server.
  if (!ReceiveBytes(s, (unsigned char *) achData, BUFSIZE, &cbRead))
    return -1;

  // Display received data.
  ::MessageBox(NULL, achData, "Data returned from web server", MB_OK | MB_ICONINFORMATION);
  
  // Terminate socket.
  CloseSocket(s);
  TermWinsock();
  return 0;
}

As can be seen from the above code sample, I call the buildBasicGet function to prepare an HTTP GET packet. Here is its implementation.

#include <string.h>
#include "base64.h"

static char Headers[] = "HTTP/1.0\r\n"
  "User-Agent: HttpBasicClient\r\n"
  "Content-type: text/html\r\n"
  "Accept: */*\r\n"
  "Connection: Keep-Alive\r\n";


/*
 * buildBasicGet
 * Builds an HTTP GET request with embedded basic authentication information.
 *
 * Parameters:
 *  pData - data buffer to build a request in.
 *  pcbSize - points to data size.
 *  pURL - URL.
 *  Returns - 0 if we are okay.
 */
int buildBasicGet(char * pData, unsigned long * pcbSize, char * pURL)
{
  // Clear text user name and password. Change as necessary.
  const char user[]="TestUser";
  const char pwd[]="password";
	
  memset(pData, 0, *pcbSize);
  strcpy(pData, "GET ");
  strcat(pData, pURL);
  strcat(pData, " ");
  strcat(pData, Headers);
  
  // Prepare clear text authorization string.
  char authstr[256] = {0};
  strcat(authstr, user);
  strcat(authstr, ":");
  strcat(authstr, pwd);

  // Base64 encode the authorization string.
  char * b64_auth = base64_encode((unsigned char*) authstr, strlen(authstr));

  // Append the authorization string.
  strcat(pData, "Authorization: Basic ");
  strcat(pData, b64_auth);
  strcat(pData, "\r\n");
  strcat(pData, "\r\n");
  
  // Release memory.
  if (b64_auth)
    delete b64_auth;
  
  return 0;
}

So, to summarize, if a client is using the basic authentication schema, it must supply the Authorization: header, containing base64 encoded user name and password separated by a semicolon. As already mentioned in RFC 2068, for user named "Aladdin" and password "open sesame", the header must look like

Authorization: Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==

My sample code for hard-coded user name "TestUser" and password "password" builds this header as

Authorization: Basic VGVzdFVzZXI6cGFzc3dvcmQ=

The complete list of headers that my sample provides is presented below:

GET /1/1.htm HTTP/1.0
User-Agent: HttpBasicClient
Content-type: text/html
Accept: */*
Connection: Keep-Alive
Autorization: Basic VGVzdFVzZXI6cGFzc3dvcmQ=

This list is followed by 2 CRLFs.

As in the previous section I have captured network traffic between client applications and IIS for reference. The complete list of related traffic captures is summarized in the following table.


 
[ Contents | Home ]

Send comments and suggestions to niko@wrconsulting.com
Copyright © 2000 by Nik Okuntseff
Client

Server

File with network traffic data

Comment

IE 5.00.3103.1000IIS 5.0IE5_IIS50_Basic.cap200 OK. Successful access with basic authentication.
IE 5.00.3103.1000IIS 5.0IE5_IIS50_BasicNotFound.cap 404 Object Not Found. Successful access to the virtual directory on the server, but the document does not exist.
IE 5.00.3103.1000IIS 5.0IE5_IIS50_BasicNtfsNoAccess.cap 401 Access Denied. Successful access to the virtual directory, but NTFS permissions prohibit access to the file.
HttpBasicClientIIS 5.0NikBasicClient_IIS50.cap200 OK. Successful access with basic authentication.
HttpBasicClientIIS 5.0NikBasicClient_IIS50_NoBasic.cap401 Access Denied. The virtual directory does not allow for basic authentication access.
HttpBasicClientIIS 5.0NikBasicClient_IIS50_NotFound.cap 404 Object Not Found. Successful access to the virtual directory on the server, but the document does not exist on the server.
HttpBasicClientIIS 5.0NikBasicClient_IIS50_NtfsNoAccess.cap 401 Access Denied. Basic access to the directory is allowed, but NTFS permissions prohibit access to the file.
IE 5.00.2920.0000IIS 4.0IE5_IIS40_Basic.cap200 OK. Successful access with basic authentication information.
IE 5.00.2920.0000IIS 4.0IE5_IIS40_BasicNotFound.cap 404 Object Not Found. Successful access to the virtual directory on the server, but the document does not exist on the server.
IE 5.00.2920.0000IIS 4.0IE5_IIS40_BasicNtfsNoAccess.cap 401 Access Denied. Basic access to the directory is allowed, but NTFS permissions prohibit access to the file.
HttpBasicClientIIS 4.0NikBasicClient_IIS40.cap200 OK. Successful access with basic authentication information.
HttpBasicClientIIS 4.0NikBasicClient_IIS40_NoBasic.cap401 Access Denied. The virtual directory does not allow for basic access.
HttpBasicClientIIS 4.0NikBasicClient_IIS40_NotFound.cap 404 Object Not Found. Successful access to the virtual directory on the server, but the document does not exist on the server.
HttpBasicClientIIS 4.0NikBasicClient_IIS40_NtfsNoAccess.cap 401 Access Denied. Basic access to the directory is allowed, but NTFS permissions prohibit access to the file.