gnunet-svn
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[GNUnet-SVN] r14100 - libmicrohttpd-docs/WWW


From: gnunet
Subject: [GNUnet-SVN] r14100 - libmicrohttpd-docs/WWW
Date: Sat, 1 Jan 2011 14:49:34 +0100

Author: grothoff
Date: 2011-01-01 14:49:34 +0100 (Sat, 01 Jan 2011)
New Revision: 14100

Modified:
   libmicrohttpd-docs/WWW/tutorial.html
   libmicrohttpd-docs/WWW/tutorial.pdf
Log:
update

Modified: libmicrohttpd-docs/WWW/tutorial.html
===================================================================
--- libmicrohttpd-docs/WWW/tutorial.html        2011-01-01 13:47:44 UTC (rev 
14099)
+++ libmicrohttpd-docs/WWW/tutorial.html        2011-01-01 13:49:34 UTC (rev 
14100)
@@ -14,7 +14,7 @@
 Free Documentation License".
 
  -->
-<!-- Created on December 25, 2010 by texi2html 1.82
+<!-- Created on January 1, 2011 by texi2html 1.82
 texi2html was written by: 
             Lionel Cons <address@hidden> (original author)
             Karl Berry  <address@hidden>
@@ -296,7 +296,7 @@
 is the port you chose. If everything works as expected, the browser will 
present the message of the
 static HTML page it got from our minimal server.
 </p>
-<a name="Remarks-1"></a>
+<a name="Remarks"></a>
 <h2 class="heading">Remarks</h2>
 <p>To keep this first example as small as possible, some drastic shortcuts 
were taken and are to be
 discussed now. 
@@ -459,7 +459,7 @@
 <p>Of course, no transmission can occur while the return value is still set to 
<code>MHD_NO</code> in the
 callback function.
 </p>
-<a name="Exercises-2"></a>
+<a name="Exercises-3"></a>
 <h2 class="heading">Exercises</h2>
 <ul>
 <li>
@@ -768,99 +768,61 @@
 so every &quot;GET&quot; request will be challenged.
 <em>RFC 2617</em> describes how the server shall ask for authentication by 
adding a
 <em>WWW-Authenticate</em> response header with the name of the <em>realm</em> 
protected.
+MHD can generate and queue such a failure response for you using
+the <code>MHD_queue_basic_auth_fail_response</code> API.  The only thing you 
need to do
+is construct a response with the error page to be shown to the user
+if he aborts basic authentication.  But first, you should check if the
+proper credentials were already supplied using the
+<code>MHD_basic_auth_get_username_password</code> call.
 </p>
