Browse Source

added a first basic athentication system with ldap binding. Now login depends on the existens of a valid ldap account

master
Georg Hopp 14 years ago
parent
commit
5fc9ce547c
  1. 6
      assets/html/main.html
  2. 4
      assets/style/common.css
  3. 45
      include/auth.h
  4. 19
      include/auth/ldap.h
  5. 8
      include/commons.h
  6. 32
      include/credential.h
  7. 1
      include/http/message.h
  8. 1
      include/http/parser.h
  9. 2
      include/http/worker.h
  10. 49
      include/interface/auth.h
  11. 14
      src/Makefile.am
  12. 88
      src/auth/ldap.c
  13. 64
      src/credential.c
  14. 3
      src/http/message.c
  15. 2
      src/http/parser/body.c
  16. 4
      src/http/parser/header.c
  17. 4
      src/http/parser/post_vars.c
  18. 3
      src/http/worker.c
  19. 45
      src/http/worker/process.c
  20. 4
      src/http/writer/write.c
  21. 42
      src/interface/auth.c
  22. 2
      src/interface/http_intro.c
  23. 2
      src/interface/subject.c
  24. 9
      src/webgameserver.c

6
assets/html/main.html

@ -21,7 +21,11 @@
</div>
<div id="login" class="hide">
<form>
<input type="text" name="username" />
<label for="username">username</label>
<input type="text" name="username" /><br />
<label for="password">password</label>
<input type="password" name="password" /><br />
<input type="submit" />
</form>
</div>
<div id="randval" class="hide">

4
assets/style/common.css

