[Top][All Lists]
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
Re: [libmicrohttpd] HTTP Authentication using libmicrohttpd
From: |
John Popplewell |
Subject: |
Re: [libmicrohttpd] HTTP Authentication using libmicrohttpd |
Date: |
Tue, 1 Jul 2008 23:21:47 +0100 |
User-agent: |
Mutt/1.5.8i |
Hi,
here's a sketch of how I did this for a site with a single hard-coded
user on a site-wide basis. I used libb64 from SourceForge to avoid
reinventing the Base64 encoding wheel.
Seemed to work OK with Firefox2 and IE6.
Hope it's of some use,
regards,
John.
===================================================================================
....
#include <cencode.h>
....
#define AUTH_REALM "Basic realm=\"Secure Area\""
#define USER_PASSWD "username:password"
....
static char *user_password_b64 = NULL; // holds the base64 encoded
version
....
static char *PAGE_401 =
"<html>\n"
"<head>\n"
"<meta http-equiv=\"content-type\" content=\"text/html;charset=iso-8859-1\">\n"
"<title>401 Unauthorised</title>\n"
"</head>\n"
"<body>\n"
"<blockquote>\n"
"<H1>Unauthorised</H1>\n"
"The request was denied: '%s'.\n"
"<p>\n"
"</body>\n"
"</html>\n";
static char *GetBasicAuthString(const char *user_passwd)
{
base64_encodestate state;
int len = strlen(user_passwd);
char *auth_b64;
char *p;
// construct base64 representation of username/password
auth_b64 = malloc(len*2);
base64_init_encodestate(&state);
len = base64_encode_block(user_passwd, len, auth_b64, &state);
base64_encode_blockend(auth_b64 + len, &state);
// remove trailing LF, if present
p = strrchr(auth_b64, '\n');
if (p) *p = 0;
return auth_b64;
}
static int Send401(struct MHD_Connection *connection, const char *msg)
{
struct MHD_Response *response;
int ret;
int len;
char *buff;
len = snprintf(NULL, 0, PAGE_401, msg);
buff = malloc(len+1);
sprintf(buff, PAGE_401, msg);
response = MHD_create_response_from_data(len, buff, MHD_YES, MHD_NO);
MHD_add_response_header(response, "WWW-Authenticate", AUTH_REALM);
ret = MHD_queue_response(connection, 401, response);
MHD_destroy_response(response);
return ret;
}
static int authenticationOK(struct MHD_Connection *connection, const char *url)
{
const char *user_passwd = MHD_lookup_connection_value(connection,
MHD_HEADER_KIND, "Authorization");
int len;
char *auth_string;
int res;
if (!user_passwd) return 0;
len = snprintf(NULL, 0, "Basic %s", user_password_b64);
auth_string = malloc(len+1);
sprintf(auth_string , "Basic %s", user_password_b64);
res = !strcmp(user_passwd, auth_string);
free(auth_string);
return res;
}
static int AccessHandler(void *cls, struct MHD_Connection *connection, const
char *url,
const char *method, const char *upload_data, const
char *version,
unsigned int *upload_data_size, void **ptr)
{
static int aptr;
const char *url_ = url;
if (0 != strcmp(method, "GET"))
return MHD_NO; // unexpected method
if (&aptr != *ptr)
{
*ptr = &aptr; // never respond on first call
return MHD_YES;
}
*ptr = NULL; // reset when done
if (!authenticationOK(connection, url_))
{
return Send401(connection, "Not authorised");
}
if (0 == strcmp(url_, "/"))
{
url_ = DEFAULT_PAGE;
}
if (0 == strcmp(url_, DEFAULT_PAGE))
{
return HandleMainPage(connection, url_);
}
.....
}
static int run_main_app(void)
{
....
user_password_b64 = GetBasicAuthString(USER_PASSWD);
....
while (1)
{
....
}
....
free(user_password_b64);
....
}
int main(int argc, char *argv[])
{
struct MHD_Daemon *d;
d = MHD_start_daemon(MHD_USE_THREAD_PER_CONNECTION, HTTPD_PORT,
NULL, NULL, &AccessHandler, &dummy, MHD_OPTION_END);
if (d == NULL)
{
fprintf(stderr, "Failed to start libmicrohttpd.");
return -1;
}
run_main_app();
MHD_stop_daemon(d);
return 0;
}
On Tue, Jul 01, 2008 at 10:33:11PM +0200, Sebastian wrote:
> Hello,
>
>
> > I need to write an application which can authenticate a user against
> > stored passwords in a file. I need to know if I can do this using
> > libmicrohttpd or not?
>
> Yes, you can.
> But you have to understand that this library still expects _you_ to fill
> the http headers with the appropriate content. For example, your
> application would respond on the first request of a new connection with
> an "Authorization" header containing the accepted encryption (e.g.
> BASIC) and the realm (e.g. "Secret Area"). It is then your application's
> responsibilty to check the content of the answer for the proper
> authentication. It then can "remember" that this connection already has
> been authenticated or it is free to challenge the connecting client
> again. This is up to you.
>
> But what you will have to do by all means is to read the RFCs describing
> these mechanisms in great detail (and pretty mandatory). They are to be
> followed for compatible behaviour of your application. For basic
> authentication this would be rfc2617.
>
>
> Hope that helps
>
> Sebastian
>
> _______________________________________________
> libmicrohttpd mailing list
> address@hidden
> http://crisp.cs.du.edu/cgi-bin/mailman/listinfo/libmicrohttpd