Skip to content
This repository has been archived by the owner on Mar 12, 2019. It is now read-only.

Commit

Permalink
Browse files Browse the repository at this point in the history
…into wendal-master

Added example python api
removed included Mosquitto code
slight cleanup of README
	closes #35
	closes 28
  • Loading branch information
jpmens committed Nov 3, 2014
2 parents 60fd7cf + 2fda787 commit 368ff61
Show file tree
Hide file tree
Showing 6 changed files with 381 additions and 9 deletions.
18 changes: 16 additions & 2 deletions Makefile.orig
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ BACKEND_SQLITE ?= no
BACKEND_REDIS ?= no
BACKEND_POSTGRES ?= yes
BACKEND_LDAP ?= yes
BACKEND_HTTP ?= no

BE_CFLAGS =
BE_LDFLAGS =
Expand All @@ -14,7 +15,7 @@ OBJS = auth-plug.o base64.o pbkdf2-check.o log.o hash.o be-psk.o backends.o cach

BACKENDS =
BACKENDSTR =
MOSQUITTO_SRC =
MOSQUITTO_SRC =

ifneq ($(BACKEND_CDB),no)
BACKENDS += -DBE_CDB
Expand Down Expand Up @@ -75,13 +76,22 @@ ifneq ($(BACKEND_LDAP),no)
OBJS += be-ldap.o
endif

ifneq ($(BACKEND_HTTP), no)
BACKENDS+= -DBE_HTTP
BE_LDADD += -lcurl
OBJS += be-http.o
endif

OPENSSLDIR = /usr
OSSLINC = -I$(OPENSSLDIR)/include
OSSLIBS = -L$(OPENSSLDIR)/lib -lcrypto

CFLAGS = -I$(MOSQUITTO_SRC)/src/
CFLAGS += -I$(MOSQUITTO_SRC)/lib/
CFLAGS += -fPIC -Wall -Werror $(BACKENDS) $(BE_CFLAGS) -I$(MOSQ)/src -DDEBUG=1 $(OSSLINC)
ifneq ($(OS),Windows_NT)
CFLAGS += -fPIC -Wall -Werror
endif
CFLAGS += $(BACKENDS) $(BE_CFLAGS) -I$(MOSQ)/src -DDEBUG=1 $(OSSLINC)
LDFLAGS = $(BE_LDFLAGS) -L$(MOSQUITTO_SRC)/lib/
# LDFLAGS += -Wl,-rpath,$(../../../../pubgit/MQTT/mosquitto/lib) -lc
# LDFLAGS += -export-dynamic
Expand Down Expand Up @@ -113,7 +123,11 @@ base64.o: base64.c base64.h Makefile
log.o: log.c log.h Makefile
hash.o: hash.c hash.h uthash.h Makefile
be-postgres.o: be-postgres.c be-postgres.h Makefile
<<<<<<< HEAD:Makefile.orig
cache.o: cache.c cache.h uthash.h Makefile
=======
be-http.o: be-http.c be-http.h Makefile
>>>>>>> 2fda787f0ab2994b0e339a78d8808385519c934d:Makefile

np: np.c base64.o
$(CC) $(CFLAGS) $^ -o $@ $(OSSLIBS)
Expand Down
53 changes: 47 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,23 +4,26 @@ This is a plugin to authenticate and authorize [Mosquitto] users from one
of several distinct back-ends:

* MySQL
* PostgreSQL
* CDB
* SQLite3 database
* [Redis] key/value store
* TLS PSK (the `psk` back-end is a bit of a shim which piggy-backs onto the other database back-ends)
* LDAP
* HTTP (custom HTTP API)

## Introduction