@ -9,7 +9,11 @@ div#randval {
}
div#login {
padding: 5px;
position: fixed;
background-color: white;
border: 1px solid black;
border-radius: 10px;
}
div.hide {

45
include/auth.h

@ -0,0 +1,45 @@
/**
* \file
* Authenticatio module factory
*
* A factory to get a specific authentication module.
* An authentication module is a class that implement the Auth interface.
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2012 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __AUTH_H__
#define __AUTH_H__
#include "class.h"
#include "auth/ldap.h"
typedef enum e_AuthModule {
AUTH_LDAP = 0
} AuthModule;
CLASS(Auth) {
};
void * authCreateById(Auth, int);
AuthLdap authCreateLdap(Auth);
#endif // __AUTH_H__
// vim: set ts=4 sw=4:

19
include/auth/ldap.h

@ -0,0 +1,19 @@
#ifndef __AUTH_LDAP_H__
#define __AUTH_LDAP_H__
#include <ldap.h>
#include <sys/types.h>
#include "class.h"
CLASS(AuthLdap) {
LDAP * ldap;
char * url;
char * base_dn;
int version;
size_t nbase_dn;
};
#endif // __AUTH_LDAP_H__
// vim: set ts=4 sw=4:

8
include/commons.h

@ -5,6 +5,14 @@
#define TRUE 1
#define FALSE 0
#ifndef MAX
# define MAX(a,b) ((a)>(b)? (a) : (b))
#endif
#ifndef MIN
# define MIN(a,b) ((a)<(b)? (a) : (b))
#endif
#define SWAP_FUN(a, b) ((a)^=(b),(b)^=(a),(a)^=(b))
#define SWAP(type, a, b) do { \

32
include/credential.h

@ -0,0 +1,32 @@
#ifndef __CREDENTIAL_H__
#define __CREDENTIAL_H__
#include <sys/types.h>
#include "class.h"
#define CRED_PWD(c) (((c)->cred).pwd)
typedef enum e_CredentialType {
CRED_PASSWORD = 0
} CredentialType;
CLASS(Credential) {
CredentialType type;
union {
struct {
char * user;
size_t nuser;
char * pass;
size_t npass;
} pwd;
} cred;
};
#endif // __CREDENTIAL_H__
// vim: set ts=4 sw=4:

1
include/http/message.h

@ -38,6 +38,7 @@ CLASS(HttpMessage) {
char * version;
Hash header;
Hash cookies;
HttpMessageType type;
Stream handle;

1
include/http/parser.h

@ -58,6 +58,7 @@ CLASS(HttpParser) {
};
ssize_t httpParserParse(void *, Stream);
void httpParserRequestVars(HttpParser);
void httpParserHeader(HttpParser, const char *, const char *);
void httpParserNewMessage(HttpParser, const char *, const char * lend);
size_t httpParserBody(HttpParser, const char *, size_t);

2
include/http/worker.h

@ -52,6 +52,8 @@ CLASS(HttpWorker) {
HttpWriter writer;
Session session;
Session * sroot;
void * auth;
};
#endif // __HTTP_WORKER_H__

49
include/interface/auth.h

@ -0,0 +1,49 @@
/**
* \file
* The authentication interface.
*
* This is the authentication interface. It's only pupose is to
* authenticate someone or somewhat. It is called AUTH.
* The concrete access rights are managed within a class called ACL.
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2012 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef __INTERFACE_AUTH_H__
#define __INTERFACE_AUTH_H__
#include <stdarg.h>
#include "interface.h"
#include "credential.h"
typedef int (* fptr_authenticate)(void *, Credential);
extern const struct interface i_Auth;
struct i_Auth {
const struct interface * const _;
fptr_authenticate authenticate;
};
extern int authenticate(void *, Credential);
#endif // __INTERFACE_AUTH_H__
// vim: set ts=4 sw=4:

14
src/Makefile.am

@ -6,13 +6,8 @@ IFACE = interface/class.c interface/stream_reader.c interface/logger.c \
interface/subject.c interface/observer.c interface.c
SOCKET = socket.c socket/accept.c socket/connect.c socket/listen.c
STREAM = stream.c stream/read.c stream/write.c
HASH = hash.c \
hash/add.c \
hash/get.c \
hash/delete.c \
hash/each.c \
interface/hashable.c \
hash_value.c
HASH = hash.c hash/add.c hash/get.c hash/delete.c \
hash/each.c interface/hashable.c hash_value.c
SERVER = server.c server/run.c server/close_conn.c server/poll.c \
server/handle_accept.c server/read.c server/write.c
LOGGER = logger.c logger/stderr.c logger/syslog.c
@ -61,6 +56,7 @@ UTILS = utils/hash.c \
utils/http.c \
utils/daemonize.c \
utils/signalHandling.c
AUTH = interface/auth.c auth/ldap.c credential.c
AM_CFLAGS = -Wall -I ../include/
@ -70,6 +66,6 @@ bin_PROGRAMS = webgameserver
webgameserver_SOURCES = webgameserver.c \
$(IFACE) $(SOCKET) $(SERVER) $(LOGGER) $(MSG) $(REQ) \
$(WRITER) $(RESP) $(HEADER) $(PARSER) $(WORKER) $(CB) \
$(UTILS) $(MSGQ) $(SESSION) $(STREAM) $(HASH)
$(UTILS) $(MSGQ) $(SESSION) $(STREAM) $(HASH) $(AUTH)
webgameserver_CFLAGS = -Wall -I ../include/
webgameserver_LDFLAGS = -lrt -lssl
webgameserver_LDFLAGS = -lrt -lssl -lldap

88
src/auth/ldap.c

@ -0,0 +1,88 @@
#include <stdarg.h>
#include <stdlib.h>
#include <string.h>
#include <stdio.h>
#include <ldap.h>
#include "auth/ldap.h"
#include "class.h"
#include "credential.h"
#include "interface/class.h"
#include "interface/auth.h"
#include "utils/memory.h"
#include "commons.h"
static
int
authLdapCtor(void * _this, va_list * params)
{
AuthLdap this = _this;
char * url = va_arg(*params, char*);
char * base_dn;
this->url = malloc(strlen(url) + 1);
strcpy(this->url, url);
this->version = 3;
base_dn = va_arg(* params, char *);
this->nbase_dn = va_arg(* params, size_t);
this->base_dn = malloc(this->nbase_dn + 1);
this->base_dn[this->nbase_dn] = 0;
memcpy(this->base_dn, base_dn, this->nbase_dn);
return 0;
}
static
void
authLdapDtor(void * _this)
{
AuthLdap this = _this;
FREE(this->base_dn);
FREE(this->url);
}
static
int
authLdapAuthenticate(void * _this, Credential cred)
{
AuthLdap this = _this;
char who[256];
char * who_ptr = who;
int ldap_err;
if (CRED_PASSWORD != cred->type) {
return FALSE;
}
ldap_initialize(&(this->ldap), this->url);
ldap_set_option(this->ldap, LDAP_OPT_PROTOCOL_VERSION, &(this->version));
memcpy(who_ptr, "cn=", sizeof("cn=") - 1);
who_ptr += sizeof("cn=") - 1;
memcpy(who_ptr, CRED_PWD(cred).user, CRED_PWD(cred).nuser);
who_ptr += CRED_PWD(cred).nuser;
*who_ptr++ = ',';
memcpy(who_ptr, this->base_dn, this->nbase_dn);
who_ptr[this->nbase_dn] = 0;
ldap_err = ldap_simple_bind_s(this->ldap, who, CRED_PWD(cred).pass);
if (0 == ldap_err) {
ldap_unbind_s(this->ldap);
//! \todo here we need to get and return the user id
return TRUE;
}
fprintf(stderr, "%s\n", ldap_err2string(ldap_err));
return FALSE;
}
INIT_IFACE(Class, authLdapCtor, authLdapDtor, NULL);
INIT_IFACE(Auth, authLdapAuthenticate);
CREATE_CLASS(AuthLdap, NULL, IFACE(Class), IFACE(Auth));
// vim: set ts=4 sw=4:

64
src/credential.c

@ -0,0 +1,64 @@
#include <stdarg.h>
#include <sys/types.h>
#include <stdlib.h>
#include <string.h>
#include "credential.h"
#include "class.h"
#include "interface/class.h"
#include "utils/memory.h"
static
int
credentialCtor(void * _this, va_list * params)
{
Credential this = _this;
this->type = va_arg(* params, CredentialType);
switch(this->type) {
case CRED_PASSWORD:
{
char * user, *pass;
user = va_arg(* params, char*);
CRED_PWD(this).nuser = va_arg(* params, size_t);
pass = va_arg(* params, char*);
CRED_PWD(this).npass = va_arg(* params, size_t);
CRED_PWD(this).user = malloc(CRED_PWD(this).nuser + 1);
CRED_PWD(this).user[CRED_PWD(this).nuser] = 0;
memcpy(CRED_PWD(this).user, user, CRED_PWD(this).nuser);
CRED_PWD(this).pass = malloc(CRED_PWD(this).npass + 1);
CRED_PWD(this).pass[CRED_PWD(this).npass] = 0;
memcpy(CRED_PWD(this).pass, pass, CRED_PWD(this).npass);
}
break;
default:
return -1;
}
return 0;
}
static
void
credentialDtor(void * _this)
{
Credential this = _this;
switch(this->type) {
case CRED_PASSWORD:
FREE(CRED_PWD(this).user);
FREE(CRED_PWD(this).pass);
break;
}
}
INIT_IFACE(Class, credentialCtor, credentialDtor, NULL);
CREATE_CLASS(Credential, NULL, IFACE(Class));
// vim: set ts=4 sw=4:

3
src/http/message.c

@ -48,6 +48,7 @@ httpMessageCtor(void * _this, va_list * params)
strcpy(this->version, version);
this->header = new(Hash);
this->cookies = new(Hash);
return 0;
}
@ -59,6 +60,8 @@ httpMessageDtor(void * _this)
HttpMessage this = _this;
delete(this->header);
delete(this->cookies);
FREE(this->version);
switch (this->type) {

2
src/http/parser/body.c

@ -28,7 +28,7 @@
#include "http/parser.h"
#include "cbuf.h"
#define MIN(a,b) (((a) < (b))? (a) : (b))
#include "commons.h"
size_t
httpParserBody(HttpParser this, const char * buf, size_t nbuf)

4
src/http/parser/header.c

@ -72,7 +72,7 @@ httpParserHeader(
if (0 == strncasecmp("cookie", name, nname-1)) {
HttpRequest request = (HttpRequest)this->current;
char * pair = value;
size_t togo = lend - value;
ssize_t togo = lend - value;
while(NULL != pair && 0 < togo) {
char * key = pair;
@ -100,8 +100,8 @@ httpParserHeader(
hashAdd(request->cookies,
new(HashValue, key, eqsign-key, val, nval));
togo -= (pair - eqsign);
pair++;
togo -= (pair - eqsign);
}
}

4
src/http/parser/post_vars.c

@ -17,7 +17,7 @@ httpParserPostVars(HttpParser this)
{
HttpRequest request = (HttpRequest)this->current;
char * pair = this->current->body;
size_t togo = this->current->nbody;
ssize_t togo = this->current->nbody;
while(NULL != pair && 0 < togo) {
char * key = pair;
@ -42,8 +42,8 @@ httpParserPostVars(HttpParser this)
hashAdd(request->post,
new(HashValue, key, eqsign-key, value, nvalue));
togo -= (pair - eqsign);
pair++;
togo -= (pair - eqsign);
}
}

3
src/http/worker.c

@ -64,6 +64,8 @@ httpWorkerCtor(void * _this, va_list * params)
this->sroot = &(this->session);
this->auth = va_arg(* params, void *);
return 0;
}
@ -106,6 +108,7 @@ httpWorkerClone(void * _this, void * _base)
this->writer = new(HttpWriter, base->wbuf);
this->sroot = &(base->session);
this->auth = base->auth;
}
ssize_t httpWorkerProcess(void *, Stream);

45
src/http/worker/process.c

@ -28,6 +28,7 @@
#include "class.h"
#include "interface/class.h"
#include "interface/auth.h"
#include "http/worker.h"
#include "http/header.h"
@ -40,13 +41,17 @@
#include "stream.h"
#include "hash_value.h"
#include "hash.h"
#include "credential.h"
#include "utils/memory.h"
#include "hash.h"
#include "commons.h"
HttpMessage httpWorkerGetAsset(HttpRequest, const char *, const char *, size_t);
void httpWorkerAddCommonHeader(HttpMessage, HttpMessage);
ssize_t
httpWorkerProcess(HttpWorker this, Stream st)
{
@ -96,16 +101,50 @@ httpWorkerProcess(HttpWorker this, Stream st)
size_t nbuf;
HashValue username = hashGet(request->post, CSTRA("username"));
HashValue password = hashGet(request->post, CSTRA("password"));
/**
* \todo This is an application authorization not an HTTP
* authorization...anyway think about sending HTTP 401
* messages if authorization is required and think about
* sending the credentials via header as described in the
* HTTP protocol. Most likely this will lead to hacky thing
* with javascript as i am not sure how far this is implemented
* within browsers.
* Anyway, for now we simply ignore a failed login within the
* response except that no session is initialized. We send
* an empty 200 OK
*/
if (NULL == password || NULL == username) {
response = new(HttpResponse, "HTTP/1.1", 200, "OK");
}
if (NULL == response) {
Credential cred = new(Credential,
CRED_PASSWORD,
(char*)(username->value), username->nvalue,
(char*)(password->value), password->nvalue);
if (!authenticate(this->auth, cred)) {
response = new(HttpResponse, "HTTP/1.1", 200, "OK");
} else {
this->session = sessionAdd(
this->sroot,
new(Session, username->value, username->nvalue));
nbuf = sprintf(buffer, "sid=%lu;Path=/", this->session->id);
nbuf = sprintf(buffer,
"sid=%lu;Path=/",
this->session->id);
response = (HttpMessage)httpResponseSession(this->session);
response = (HttpMessage)httpResponseSession(
this->session);
hashAdd(response->header,
new(HttpHeader, CSTRA("Set-Cookie"), buffer, nbuf));
new(HttpHeader,
CSTRA("Set-Cookie"),
buffer, nbuf));
}
delete(cred);
}
}
}