-<p>We let an extra function function do this.
-</p><pre class="verbatim">static int 
-ask_for_authentication (struct MHD_Connection *connection, const char *realm)
+<p>Your code would then look like this:
+</p><pre class="verbatim">static int
+answer_to_connection (void *cls, struct MHD_Connection *connection,
+                      const char *url, const char *method,
+                      const char *version, const char *upload_data,
+                      size_t *upload_data_size, void **con_cls)
 {
-  int ret;
+  char *user;
+  char *pass;
+  int fail;
   struct MHD_Response *response;
-  char *headervalue;
-  const char *strbase = &quot;Basic realm=&quot;;
-  
-  response = MHD_create_response_from_data (0, NULL, MHD_NO, MHD_NO);
-  if (!response) return MHD_NO;
-  
-  headervalue = malloc (strlen (strbase) + strlen (realm) + 1);
-  if (!headervalue) return MHD_NO;  
 
-  strcpy (headervalue, strbase);
-  strcat (headervalue, realm);
-  
-  ret = MHD_add_response_header (response, &quot;WWW-Authenticate&quot;, 
headervalue);
-  free (headervalue);  
-  if (!ret) {MHD_destroy_response (response); return MHD_NO;}
-
-  ret = MHD_queue_response (connection, MHD_HTTP_UNAUTHORIZED, response);
+  if (0 != strcmp (method, MHD_HTTP_METHOD_GET))
+    return MHD_NO;
+  if (NULL == *con_cls)
+    {
+      *con_cls = connection;
+      return MHD_YES;
+    }
+  pass = NULL;
+  user = MHD_basic_auth_get_username_password (connection, &amp;pass);
+  fail = ( (user == NULL) ||
+          (0 != strcmp (user, &quot;root&quot;)) ||
+          (0 != strcmp (pass, &quot;pa$$w0rd&quot;) ) );  
+  if (user != NULL) free (user);
+  if (pass != NULL) free (pass);
+  if (fail)
+    {
+      const char *page = &quot;&lt;html&gt;&lt;body&gt;Go 
away.&lt;/body&gt;&lt;/html&gt;&quot;;
+      response =
+       MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
+                                      MHD_NO);
+      ret = MHD_queue_basic_auth_fail_response (connection,
+                                               &quot;my realm&quot;,
+                                               response);
+    }
+  else
+    {
+      const char *page = &quot;&lt;html&gt;&lt;body&gt;A 
secret.&lt;/body&gt;&lt;/html&gt;&quot;;
+      response =
+       MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
+                                      MHD_NO);
+      ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+    }
   MHD_destroy_response (response);
   return ret;
 }
 </pre>
-<p><code>#define</code> the realm name according to your own taste, e.g. 
&quot;Maintenance&quot; or &quot;Area51&quot; but
-it will need to have extra quotes.
-</p>
-<p>Since the client may send the authentication right away, it would be wrong 
to ask for
-it without checking the request&rsquo;s header&ndash;where the authentication 
is expected to be found.
-</p>
-<a name="Authentication-in-detail"></a>
-<h2 class="heading">Authentication in detail</h2>
-<p>Checking <em>RFC 2617</em> again, we find that the client will pack the 
username and password, by
-whatever means he might have obtained them, in a line separated by a 
colon&mdash;and then encodes
-them to <em>Base64</em>. The actual implementation of this encoding are not 
within the scope of
-this tutorial although a working function is included in the complete source 
file of the example.
-</p>
-<p>An unencoded word describing the authentication method (here 
&quot;Basic&quot;) will precede the code
-and the resulting line is the value of a request header of the type 
&quot;Authorization&quot;.  
-</p>
-<p>This header line thus is of interest to the function checking a connection 
for a given username/password:
-</p><pre class="verbatim">static int 
-is_authenticated (struct MHD_Connection *connection,
-                  const char *username, const char *password)
-{
-  const char *headervalue;
-  ...
-
-  headervalue = MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
-                                             &quot;Authorization&quot;);
-  if (NULL == headervalue) return 0;
-</pre>
-<p>where, firstly, the authentication method will be checked.
-</p><pre class="verbatim">const char *strbase = &quot;Basic &quot;;
-...
-if (0 != strncmp (headervalue, strbase, strlen (strbase))) return 0;
-</pre>
-<p>Of course, we could decode the passed credentials in the next step and 
compare them directly to
-the given strings. But as this would involve string parsing, which is more 
complicated then string
-composing, it is done the other way around&mdash;the clear text credentials 
will be encoded to <em>Base64</em>
-and then compared against the headerline. The authentication method string 
will be left out here as
-it has been checked already at this point.
-</p><pre class="verbatim">  char *expected_b64, *expected;
-  int authenticated;
-
-  ...
-  strcpy (expected, username);
-  strcat (expected, &quot;:&quot;);
-  strcat (expected, password);  
-
-  expected_b64 = string_to_base64 (expected);
-  if (NULL == expected_b64) return 0;
- 
-  strcpy (expected, strbase);
-  authenticated = (strcmp (headervalue + strlen (strbase), expected_b64) == 0);
-
-  free (expected_b64);
-
-  return authenticated;
-}
-</pre>
-<p>These two functions&mdash;together with a response function in case of 
positive authentication doing little 
-new&mdash;allow the rest of the callback function to be rather short. 
-</p><pre class="verbatim">  if (!is_authenticated (connection, USER, 
PASSWORD)) 
-    return ask_for_authentication (connection, REALM); 
-  
-  return secret_page (connection);
-}
-</pre>
 <p>See the <code>examples</code> directory for the complete example file.
 </p>
 <a name="Remarks-2"></a>