This plugin can perform authentication (check username / password)
and authorization (ACL). Currently not all back-ends have the same capabilities
(the the section on the back-end you're interested in).

| Capability | mysql | redis | cdb | sqlite | ldap | psk | postgres |
| -------------------------- | :---: | :---: | :---: | :---: | :-: | :-: | :------: |
| authentication | Y | Y | Y | Y | Y | Y | Y |
| superusers | Y | | | | | 2 | Y |
| acl checking | Y | 1 | 1 | 1 | | 2 | Y |
| static superusers | Y | Y | Y | Y | | 2 | Y |
| Capability | mysql | redis | cdb | sqlite | ldap | psk | postgres | http |
| -------------------------- | :---: | :---: | :---: | :---: | :-: | :-: | :------: | :--: |
| authentication | Y | Y | Y | Y | Y | Y | Y | Y |
| superusers | Y | | | | | 2 | Y | Y |
| acl checking | Y | 1 | 1 | 1 | | 2 | Y | Y |
| static superusers | Y | Y | Y | Y | | 2 | Y | Y |

1. Currently not implemented; back-end returns TRUE
2. Dependent on the database used by PSK
Expand Down Expand Up @@ -286,6 +289,44 @@ auth_opt_ldap_uri ldap:https://127.0.0.1/ou=Users,dc=mens,dc=de?cn?sub?(&(objectclass=
| redis_host | localhost | | hostname / IP address
| redis_port | 6379 | | TCP port number |

### HTTP

The `http` back-end is for auth by custom HTTP API.

The following `auth_opt_` options are supported by the `http` back-end:

| Option | default | Mandatory | Meaning |
| ----------------- | ----------------- | :---------: | ---------- |
| http_ip | | Y | IP address,will skip dns lookup |
| http_port | 80 | | TCP port number |
| http_hostname | | | hostname for HTTP header |
| http_getuser_uri | | Y | URI for check username/password |
| http_superuser_uri| | Y | URI for check superuser |
| http_aclcheck_uri | | Y | URI for check acl |

If the configured URLs return an HTTP status code == `200`, the authentication /
authorization succeeds, else it fails.

| URI-Param | username | password | topic | acc |
| ----------------- | -------- | -------- | :---: | :-: |
| http_getuser_uri | Y | Y | N | N |
| http_superuser_uri| Y | N | N | N |
| http_aclcheck_uri | Y | N | Y | Y |

Mosquitto configuration for the `http` back-end:

```
auth_opt_backends http
auth_opt_http_ip 127.0.0.1
auth_opt_http_port 8089
#auth_opt_http_hostname example.org
auth_opt_http_getuser_uri /auth
auth_opt_http_superuser_uri /superuser
auth_opt_http_aclcheck_uri /acl
```

A very simple example service using Python and bottle can be found in [examples/http-auth-be.py](examples/http-auth-be.py).

### PostgreSQL

The `postgres` like `mysql` back-end is currently the most feature-complete: it supports
Expand Down
21 changes: 20 additions & 1 deletion auth-plug.c
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
#include "be-redis.h"
#include "be-postgres.h"
#include "be-ldap.h"
#include "be-http.h"

#include "userdata.h"
#include "cache.h"
Expand Down Expand Up @@ -297,6 +298,25 @@ int mosquitto_auth_plugin_init(void **userdata, struct mosquitto_auth_opt *auth_
PSKSETUP;
}
#endif

#if BE_HTTP
if (!strcmp(q, "http")) {
*bep = (struct backend_p *)malloc(sizeof(struct backend_p));
memset(*bep, 0, sizeof(struct backend_p));
(*bep)->name = strdup("http");
(*bep)->conf = be_http_init();
if ((*bep)->conf == NULL) {
_fatal("%s init returns NULL", q);
}
(*bep)->kill = be_http_destroy;
(*bep)->getuser = be_http_getuser;
(*bep)->superuser = be_http_superuser;
(*bep)->aclcheck = be_http_aclcheck;
found = 1;
ud->fallback_be = ud->fallback_be == -1 ? nord : ud->fallback_be;
PSKSETUP;
}
#endif
if (!found) {
_fatal("ERROR: configured back-end `%s' is not compiled in this plugin", q);
}
Expand Down Expand Up @@ -537,4 +557,3 @@ int mosquitto_auth_psk_key_get(void *userdata, const char *hint, const char *ide
return MOSQ_ERR_AUTH;
#endif /* BE_PSK */
}

186 changes: 186 additions & 0 deletions be-http.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,186 @@
/*
* Copyright (c) 2013 Jan-Piet Mens <jpmens()gmail.com> wendal <wendal1985()gmai.com>
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions are met:
*
* 1. Redistributions of source code must retain the above copyright notice,
* this list of conditions and the following disclaimer.
* 2. Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in the
* documentation and/or other materials provided with the distribution.
* 3. Neither the name of mosquitto nor the names of its
* contributors may be used to endorse or promote products derived from
* this software without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
* AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
* ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
* LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
* CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/

#ifdef BE_HTTP
#include "backends.h"
#include "be-http.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "hash.h"
#include "log.h"
#include <curl/curl.h>

static int http_post(void *handle, char *uri, const char *username,const char *password, const char *topic, int acc)
{
struct http_backend *conf = (struct http_backend *)handle;
struct curl_slist *headerlist=NULL;
int re;
int respCode = 0;
int ok = FALSE;
char *url;
char *data;

if (username == NULL) {
return (FALSE);
}
if (password == NULL)
password = "";

if (topic == NULL)
topic = "";

CURL *curl = curl_easy_init();
if (NULL == curl) {
_fatal("create easy_handle fail");
return (FALSE);
}
if (conf->hostheader != NULL)
curl_slist_append(headerlist, conf->hostheader);
curl_slist_append(headerlist, "Expect:");

//_log(LOG_NOTICE, "u=%s p=%s t=%s acc=%d", username, password, topic, acc);

url = (char *)malloc(1024);
data = (char *)malloc(1024);
sprintf(data, "username=%s&password=%s&topic=%s&acc=%d",
curl_easy_escape(curl, username, 0),
curl_easy_escape(curl, password, 0),
curl_easy_escape(curl, topic, 0),
acc);

sprintf(url, "https://%s:%d%s", conf->ip, conf->port, strdup(uri));

_log(LOG_DEBUG, "url=%s", url);
// curl_easy_setopt(curl, CURLOPT_VERBOSE, 1L);

curl_easy_setopt(curl, CURLOPT_URL, url);
curl_easy_setopt(curl, CURLOPT_POST, 1L);
curl_easy_setopt(curl, CURLOPT_POSTFIELDS, data);
curl_easy_setopt(curl, CURLOPT_HTTPHEADER, headerlist);
curl_easy_setopt(curl, CURLOPT_TIMEOUT, 1);

re = curl_easy_perform(curl);
if (re == CURLE_OK) {
re = curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &respCode);
if (re == CURLE_OK && respCode == 200) {
ok = TRUE;
} else {
//_log(LOG_NOTICE, "http auth fail re=%d respCode=%d", re, respCode);
}
} else {
_log(LOG_DEBUG, "http req fail url=%s re=%s", url, curl_easy_strerror(re));
}

curl_easy_cleanup(curl);
curl_slist_free_all (headerlist);
free(url);
free(data);
return (ok);
}


void *be_http_init() {
struct http_backend *conf;
char *ip;
char *getuser_uri;
char *superuser_uri;
char *aclcheck_uri;

if (curl_global_init(CURL_GLOBAL_ALL) != CURLE_OK) {
_fatal("init curl fail");
return (NULL);
}

if ((ip = p_stab("http_ip")) == NULL) {
_fatal("Mandatory parameter `http_ip' missing");
return (NULL);
}
if ((getuser_uri = p_stab("http_getuser_uri")) == NULL) {
_fatal("Mandatory parameter `http_getuser_uri' missing");
return (NULL);
}
if ((superuser_uri = p_stab("http_superuser_uri")) == NULL) {
_fatal("Mandatory parameter `http_superuser_uri' missing");
return (NULL);
}
if ((aclcheck_uri = p_stab("http_aclcheck_uri")) == NULL) {
_fatal("Mandatory parameter `http_aclcheck_uri' missing");
return (NULL);
}
conf = (struct http_backend *)malloc(sizeof(struct http_backend));
conf->ip = ip;
conf->port = p_stab("http_port") == NULL ? 80 : atoi(p_stab("http_port"));
if (p_stab("http_hostname") != NULL) {
conf->hostheader = (char *)malloc(128);
sprintf(conf->hostheader, "Host: %s", p_stab("http_hostname"));
} else {
conf->hostheader = NULL;
}
conf->getuser_uri = getuser_uri;
conf->superuser_uri = superuser_uri;
conf->aclcheck_uri = aclcheck_uri;

_log(LOG_DEBUG, "getuser_uri=%s", getuser_uri);
_log(LOG_DEBUG, "superuser_uri=%s", superuser_uri);
_log(LOG_DEBUG, "aclcheck_uri=%s", aclcheck_uri);

return conf;
};
void be_http_destroy(void *handle){
struct http_backend *conf = (struct http_backend *)handle;
if (conf) {
curl_global_cleanup();
free(conf);
}
};
char *be_http_getuser(void *handle, const char *username, const char *password, int *authenticated) {
struct http_backend *conf = (struct http_backend *)handle;
int re;
if (username == NULL) {
return NULL;
}
re = http_post(handle, conf->getuser_uri, username, password, NULL, -1);
if (re == 1) {
*authenticated = 1;
}
return NULL;
};
int be_http_superuser(void *handle, const char *username){
struct http_backend *conf = (struct http_backend *)handle;
return http_post(handle, conf->superuser_uri, username, NULL, NULL, -1);
};
int be_http_aclcheck(void *handle, const char *clientid, const char *username, const char *topic, int acc)
{
struct http_backend *conf = (struct http_backend *)handle;

/* FIXME: support clientid */
return http_post(conf, conf->aclcheck_uri, username, NULL, topic, acc);
};
#endif /* BE_HTTP */
Loading

0 comments on commit 368ff61

Please sign in to comment.