4
src/http/writer/write.c

@ -30,8 +30,8 @@
#include "cbuf.h"
#include "stream.h"
#define MIN(x,y) ((x) < (y) ? (x) : (y))
#define MAX(x,y) ((x) > (y) ? (x) : (y))
#include "commons.h"
ssize_t
httpWriterWrite(void * _this, Stream st)

42
src/interface/auth.c

@ -0,0 +1,42 @@
/**
* \file
*
* \author Georg Hopp
*
* \copyright
* Copyright © 2012 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "auth.h"
#include "credential.h"
#include "interface/auth.h"
const struct interface i_Auth = {
"auth",
1
};
int
authenticate(void * auth, Credential cred)
{
int ret;
RETCALL(auth, Auth, authenticate, ret, cred);
return ret;
}
// vim: set ts=4 sw=4:

2
src/interface/http_intro.c

@ -4,7 +4,7 @@
* \author Georg Hopp
*
* \copyright
* Copyright (C) 2012 Georg Hopp
* Copyright © 2012 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

2
src/interface/subject.c

@ -4,7 +4,7 @@
* \author Georg Hopp
*
* \copyright
* Copyright (C) 2012 Georg Hopp
* Copyright © 2012 Georg Hopp
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by

9
src/webgameserver.c

@ -38,11 +38,13 @@
#include "server.h"
#include "logger.h"
#include "http/worker.h"
#include "auth/ldap.h"
#include "interface/class.h"
#include "interface/logger.h"
#include "utils/signalHandling.h"
#include "utils/memory.h"
#define DEFAULT_SECS 10
//#define DEFAULT_USECS (1000000 / HZ * 2)
@ -126,6 +128,7 @@ main()
default:
{
Logger logger;
AuthLdap auth;
HttpWorker worker;
Server server;
@ -136,7 +139,10 @@ main()
close(shm);
logger = new(LoggerSyslog, LOGGER_ERR);
worker = new(HttpWorker, "testserver", value);
auth = new(AuthLdap,
"ldap://localhost/",
CSTRA("ou=user,dc=yabrog,dc=weird-web-workers,dc=org"));
worker = new(HttpWorker, "testserver", value, auth);
server = new(Server, logger, worker, 11212, SOMAXCONN);
//daemonize();
@ -184,6 +190,7 @@ main()
if (NULL != server) delete(server);
if (NULL != worker) delete(worker);
if (NULL != auth) delete(auth);
if (NULL != logger) delete(logger);
}

Loading…
Cancel
Save