@@ -870,7 +832,7 @@
 failures of memory allocation are best reported as <em>internal server 
error</em> and unexpected 
 authentication methods as <em>400 bad request</em>.
 </p>
-<a name="Exercises-3"></a>
+<a name="Exercises-2"></a>
 <h2 class="heading">Exercises</h2>
 <ul>
 <li>
@@ -1404,7 +1366,7 @@
 <p>This is essentially the whole example <code>largepost.c</code>.
 </p>
 
-<a name="Remarks"></a>
+<a name="Remarks-1"></a>
 <h2 class="heading">Remarks</h2>
 <p>Now that the clients are able to create files on the server, security 
aspects are becoming even more
 important than before. Aside from proper client authentication, the server 
should always make sure
@@ -1557,8 +1519,20 @@
 <p>You can also use MHD to authenticate the client via SSL/TLS certificates
 (as an alternative to using the password-based Basic or Digest authentication).
 To do this, you will need to link your application against <em>gnutls</em>.
-For this, you first need to obtain the raw GnuTLS session handle from 
-<em>MHD</em> using <code>MHD_get_connection_info</code>.  
+Next, when you start the MHD daemon, you must specify the root CA that 
you&rsquo;re 
+willing to trust:
+</p><pre class="verbatim">  daemon = MHD_start_daemon 
(MHD_USE_SELECT_INTERNALLY | MHD_USE_SSL, 
+                            PORT, NULL, NULL,
+                             &amp;answer_to_connection, NULL, 
+                             MHD_OPTION_HTTPS_MEM_KEY, key_pem,
+                             MHD_OPTION_HTTPS_MEM_CERT, cert_pem,
+                            MHD_OPTION_HTTPS_MEM_TRUST, root_ca_pem,
+                             MHD_OPTION_END);
+</pre>
+<p>With this, you can then obtain client certificates for each session.
+In order to obtain the identity of the client, you first need to
+obtain the raw GnuTLS session handle from <em>MHD</em> using
+<code>MHD_get_connection_info</code>.
 </p>
 <pre class="verbatim">#include &lt;gnutls/gnutls.h&gt;
 #include &lt;gnutls/x509.h&gt;
@@ -2567,115 +2541,25 @@
 #include &lt;sys/socket.h&gt;
 #include &lt;microhttpd.h&gt;
 #include &lt;time.h&gt;
+#include &lt;string.h&gt;
+#include &lt;stdlib.h&gt;
+#include &lt;stdio.h&gt;
 
 #define PORT 8888
 
-#define REALM     &quot;\&quot;Maintenance\&quot;&quot;
-#define USER      &quot;a legitimate user&quot;
-#define PASSWORD  &quot;and his password&quot;
 
-
-char *string_to_base64 (const char *message);
-
-
 static int
