Blame src/testcurl/test_digestauth_with_arguments.c

Packit 875988
/*
Packit 875988
     This file is part of libmicrohttpd
Packit 875988
     Copyright (C) 2010, 2012 Christian Grothoff
Packit 875988
Packit 875988
     libmicrohttpd is free software; you can redistribute it and/or modify
Packit 875988
     it under the terms of the GNU General Public License as published
Packit 875988
     by the Free Software Foundation; either version 2, or (at your
Packit 875988
     option) any later version.
Packit 875988
Packit 875988
     libmicrohttpd is distributed in the hope that it will be useful, but
Packit 875988
     WITHOUT ANY WARRANTY; without even the implied warranty of
Packit 875988
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
Packit 875988
     General Public License for more details.
Packit 875988
Packit 875988
     You should have received a copy of the GNU General Public License
Packit 875988
     along with libmicrohttpd; see the file COPYING.  If not, write to the
Packit 875988
     Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor,
Packit 875988
     Boston, MA 02110-1301, USA.
Packit 875988
*/
Packit 875988
Packit 875988
/**
Packit 875988
 * @file daemontest_digestauth_with_arguments.c
Packit 875988
 * @brief  Testcase for libmicrohttpd Digest Auth with arguments
Packit 875988
 * @author Amr Ali
Packit 875988
 */
Packit 875988
#include "MHD_config.h"
Packit 875988
#include "platform.h"
Packit 875988
#include <curl/curl.h>
Packit 875988
#include <microhttpd.h>
Packit 875988
#include <stdlib.h>
Packit 875988
#include <string.h>
Packit 875988
#include <time.h>
Packit 875988
#ifdef MHD_HTTPS_REQUIRE_GRYPT
Packit 875988
#ifdef HAVE_GCRYPT_H
Packit 875988
#include <gcrypt.h>
Packit 875988
#endif
Packit 875988
#endif /* MHD_HTTPS_REQUIRE_GRYPT */
Packit 875988
Packit 875988
#ifndef WINDOWS
Packit 875988
#include <sys/socket.h>
Packit 875988
#include <unistd.h>
Packit 875988
#else
Packit 875988
#include <wincrypt.h>
Packit 875988
#endif
Packit 875988
Packit 875988
#define PAGE "<html><head><title>libmicrohttpd demo</title></head><body>Access granted</body></html>"
Packit 875988
Packit 875988
#define DENIED "<html><head><title>libmicrohttpd demo</title></head><body>Access denied</body></html>"
Packit 875988
Packit 875988
#define MY_OPAQUE "11733b200778ce33060f31c9af70a870ba96ddd4"
Packit 875988
Packit 875988
struct CBC
Packit 875988
{
Packit 875988
  char *buf;
Packit 875988
  size_t pos;
Packit 875988
  size_t size;
Packit 875988
};
Packit 875988
Packit 875988
static size_t
Packit 875988
copyBuffer (void *ptr, size_t size, size_t nmemb, void *ctx)
Packit 875988
{
Packit 875988
  struct CBC *cbc = ctx;
Packit 875988
Packit 875988
  if (cbc->pos + size * nmemb > cbc->size)
Packit 875988
    return 0;                   /* overflow */
Packit 875988
  memcpy (&cbc->buf[cbc->pos], ptr, size * nmemb);
Packit 875988
  cbc->pos += size * nmemb;
Packit 875988
  return size * nmemb;
Packit 875988
}
Packit 875988
Packit 875988
static int
Packit 875988
ahc_echo (void *cls,
Packit 875988
          struct MHD_Connection *connection,
Packit 875988
          const char *url,
Packit 875988
          const char *method,
Packit 875988
          const char *version,
Packit 875988
          const char *upload_data, size_t *upload_data_size,
Packit 875988
          void **unused)
