libmicrohttpd
[Top][All Lists]
Advanced

[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


reply via email to

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