-ask_for_authentication (struct MHD_Connection *connection, const char *realm)
-{
-  int ret;
-  struct MHD_Response *response;
-  char *headervalue;
-  const char *strbase = &quot;Basic realm=&quot;;
-
-  response = MHD_create_response_from_data (0, NULL, MHD_NO, MHD_NO);
-  if (!response)
-    return MHD_NO;
-
-  headervalue = malloc (strlen (strbase) + strlen (realm) + 1);
-  if (!headervalue)
-    return MHD_NO;
-
-  strcpy (headervalue, strbase);
-  strcat (headervalue, realm);
-
-  ret = MHD_add_response_header (response, &quot;WWW-Authenticate&quot;, 
headervalue);
-  free (headervalue);
-  if (!ret)
-    {
-      MHD_destroy_response (response);
-      return MHD_NO;
-    }
-
-  ret = MHD_queue_response (connection, MHD_HTTP_UNAUTHORIZED, response);
-
-  MHD_destroy_response (response);
-
-  return ret;
-}
-
-static int
-is_authenticated (struct MHD_Connection *connection,
-                  const char *username, const char *password)
-{
-  const char *headervalue;
-  char *expected_b64, *expected;
-  const char *strbase = &quot;Basic &quot;;
-  int authenticated;
-
-  headervalue =
-    MHD_lookup_connection_value (connection, MHD_HEADER_KIND,
-                                 &quot;Authorization&quot;);
-  if (NULL == headervalue)
-    return 0;
-  if (0 != strncmp (headervalue, strbase, strlen (strbase)))
-    return 0;
-
-  expected = malloc (strlen (username) + 1 + strlen (password) + 1);
-  if (NULL == expected)
-    return 0;
-
-  strcpy (expected, username);
-  strcat (expected, &quot;:&quot;);
-  strcat (expected, password);
-
-  expected_b64 = string_to_base64 (expected);
-  free (expected);
-  if (NULL == expected_b64)
-       return 0;
-
-  authenticated =
-    (strcmp (headervalue + strlen (strbase), expected_b64) == 0);
-
-  free (expected_b64);
-  return authenticated;
-}
-
-
-static int
-secret_page (struct MHD_Connection *connection)
-{
-  int ret;
-  struct MHD_Response *response;
-  const char *page = &quot;&lt;html&gt;&lt;body&gt;A 
secret.&lt;/body&gt;&lt;/html&gt;&quot;;
-
-  response =
-    MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
-                                   MHD_NO);
-  if (!response)
-    return MHD_NO;
-
-  ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
-  MHD_destroy_response (response);
-
-  return ret;
-}
-
-
-static int
 answer_to_connection (void *cls, struct MHD_Connection *connection,
                       const char *url, const char *method,
                       const char *version, const char *upload_data,
                       size_t *upload_data_size, void **con_cls)
 {
+  char *user;
+  char *pass;
+  int fail;
+  int ret;
+  struct MHD_Response *response;
+
   if (0 != strcmp (method, &quot;GET&quot;))
     return MHD_NO;
   if (NULL == *con_cls)
@@ -2683,11 +2567,33 @@
       *con_cls = connection;
       return MHD_YES;
     }
-
-  if (!is_authenticated (connection, USER, PASSWORD))
-    return ask_for_authentication (connection, REALM);
-
-  return secret_page (connection);
+  pass = NULL;
+  user = MHD_basic_auth_get_username_password (connection, &amp;pass);
+  fail = ( (user == NULL) ||
+          (0 != strcmp (user, &quot;root&quot;)) ||
+          (0 != strcmp (pass, &quot;pa$$w0rd&quot;) ) );  
+  if (user != NULL) free (user);
+  if (pass != NULL) free (pass);
+  if (fail)
+    {
+      const char *page = &quot;&lt;html&gt;&lt;body&gt;Go 
away.&lt;/body&gt;&lt;/html&gt;&quot;;
+      response =
+       MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
+                                      MHD_NO);
+      ret = MHD_queue_basic_auth_fail_response (connection,
+                                               &quot;my realm&quot;,
+                                               response);
+    }
+  else
+    {
+      const char *page = &quot;&lt;html&gt;&lt;body&gt;A 
secret.&lt;/body&gt;&lt;/html&gt;&quot;;
+      response =
+       MHD_create_response_from_data (strlen (page), (void *) page, MHD_NO,
+                                      MHD_NO);
+      ret = MHD_queue_response (connection, MHD_HTTP_OK, response);
+    }
+  MHD_destroy_response (response);
+  return ret;
 }
 
 