Packit 875988
{
Packit 875988
  struct MHD_Response *response;
Packit 875988
  char *username;
Packit 875988
  const char *password = "testpass";
Packit 875988
  const char *realm = "test@example.com";
Packit 875988
  int ret;
Packit 875988
  (void)cls;(void)url;                          /* Unused. Silent compiler warning. */
Packit 875988
  (void)method;(void)version;(void)upload_data; /* Unused. Silent compiler warning. */
Packit 875988
  (void)upload_data_size;(void)unused;         /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
  username = MHD_digest_auth_get_username(connection);
Packit 875988
  if ( (username == NULL) ||
Packit 875988
       (0 != strcmp (username, "testuser")) )
Packit 875988
    {
Packit 875988
      response = MHD_create_response_from_buffer(strlen (DENIED), 
Packit 875988
						 DENIED,
Packit 875988
						 MHD_RESPMEM_PERSISTENT);  
Packit 875988
      ret = MHD_queue_auth_fail_response(connection, realm,
Packit 875988
					 MY_OPAQUE,
Packit 875988
					 response,
Packit 875988
					 MHD_NO);    
Packit 875988
      MHD_destroy_response(response);  
Packit 875988
      return ret;
Packit 875988
    }
Packit 875988
  ret = MHD_digest_auth_check(connection, realm,
Packit 875988
			      username, 
Packit 875988
			      password, 
Packit 875988
			      300);
Packit 875988
  free(username);
Packit 875988
  if ( (ret == MHD_INVALID_NONCE) ||
Packit 875988
       (ret == MHD_NO) )
Packit 875988
    {
Packit 875988
      response = MHD_create_response_from_buffer(strlen (DENIED), 
Packit 875988
						 DENIED,
Packit 875988
						 MHD_RESPMEM_PERSISTENT);  
Packit 875988
      if (NULL == response) 
Packit 875988
	return MHD_NO;
Packit 875988
      ret = MHD_queue_auth_fail_response(connection, realm,
Packit 875988
					 MY_OPAQUE,
Packit 875988
					 response,
Packit 875988
					 (ret == MHD_INVALID_NONCE) ? MHD_YES : MHD_NO);  
Packit 875988
      MHD_destroy_response(response);  
Packit 875988
      return ret;
Packit 875988
    }
Packit 875988
  response = MHD_create_response_from_buffer(strlen(PAGE), PAGE,
Packit 875988
					     MHD_RESPMEM_PERSISTENT);
Packit 875988
  ret = MHD_queue_response(connection, MHD_HTTP_OK, response);  
Packit 875988
  MHD_destroy_response(response);
Packit 875988
  return ret;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
static int
Packit 875988
testDigestAuth ()
Packit 875988
{
Packit 875988
  CURL *c;
Packit 875988
  CURLcode errornum;
Packit 875988
  struct MHD_Daemon *d;
Packit 875988
  struct CBC cbc;
Packit 875988
  char buf[2048];
Packit 875988
  char rnd[8];
Packit 875988
  int port;
Packit 875988
  char url[128];
Packit 875988
#ifndef WINDOWS
Packit 875988
  int fd;
Packit 875988
  size_t len;
Packit 875988
  size_t off = 0;
Packit 875988
#endif /* ! WINDOWS */
Packit 875988
Packit 875988
  if (MHD_NO != MHD_is_feature_supported (MHD_FEATURE_AUTODETECT_BIND_PORT))
Packit 875988
    port = 0;
Packit 875988
  else
Packit 875988
    port = 1160;
Packit 875988
Packit 875988
  cbc.buf = buf;
Packit 875988
  cbc.size = 2048;
Packit 875988
  cbc.pos = 0;
Packit 875988
#ifndef WINDOWS
Packit 875988
  fd = open("/dev/urandom", O_RDONLY);
Packit 875988
  if (-1 == fd)
Packit 875988
    {
Packit 875988
	  fprintf(stderr, "Failed to open `%s': %s\n",
Packit 875988
	       "/dev/urandom",
Packit 875988
		   strerror(errno));
Packit 875988
	  return 1;
Packit 875988
	}
Packit 875988
  while (off < 8)
Packit 875988
	{
Packit 875988
	  len = read(fd, rnd, 8);
Packit 875988
	  if (len == (size_t)-1)
Packit 875988
	    {
Packit 875988
		  fprintf(stderr, "Failed to read `%s': %s\n",
Packit 875988
		       "/dev/urandom",
Packit 875988
			   strerror(errno));
Packit 875988
		  (void) close(fd);
Packit 875988
		  return 1;
Packit 875988
		}
Packit 875988
	  off += len;
Packit 875988
	}
Packit 875988
  (void) close(fd);
Packit 875988
#else
Packit 875988
  {
Packit 875988
    HCRYPTPROV cc;
Packit 875988
    BOOL b;
Packit 875988
    b = CryptAcquireContext (&cc, NULL, NULL, PROV_RSA_FULL, CRYPT_VERIFYCONTEXT);
Packit 875988
    if (b == 0)
Packit 875988
    {
Packit 875988
      fprintf (stderr, "Failed to acquire crypto provider context: %lu\n",
Packit 875988
          GetLastError ());
Packit 875988
      return 1;
Packit 875988
    }
Packit 875988
    b = CryptGenRandom (cc, 8, (BYTE*)rnd);
Packit 875988
    if (b == 0)
Packit 875988
    {
Packit 875988
      fprintf (stderr, "Failed to generate 8 random bytes: %lu\n",
Packit 875988
          GetLastError ());
Packit 875988
    }
Packit 875988
    CryptReleaseContext (cc, 0);
Packit 875988
    if (b == 0)
Packit 875988
      return 1;
Packit 875988
  }
Packit 875988
#endif
Packit 875988
  d = MHD_start_daemon (MHD_USE_INTERNAL_POLLING_THREAD | MHD_USE_ERROR_LOG,
Packit 875988
                        port, NULL, NULL, &ahc_echo, PAGE,
Packit 875988
			MHD_OPTION_DIGEST_AUTH_RANDOM, sizeof (rnd), rnd,
Packit 875988
			MHD_OPTION_NONCE_NC_SIZE, 300,
Packit 875988
			MHD_OPTION_END);
Packit 875988
  if (d == NULL)
Packit 875988
    return 1;
Packit 875988
  if (0 == port)
Packit 875988
    {
Packit 875988
      const union MHD_DaemonInfo *dinfo;
Packit 875988
      dinfo = MHD_get_daemon_info (d, MHD_DAEMON_INFO_BIND_PORT);
Packit 875988
      if (NULL == dinfo || 0 == dinfo->port)
Packit 875988
        { MHD_stop_daemon (d); return 32; }
Packit 875988
      port = (int)dinfo->port;
Packit 875988
    }
Packit 875988
  sprintf(url, "http://127.0.0.1:%d/foo?key=value", port);
Packit 875988
  c = curl_easy_init ();
Packit 875988
  curl_easy_setopt (c, CURLOPT_URL, url);
Packit 875988
  curl_easy_setopt (c, CURLOPT_WRITEFUNCTION, &copyBuffer);
Packit 875988
  curl_easy_setopt (c, CURLOPT_WRITEDATA, &cbc);
Packit 875988
  curl_easy_setopt (c, CURLOPT_HTTPAUTH, CURLAUTH_DIGEST);
Packit 875988
  curl_easy_setopt (c, CURLOPT_USERPWD, "testuser:testpass");
Packit 875988
  curl_easy_setopt (c, CURLOPT_FAILONERROR, 1);
Packit 875988
  curl_easy_setopt (c, CURLOPT_TIMEOUT, 150L);
Packit 875988
  curl_easy_setopt (c, CURLOPT_CONNECTTIMEOUT, 150L);
Packit 875988
  curl_easy_setopt (c, CURLOPT_HTTP_VERSION, CURL_HTTP_VERSION_1_1);
Packit 875988
  /* NOTE: use of CONNECTTIMEOUT without also
Packit 875988
     setting NOSIGNAL results in really weird
Packit 875988
     crashes on my system!*/
Packit 875988
  curl_easy_setopt (c, CURLOPT_NOSIGNAL, 1);
Packit 875988
  if (CURLE_OK != (errornum = curl_easy_perform (c)))
Packit 875988
    {
Packit 875988
      fprintf (stderr,
Packit 875988
               "curl_easy_perform failed: `%s'\n",
Packit 875988
               curl_easy_strerror (errornum));
Packit 875988
      curl_easy_cleanup (c);
Packit 875988
      MHD_stop_daemon (d);
Packit 875988
      return 2;
Packit 875988
    }
Packit 875988
  curl_easy_cleanup (c);
Packit 875988
  MHD_stop_daemon (d);
Packit 875988
  if (cbc.pos != strlen (PAGE))
Packit 875988
    return 4;
Packit 875988
  if (0 != strncmp (PAGE, cbc.buf, strlen (PAGE)))
Packit 875988
    return 8;
Packit 875988
  return 0;
Packit 875988
}
Packit 875988
Packit 875988
Packit 875988
int
Packit 875988
main (int argc, char *const *argv)
Packit 875988
{
Packit 875988
  unsigned int errorCount = 0;
Packit 875988
  (void)argc; (void)argv; /* Unused. Silent compiler warning. */
Packit 875988
Packit 875988
#ifdef MHD_HTTPS_REQUIRE_GRYPT
Packit 875988
#ifdef HAVE_GCRYPT_H
Packit 875988
  gcry_control (GCRYCTL_ENABLE_QUICK_RANDOM, 0);
Packit 875988
#ifdef GCRYCTL_INITIALIZATION_FINISHED
Packit 875988
  gcry_control (GCRYCTL_INITIALIZATION_FINISHED, 0);
Packit 875988
#endif
Packit 875988
#endif
Packit 875988
#endif /* MHD_HTTPS_REQUIRE_GRYPT */
Packit 875988
  if (0 != curl_global_init (CURL_GLOBAL_WIN32))
Packit 875988
    return 2;
Packit 875988
  errorCount += testDigestAuth ();
Packit 875988
  if (errorCount != 0)
Packit 875988
    fprintf (stderr, "Error (code: %u)\n", errorCount);
Packit 875988
  curl_global_cleanup ();
Packit 875988
  return errorCount != 0;       /* 0 == pass */
Packit 875988
}