@@ -2706,45 +2612,6 @@
   MHD_stop_daemon (daemon);
   return 0;
 }
-
-
-char *
-string_to_base64 (const char *message)
-{
-  const char *lookup =
-    
&quot;ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/&quot;;
-  unsigned long l;
-  int i;
-  char *tmp;
-  size_t length = strlen (message);
-
-  tmp = malloc (length * 2);
-  if (NULL == tmp)
-    return tmp;
-
-  tmp[0] = 0;
-
-  for (i = 0; i &lt; length; i += 3)
-    {
-      l = (((unsigned long) message[i]) &lt;&lt; 16)
-        | (((i + 1) &lt; length) ? (((unsigned long) message[i + 1]) &lt;&lt; 
8) : 0)
-        | (((i + 2) &lt; length) ? ((unsigned long) message[i + 2]) : 0);
-
-
-      strncat (tmp, &amp;lookup[(l &gt;&gt; 18) &amp; 0x3F], 1);
-      strncat (tmp, &amp;lookup[(l &gt;&gt; 12) &amp; 0x3F], 1);
-
-      if (i + 1 &lt; length)
-        strncat (tmp, &amp;lookup[(l &gt;&gt; 6) &amp; 0x3F], 1);
-      if (i + 2 &lt; length)
-        strncat (tmp, &amp;lookup[l &amp; 0x3F], 1);
-    }
-
-  if (length % 3)
-    strncat (tmp, &quot;===&quot;, 3 - length % 3);
-
-  return tmp;
-}
 </pre></pre></td></tr></table>
 
 <hr size="6">
@@ -2794,7 +2661,7 @@
                        &lt;input type=\&quot;submit\&quot; value=\&quot; Send 
\&quot;&gt;&lt;/form&gt;\
                        &lt;/body&gt;&lt;/html&gt;&quot;;
 
-const char *greatingpage =
+const char *greetingpage =
   &quot;&lt;html&gt;&lt;body&gt;&lt;h1&gt;Welcome, 
%s!&lt;/center&gt;&lt;/h1&gt;&lt;/body&gt;&lt;/html&gt;&quot;;
 
 const char *errorpage =
@@ -2838,7 +2705,7 @@
           if (!answerstring)
             return MHD_NO;
 
-          snprintf (answerstring, MAXANSWERSIZE, greatingpage, data);
+          snprintf (answerstring, MAXANSWERSIZE, greetingpage, data);
           con_info-&gt;answerstring = answerstring;
         }
       else
@@ -3530,7 +3397,7 @@
 </tr></table>
 <h1>About This Document</h1>
 <p>
-  This document was generated by <em>Christian Grothoff</em> on <em>December 
25, 2010</em> using <a href="http://www.nongnu.org/texi2html/";><em>texi2html 
1.82</em></a>.
+  This document was generated by <em>Christian Grothoff</em> on <em>January 1, 
2011</em> using <a href="http://www.nongnu.org/texi2html/";><em>texi2html 
1.82</em></a>.
 </p>
 <p>
   The buttons in the navigation panels have the following meaning:
@@ -3632,7 +3499,7 @@
 <hr size="1">
 <p>
  <font size="-1">
-  This document was generated by <em>Christian Grothoff</em> on <em>December 
25, 2010</em> using <a href="http://www.nongnu.org/texi2html/";><em>texi2html 
1.82</em></a>.
+  This document was generated by <em>Christian Grothoff</em> on <em>January 1, 
2011</em> using <a href="http://www.nongnu.org/texi2html/";><em>texi2html 
1.82</em></a>.
  </font>
  <br>
 

Modified: libmicrohttpd-docs/WWW/tutorial.pdf
===================================================================
(Binary files differ)




reply via email to

[Prev in Thread] Current Thread [Next in Thread]