+++ /dev/null
-###########################################################################
-# Copyright 2015, 2016, 2017 IoT.bzh
-#
-# author: Loïc Collignon <loic.collignon@iot.bzh>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-###########################################################################
-
-cmake_minimum_required(VERSION 3.3)
-project(idkey)
-add_executable(idkey main.c)
-install(TARGETS idkey
- RUNTIME DESTINATION bin
- LIBRARY DESTINATION lib)
+++ /dev/null
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-
-#define EXIT_SUCCESS 0
-#define EXIT_CMDLINE 1
-#define EXIT_FILEOPEN 2
-#define EXIT_FILEREAD 3
-#define EXIT_FILEWRITE 4
-#define EXIT_INVALID 5
-#define EXIT_ALLOC 6
-
-#define BLOCK_SIZE 4096
-
-/// @brief Header of the datas.
-typedef struct header_
-{
- char mn[4];
- size_t size;
-} header;
-
-/// @brief Check if the @c v is a valid magick number.
-/// @param[in] v magick number.
-/// @return 1 if valid, zero otherwise.
-int is_valid_nm(const char* v)
-{
- return v && v[0] == 'I' && v[1] == 'D' && v[2] == 'K' && v[3] == 'Y';
-}
-
-/// @brief Close the file descriptor if valid then print a formatted error message then return the specified code.
-/// @param[in] fd File descriptor to close.
-/// @param[in] code The exit code to return.
-/// @param[in] format The message to print.
-/// @param[in] ... Values for formatting.
-/// @return The exit code provided by @c code.
-int close_and_fail(int fd, int code, const char* format, ...)
-{
- va_list arglist;
- fprintf(stderr, "Error: ");
- va_start(arglist, format);
- vfprintf(stderr, format, arglist);
- va_end(arglist);
- fprintf(stderr, "\n");
- return code;
-}
-
-/// @brief Read the device @c devname and print it's data to stdout.
-/// @param[in] devname Device's name.
-/// @return Exit code, zero if success.
-int read_device(const char* devname)
-{
- int fd = open(devname, O_RDONLY);
- if (fd == -1) return close_and_fail(fd, EXIT_FILEOPEN, "Failed to open '%s'!", devname);
-
- header h;
- ssize_t sz = read(fd, &h, sizeof(header));
- if (sz != sizeof(header)) return close_and_fail(fd, EXIT_FILEREAD, "Failed to read the header!");
- if (!is_valid_nm(h.mn)) return close_and_fail(fd, EXIT_INVALID, "Not a valid identity key!");
-
- while(h.size)
- {
- char datas[BLOCK_SIZE + 1];
- memset(datas, BLOCK_SIZE +1, 0);
- size_t count = BLOCK_SIZE > h.size ? h.size : BLOCK_SIZE;
-
- sz = read(fd, datas, count);
-
- if (sz != count) close_and_fail(fd, EXIT_FILEREAD, "Failed to read a data block!");
- h.size = (h.size - count);
-
- printf(datas);
- }
- printf("\n");
- close(fd);
- return EXIT_SUCCESS;
-}
-
-/// @brief Write the specified data to the specified device.
-/// @param[in] devname Name of the device.
-/// @param[in] datas Datas to write.
-/// @return Exit code, zero if success, non-zero otherwise.
-int write_device(const char* devname, const char* datas)
-{
- header h = {
- .mn = {'I', 'D', 'K', 'Y'},
- .size = strlen(datas)
- };
- if (h.size < 1) return close_and_fail(-1, EXIT_CMDLINE, "No data to write!");
-
- int fd = open(devname, O_WRONLY);
- if (fd == -1) return close_and_fail(fd, EXIT_FILEOPEN, "Failed to open device '%s'!", devname);
- if (write(fd, &h, sizeof(header)) != sizeof(header)) return close_and_fail(fd, EXIT_FILEWRITE, "Failed to write the header!");
- if (write(fd, datas, h.size) != h.size) return close_and_fail(fd, EXIT_FILEWRITE, "Failed to write datas!");
-
- close(fd);
- return EXIT_SUCCESS;
-}
-
-/// @brief Entry point.
-/// @param[in] argc Number of arguments in @c argv.
-/// @param[in] argv Arguments array.
-/// @return Exit code, zero if success, non-zero otherwise.
-int main(int argc, char** argv)
-{
- switch(argc)
- {
- case 0:
- case 1:
- fprintf(stderr, "ERROR: too few arguments!\n");
- return EXIT_CMDLINE;
-
- case 2: // Read the device
- return read_device(argv[1]);
-
- case 3: // Write the device
- return write_device(argv[1], argv[2]);
-
- default:
- fprintf(stderr, "ERROR: too many arguments!\n");
- return EXIT_CMDLINE;
- }
-}
-
+++ /dev/null
-###########################################################################
-# Copyright 2015, 2016, 2017 IoT.bzh
-#
-# author: Loïc Collignon <loic.collignon@iot.bzh>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-###########################################################################
-
-cmake_minimum_required(VERSION 3.3)
-
-include(${CMAKE_CURRENT_SOURCE_DIR}/conf.d/cmake/config.cmake)
+++ /dev/null
-###########################################################################
-# Copyright 2015, 2016, 2017 IoT.bzh
-#
-# author: Loïc Collignon <loic.collignon@iot.bzh>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-###########################################################################
-
-# Project Info
-# ------------------
-set(PROJECT_NAME ll-auth-binding)
-set(PROJECT_VERSION "0.1")
-set(PROJECT_PRETTY_NAME "Low Level Auth Binding")
-set(PROJECT_DESCRIPTION "A low level binding to log users in and out.")
-set(PROJECT_URL "")
-set(PROJECT_ICON "icon.png")
-set(PROJECT_AUTHOR "Collignon, Loïc")
-set(PROJECT_AUTHOR_MAIL "loic.collignon@iot.bzh")
-set(PROJECT_LICENSE "APL2.0")
-set(PROJECT_LANGUAGES,"C")
-
-# Where are stored default templates files from submodule or subtree app-templates in your project tree
-# relative to the root project directory
-set(PROJECT_APP_TEMPLATES_DIR "../conf.d/app-templates")
-
-# Where are stored your external libraries for your project. This is 3rd party library that you don't maintain
-# but used and must be built and linked.
-# set(PROJECT_LIBDIR "libs")
-
-# Where are stored data for your application. Pictures, static resources must be placed in that folder.
-# set(PROJECT_RESOURCES "data")
-
-# Which directories inspect to find CMakeLists.txt target files
-# set(PROJECT_SRC_DIR_PATTERN "*")
-
-# Compilation Mode (DEBUG, RELEASE)
-# ----------------------------------
-set(CMAKE_BUILD_TYPE "DEBUG")
-
-# Kernel selection if needed. Impose a minimal version.
-# NOTE FOR NOW IT CHECKS KERNEL Yocto SDK Kernel version
-# else only HOST VERSION
-# -----------------------------------------------
-#set (kernel_minimal_version 4.8)
-
-# Compiler selection if needed. Impose a minimal version.
-# -----------------------------------------------
-set (gcc_minimal_version 4.9)
-
-# PKG_CONFIG required packages
-# -----------------------------
-set (PKG_REQUIRED_LIST
- json-c
- libsystemd>=222
- afb-daemon
- libmicrohttpd>=0.9.55
- libudev
-)
-
-set(CMAKE_THREAD_PREFER_PTHREAD TRUE)
-set(THREADS_PREFER_PTHREAD_FLAG TRUE)
-find_package(Threads REQUIRED)
-
-# Static constante definition
-# -----------------------------
-add_compile_options()
-
-# LANG Specific compile flags set for all build types
-set(CMAKE_C_FLAGS "")
-set(CMAKE_CXX_FLAGS "")
-
-# Print a helper message when every thing is finished
-# ----------------------------------------------------
-#set(CLOSING_MESSAGE "")
-#set(PACKAGE_MESSAGE "Install widget file using in the target : afm-util install ${PROJECT_NAME}.wgt")
-
-# (BUG!!!) as PKG_CONFIG_PATH does not work [should be an env variable]
-# ---------------------------------------------------------------------
-set(CMAKE_INSTALL_PREFIX $ENV{HOME}/opt)
-set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} ${CMAKE_INSTALL_PREFIX}/lib64/pkgconfig ${CMAKE_INSTALL_PREFIX}/lib/pkgconfig)
-set(LD_LIBRARY_PATH ${CMAKE_INSTALL_PREFIX}/lib64 ${CMAKE_INSTALL_PREFIX}/lib)
-
-# Optional location for config.xml.in
-# -----------------------------------
-#set(WIDGET_CONFIG_TEMPLATE ${CMAKE_CURRENT_SOURCE_DIR}/conf.d/config.xml.in)
-
-# Mandatory widget Mimetype specification of the main unit
-# --------------------------------------------------------------------------
-# Choose between :
-#- text/html : HTML application,
-# content.src designates the home page of the application
-#
-#- application/vnd.agl.native : AGL compatible native,
-# content.src designates the relative path of the binary.
-#
-# - application/vnd.agl.service: AGL service, content.src is not used.
-#
-#- ***application/x-executable***: Native application,
-# content.src designates the relative path of the binary.
-# For such application, only security setup is made.
-#
-set(WIDGET_TYPE MimeType_Not_Set)
-
-# Mandatory Widget entry point file of the main unit
-# --------------------------------------------------------------
-# This is the file that will be executed, loaded,
-# at launch time by the application framework.
-#
-set(WIDGET_ENTRY_POINT EntryPoint_Path_Not_Set)
-
-# Optional dependencies order
-# ---------------------------
-#set(EXTRA_DEPENDENCIES_ORDER)
-
-# Optional Extra global include path
-# -----------------------------------
-#set(EXTRA_INCLUDE_DIRS)
-
-# Optional extra libraries
-# -------------------------
-#set(EXTRA_LINK_LIBRARIES)
-
-# Optional force binding installation
-# ------------------------------------
-# set(BINDINGS_INSTALL_PREFIX PrefixPath )
-
-# Optional force binding Linking flag
-# ------------------------------------
-# set(BINDINGS_LINK_FLAG LinkOptions )
-
-# Optional force package prefix generation, like widget
-# -----------------------------------------------------
-# set(PKG_PREFIX DestinationPath)
-
-# Optional Application Framework security token
-# and port use for remote debugging.
-#------------------------------------------------------------
-#set(AFB_TOKEN "" CACHE PATH "Default AFB_TOKEN")
-#set(AFB_REMPORT "1234" CACHE PATH "Default AFB_TOKEN")
-
-# This include is mandatory and MUST happens at the end
-# of this file, else you expose you to unexpected behavior
-# -----------------------------------------------------------
-include(${PROJECT_APP_TEMPLATES_DIR}/cmake/common.cmake)
+++ /dev/null
-AFB = function(base, initialtoken){
-
-var urlws = "ws://"+window.location.host+"/"+base;
-var urlhttp = "http://"+window.location.host+"/"+base;
-
-/*********************************************/
-/**** ****/
-/**** AFB_context ****/
-/**** ****/
-/*********************************************/
-var AFB_context;
-{
- var UUID = undefined;
- var TOKEN = initialtoken;
-
- var context = function(token, uuid) {
- this.token = token;
- this.uuid = uuid;
- }
-
- context.prototype = {
- get token() {return TOKEN;},
- set token(tok) {if(tok) TOKEN=tok;},
- get uuid() {return UUID;},
- set uuid(id) {if(id) UUID=id;}
- };
-
- AFB_context = new context();
-}
-/*********************************************/
-/**** ****/
-/**** AFB_websocket ****/
-/**** ****/
-/*********************************************/
-var AFB_websocket;
-{
- var CALL = 2;
- var RETOK = 3;
- var RETERR = 4;
- var EVENT = 5;
-
- var PROTO1 = "x-afb-ws-json1";
-
- AFB_websocket = function(onopen, onabort) {
- var u = urlws;
- if (AFB_context.token) {
- u = u + '?x-afb-token=' + AFB_context.token;
- if (AFB_context.uuid)
- u = u + '&x-afb-uuid=' + AFB_context.uuid;
- }
- this.ws = new WebSocket(u, [ PROTO1 ]);
- this.pendings = {};
- this.awaitens = {};
- this.counter = 0;
- this.ws.onopen = onopen.bind(this);
- this.ws.onerror = onerror.bind(this);
- this.ws.onclose = onclose.bind(this);
- this.ws.onmessage = onmessage.bind(this);
- this.onopen = onopen;
- this.onabort = onabort;
- this.onclose = onabort;
- }
-
- function onerror(event) {
- var f = this.onabort;
- if (f) {
- delete this.onopen;
- delete this.onabort;
- f && f(this);
- }
- this.onerror && this.onerror(this);
- }
-
- function onopen(event) {
- var f = this.onopen;
- delete this.onopen;
- delete this.onabort;
- f && f(this);
- }
-
- function onclose(event) {
- for (var id in this.pendings) {
- var ferr = this.pendings[id].onerror;
- ferr && ferr(null, this);
- }
- this.pendings = {};
- this.onclose && this.onclose();
- }
-
- function fire(awaitens, name, data) {
- var a = awaitens[name];
- if (a)
- a.forEach(function(handler){handler(data);});
- var i = name.indexOf("/");
- if (i >= 0) {
- a = awaitens[name.substring(0,i)];
- if (a)
- a.forEach(function(handler){handler(data);});
- }
- a = awaitens["*"];
- if (a)
- a.forEach(function(handler){handler(data);});
- }
-
- function reply(pendings, id, ans, offset) {
- if (id in pendings) {
- var p = pendings[id];
- delete pendings[id];
- var f = p[offset];
- f(ans);
- }
- }
-
- function onmessage(event) {
- var obj = JSON.parse(event.data);
- var code = obj[0];
- var id = obj[1];
- var ans = obj[2];
- AFB_context.token = obj[3];
- switch (code) {
- case RETOK:
- reply(this.pendings, id, ans, 0);
- break;
- case RETERR:
- reply(this.pendings, id, ans, 1);
- break;
- case EVENT:
- default:
- fire(this.awaitens, id, ans);
- break;
- }
- }
-
- function close() {
- this.ws.close();
- this.onabort();
- }
-
- function call(method, request) {
- return new Promise((function(resolve, reject){
- var id, arr;
- do {
- id = String(this.counter = 4095 & (this.counter + 1));
- } while (id in this.pendings);
- this.pendings[id] = [ resolve, reject ];
- arr = [CALL, id, method, request ];
- if (AFB_context.token) arr.push(AFB_context.token);
- this.ws.send(JSON.stringify(arr));
- }).bind(this));
- }
-
- function onevent(name, handler) {
- var id = name;
- var list = this.awaitens[id] || (this.awaitens[id] = []);
- list.push(handler);
- }
-
- AFB_websocket.prototype = {
- close: close,
- call: call,
- onevent: onevent
- };
-}
-/*********************************************/
-/**** ****/
-/**** ****/
-/**** ****/
-/*********************************************/
-return {
- context: AFB_context,
- ws: AFB_websocket
-};
-};
-
+++ /dev/null
-###########################################################################
-# Copyright 2015, 2016, 2017 IoT.bzh
-#
-# author: Fulup Ar Foll <fulup@iot.bzh>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-###########################################################################
-
-
-
-##################################################
-# HTML Testing Files
-##################################################
-PROJECT_TARGET_ADD(www_test)
-
- file(GLOB SOURCE_FILES "*.html" "*.js" "*.jpg")
-
- add_custom_target(${TARGET_NAME}
- DEPENDS ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}
- )
-
- add_custom_command(
- DEPENDS ${SOURCE_FILES}
- OUTPUT ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}
- COMMAND mkdir -p ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}
- COMMAND touch ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}
- COMMAND cp -r ${SOURCE_FILES} ${CMAKE_CURRENT_BINARY_DIR}/${TARGET_NAME}
- )
-
- SET_TARGET_PROPERTIES(${TARGET_NAME} PROPERTIES
- LABELS "HTDOCS"
- OUTPUT_NAME ${TARGET_NAME}
- )
+++ /dev/null
- var afb = new AFB("api", "mysecret");
- var ws;
- var evtidx=0;
-
- function getParameterByName(name, url) {
- if (!url) {
- url = window.location.href;
- }
- name = name.replace(/[\[\]]/g, "\\$&");
- var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
- results = regex.exec(url);
- if (!results) return null;
- if (!results[2]) return '';
- return decodeURIComponent(results[2].replace(/\+/g, " "));
- }
-
- // default soundcard is "PCH"
- var devid=getParameterByName("devid");
- if (!devid) devid="hw:0";
-
- var sndname=getParameterByName("sndname");
- if (!sndname) sndname="PCH";
-
- var quiet=getParameterByName("quiet");
- if (!quiet) quiet="99";
-
- function init() {
- ws = new afb.ws(onopen, onabort);
- }
-
- function onopen() {
- document.getElementById("main").style.visibility = "visible";
- document.getElementById("connected").innerHTML = "Binder WS Active";
- document.getElementById("connected").style.background = "lightgreen";
- ws.onevent("*", gotevent);
- }
-
- function onabort() {
- document.getElementById("main").style.visibility = "hidden";
- document.getElementById("connected").innerHTML = "Connected Closed";
- document.getElementById("connected").style.background = "red";
-
- }
-
- function replyok(obj) {
- console.log("replyok:" + JSON.stringify(obj));
- document.getElementById("output").innerHTML = "OK: "+JSON.stringify(obj);
- }
-
- function replyerr(obj) {
- console.log("replyerr:" + JSON.stringify(obj));
- document.getElementById("output").innerHTML = "ERROR: "+JSON.stringify(obj);
- }
-
- function gotevent(obj) {
- console.log("gotevent:" + JSON.stringify(obj));
- document.getElementById("outevt").innerHTML = (evtidx++) +": "+JSON.stringify(obj);
-
- document.getElementById("message").innerHTML = "";
-
- if (obj.event == "ll-auth/login") {
- document.getElementById("userid").innerHTML = obj.data.user;
- document.getElementById("device").innerHTML = obj.data.device;
- }
-
- if (obj.event == "ll-auth/logout") {
- document.getElementById("userid").innerHTML = "";
- document.getElementById("device").innerHTML = "";
- }
-
- if (obj.event == "ll-auth/failed") {
- document.getElementById("message").innerHTML = obj.data.message;
- }
- }
-
- function send(message) {
- var api = document.getElementById("api").value;
- var verb = document.getElementById("verb").value;
- document.getElementById("question").innerHTML = "subscribe: "+api+"/"+verb + " (" + JSON.stringify(message) +")";
- ws.call(api+"/"+verb, {data:message}).then(replyok, replyerr);
- }
-
-
- function callbinder(api, verb, query) {
- console.log ("subscribe api="+api+" verb="+verb+" query=" +query);
- document.getElementById("question").innerHTML = "apicall: " + api+"/"+verb +" ("+ JSON.stringify(query)+")";
- ws.call(api+"/"+verb, query).then(replyok, replyerr);
- }
+++ /dev/null
- var afb = new AFB("api", "mysecret");
- var ws;
- var evtidx=0;
-
- function getParameterByName(name, url) {
- if (!url) {
- url = window.location.href;
- }
- name = name.replace(/[\[\]]/g, "\\$&");
- var regex = new RegExp("[?&]" + name + "(=([^&#]*)|&|#|$)"),
- results = regex.exec(url);
- if (!results) return null;
- if (!results[2]) return '';
- return decodeURIComponent(results[2].replace(/\+/g, " "));
- }
-
- // default soundcard is "PCH"
- var devid=getParameterByName("devid");
- if (!devid) devid="hw:0";
-
- var sndname=getParameterByName("sndname");
- if (!sndname) sndname="PCH";
-
- var quiet=getParameterByName("quiet");
- if (!quiet) quiet="99";
-
- function init() {
- ws = new afb.ws(onopen, onabort);
- }
-
- function onopen() {
- document.getElementById("background").style.background = "lightgray";
- document.getElementById("main").style.visibility = "visible";
- callbinder("ll-auth", "getuser", "");
- ws.onevent("*", gotevent);
- }
-
- function onabort() {
- document.getElementById("background").style.background = "IndianRed";
- }
-
- function replyok(obj) {
- console.log("replyok:" + JSON.stringify(obj));
- document.getElementById("output").innerHTML = "OK: "+JSON.stringify(obj);
-
- document.getElementById("usertitle").innerHTML = "A valid user is logged in";
- document.getElementById("userid").innerHTML = obj.response.user;
- document.getElementById("userdevice").innerHTML = obj.response.device;
- document.getElementById("background").style.background = "lightgreen";
- }
-
- function replyerr(obj) {
- console.log("replyerr:" + JSON.stringify(obj));
- document.getElementById("output").innerHTML = "ERROR: "+JSON.stringify(obj);
- }
-
- function gotevent(obj) {
- console.log("gotevent:" + JSON.stringify(obj));
- document.getElementById("outevt").innerHTML = (evtidx++) +": "+JSON.stringify(obj);
-
- document.getElementById("question").innerHTML = "";
- document.getElementById("output").innerHTML = "";
- document.getElementById("message").innerHTML = "";
-
- if (obj.event == "ll-auth/login") {
- document.getElementById("usertitle").innerHTML = "A valid user is logged in";
- document.getElementById("userid").innerHTML = obj.data.user;
- document.getElementById("userdevice").innerHTML = obj.data.device;
- document.getElementById("background").style.background = "lightgreen";
- }
-
- if (obj.event == "ll-auth/logout") {
- document.getElementById("usertitle").innerHTML = "No user";
- document.getElementById("userid").innerHTML = "";
- document.getElementById("userdevice").innerHTML = "";
- document.getElementById("background").style.background = "lightgray";
- }
-
- if (obj.event == "ll-auth/failed") {
- document.getElementById("message").innerHTML = obj.data.message;
- }
- }
-
- function send(message) {
- var api = document.getElementById("api").value;
- var verb = document.getElementById("verb").value;
- document.getElementById("question").innerHTML = "subscribe: "+api+"/"+verb + " (" + JSON.stringify(message) +")";
- ws.call(api+"/"+verb, {data:message}).then(replyok, replyerr);
- }
-
-
- function callbinder(api, verb, query) {
- console.log ("subscribe api="+api+" verb="+verb+" query=" +query);
- document.getElementById("question").innerHTML = "apicall: " + api+"/"+verb +" ("+ JSON.stringify(query)+")";
- ws.call(api+"/"+verb, query).then(replyok, replyerr);
- }
+++ /dev/null
-<html>
- <head>
- <title>ll-auth-binding test</title>
- <script type="text/javascript" src="AFB-websock.js"></script>
- <script type="text/javascript" src="IdentityBinding.js"></script>
- </head>
-
- <body onload="init();">
- <h1>Identity Binding</h1>
- <button id="connected" onclick="init()">Binder WS Fail</button>
- <br>
- <ol>
- <!--
- <li><button onclick="callbinder('ll-auth','login', {})">login</button></li>
- <li><button onclick="callbinder('ll-auth','logout', {})">logout</button></li>
- -->
- <li><button onclick="callbinder('ll-auth','getuser', {})">get user</button></li>
- </ol>
- <br>
- <div>
- </div>
- <h2>User:</h2>
- <ol>
- <li>id: <span id="userid"></span></li>
- <li>device: <span id="device"></span></li>
- </ol>
- <div id="message" style="color:red;"></div>
- <br/>
- <div id="main" style="visibility:hidden">
- <h2>Debug: </h2>
- <ol>
- <li>Question <div id="question"></div></li>
- <li>Response <div id="output"></div></li>
- <li>Events: <div id="outevt"></div></li>
- </ol>
- </div>
- </body>
-</html>
+++ /dev/null
-<html>
- <head>
- <title>ll-auth-binding test</title>
- <script type="text/javascript" src="AFB-websock.js"></script>
- <script type="text/javascript" src="IdentityBinding2.js"></script>
- </head>
-
- <body onload="init();" id="background">
- <!--<button onclick="init()">Refresh</button>-->
- <div>
- <h1 id="usertitle">No user</h1>
- <ul>
- <li>User Id : <span id="userid"></span></li>
- <li>Device : <span id="userdevice"></span></li>
- </ul>
- </div>
- <div id="message" style="color:red;"></div>
- <div id="main" style="visibility:hidden">
- <h2>Debug: </h2>
- <ol>
- <li>Question <div id="question"></div></li>
- <li>Response <div id="output"></div></li>
- <li>Events: <div id="outevt"></div></li>
- </ol>
- </div>
- </body>
-</html>
+++ /dev/null
-<html>
- <head>
- <title>Identity Binding tests</title>
- </head>
- <body>
- <h1>Identity Binding tests</h1>
- <ol>
- <li><a href="auth.html">Auth</a></li>
- <li><a href="auth2.html">Auth2</a></li>
- </ol>
- </body>
-</html>
+++ /dev/null
-PROJECT_TARGET_ADD(ll-auth-binding)
-
-# Require PAM but there is no find_package
-set(PAM_INCLUDE_DIR "/usr/include/")
-set(PAM_LIBRARY "/lib64/libpam.so.0")
-set(PAM_MISC_LIBRARY "/lib64/libpam_misc.so.0")
-include_directories(${PAM_INCLUDE_DIR})
-
-add_library(ll-auth-binding MODULE ll-auth-binding.c)
-
-set_target_properties(ll-auth-binding PROPERTIES
- PREFIX "afb-"
- LABELS "BINDING"
- LINK_FLAGS ${BINDINGS_LINK_FLAG}
- OUTPUT_NAME ${TARGET_NAME})
-
-target_link_libraries(ll-auth-binding ${link_libraries} ${PAM_LIBRARY} ${PAM_MISC_LIBRARY} Threads::Threads)
-
-install(
- TARGETS ll-auth-binding
- LIBRARY DESTINATION ${BINDINGS_INSTALL_DIR})
+++ /dev/null
-{ global: afbBindingV*; local: *; };
+++ /dev/null
-#define _GNU_SOURCE
-#include <stdio.h>
-#include <string.h>
-#include <json-c/json.h>
-#include <security/pam_appl.h>
-#include <security/pam_misc.h>
-#include <libudev.h>
-#include <pthread.h>
-#include <poll.h>
-
-#define AFB_BINDING_VERSION 2
-#include <afb/afb-binding.h>
-
-// Defines
-#define PAM_RULE "agl"
-#define UDEV_MONITOR_POLLING_TIMEOUT 5000
-
-#define UDEV_ACTION_UNSUPPORTED 0
-#define UDEV_ACTION_ADD 1
-#define UDEV_ACTION_REMOVE 2
-
-#define LOGIN_SUCCESS 0
-#define LOGIN_ERROR_USER_LOGGED 1
-#define LOGIN_ERROR_PAM_START 2
-#define LOGIN_ERROR_PAM_PUTENV 3
-#define LOGIN_ERROR_PAM_AUTHENTICATE 4
-#define LOGIN_ERROR_PAM_ACCT_MGMT 5
-#define LOGIN_ERROR_PAM_NO_USER 6
-#define LOGIN_ERROR_PAM_END 7
-
-// Globals
-static const char* error_messages[] =
-{
- "",
- "The current user must be logged out first!",
- "PAM start failed!",
- "PAM putenv failed!",
- "PAM authenticate failed!",
- "PAM acct_mgmt failed!",
- "No user provided by the PAM module!",
- "PAM end failed!"
-};
-
-static char* current_device = NULL;
-static char* current_user = NULL;
-static struct pam_conv conv = { misc_conv, NULL };
-static struct udev* udev_context = NULL;
-static struct udev_monitor* udev_mon = NULL;
-static pthread_t udev_monitoring_thread_handle;
-static struct afb_event evt_login, evt_logout, evt_failed;
-
-/**
- * @brief Free the memory associated to the specified string and nullify the pointer.
- * @param[in] string A pointer to the string.
- */
-static inline void free_string(char** string)
-{
- if (string)
- {
- if (*string) free(*string);
- *string = NULL;
- }
-}
-
-/**
- * @brief Free the memory associated to the specified UDev's context and nullify the pointer.
- * @param[in] ctx UDev's context.
- */
-static inline void free_udev_context(struct udev** ctx)
-{
- if (ctx)
- {
- if (*ctx) udev_unref(*ctx);
- *ctx = NULL;
- }
-}
-
-/**
- * @brief Free the memory associated to the specified UDev's monitor and nullify the pointer.
- * @param[in] mon UDev's monitor.
- */
-static inline void free_udev_monitor(struct udev_monitor** mon)
-{
- if (mon)
- {
- if (*mon) udev_monitor_unref(*mon);
- *mon = NULL;
- }
-}
-
-/**
- * @brief Print UDev infos for the specified device.
- * @param[in] dev The device.
- */
-static inline void print_udev_device_info(struct udev_device* dev)
-{
- AFB_INFO(" Action: %s", udev_device_get_action(dev));
- AFB_INFO(" Node: %s", udev_device_get_devnode(dev));
- AFB_INFO(" Subsystem: %s", udev_device_get_subsystem(dev));
- AFB_INFO(" Devtype: %s", udev_device_get_devtype(dev));
- AFB_INFO(" DevNum: %lu", udev_device_get_devnum(dev));
- AFB_INFO(" DevPath: %s", udev_device_get_devpath(dev));
- AFB_INFO(" Driver: %s", udev_device_get_driver(dev));
- AFB_INFO(" SeqNum: %llu", udev_device_get_seqnum(dev));
- AFB_INFO(" SysName: %s", udev_device_get_sysname(dev));
- AFB_INFO(" SysNum: %s", udev_device_get_sysnum(dev));
- AFB_INFO(" SysPath: %s", udev_device_get_syspath(dev));
-}
-
-/**
- * @brief Get the UDev's action as an int to allow switch condition.
- * @param[in] dev The device.
- */
-static inline int udev_device_get_action_int(struct udev_device* dev)
-{
- const char* action = udev_device_get_action(dev);
- return
- strcmp(action, "add")
- ? (strcmp(action, "remove") ? UDEV_ACTION_UNSUPPORTED : UDEV_ACTION_REMOVE)
- : UDEV_ACTION_ADD;
-}
-
-/**
- * @brief PAM authentication process.
- * @param[in] pamh The handle to the PAM context.
- * @param[in] device The device to login.
- */
-static int pam_process(pam_handle_t* pamh, const char* device)
-{
- int r;
-
- if (!pamh) return LOGIN_ERROR_PAM_START;
-
- char pam_variable[4096] = "DEVICE=";
- strcat(pam_variable, device);
-
- if ((r = pam_putenv(pamh, pam_variable)) != PAM_SUCCESS)
- return LOGIN_ERROR_PAM_PUTENV;
-
- if ((r = pam_authenticate(pamh, 0)) != PAM_SUCCESS)
- return LOGIN_ERROR_PAM_AUTHENTICATE;
-
- if ((r = pam_acct_mgmt(pamh, 0)) != PAM_SUCCESS)
- return LOGIN_ERROR_PAM_ACCT_MGMT;
-
- const char* pam_user;
- pam_get_item(pamh, PAM_USER, (const void**)&pam_user);
- if (!pam_user)
- return LOGIN_ERROR_PAM_NO_USER;
-
- current_device = strdup(device);
- current_user = strdup(pam_user);
-
- return LOGIN_SUCCESS;
-}
-
-/**
- * @brief Login using PAM.
- * @param[in] device The device to use.
- * @return Exit code, @c LOGIN_SUCCESS on success.
- */
-static int login_pam(const char* device)
-{
- int r;
- pam_handle_t* pamh;
-
- if (current_user)
- return LOGIN_ERROR_USER_LOGGED;
-
- if ((r = pam_start("agl", NULL, &conv, &pamh)) != PAM_SUCCESS)
- return LOGIN_ERROR_PAM_START;
-
- r = pam_process(pamh, device);
- if (r != LOGIN_SUCCESS)
- {
- pam_end(pamh, r);
- return r;
- }
-
- if ((r = pam_end(pamh, r)) != PAM_SUCCESS)
- return LOGIN_ERROR_PAM_END;
-
- return LOGIN_SUCCESS;
-}
-
-/**
- * @brief Try to login a user using a device.
- * @param[in] device The device to use.
- * @return Exit code, @c LOGIN_SUCCESS if success.
- */
-static int login(const char* device)
-{
- int ret;
- struct json_object* result;
-
- result = json_object_new_object();
-
- ret = login_pam(device);
- switch(ret)
- {
- case LOGIN_SUCCESS:
- json_object_object_add(result, "device", json_object_new_string(current_device));
- json_object_object_add(result, "user", json_object_new_string(current_user));
- afb_event_broadcast(evt_login, result);
- break;
- default:
- json_object_object_add(result, "message", json_object_new_string(error_messages[ret]));
- afb_event_broadcast(evt_failed, result);
- }
-
- json_object_put(result);
- return ret;
-}
-
-/// @brief Try to logout a user using a device.
-/// @param[in] device The device to logout.
-static void logout(const char* device)
-{
- struct json_object* result;
-
- result = json_object_new_object();
-
- if (current_device && !strcmp(device, current_device))
- {
- json_object_object_add(result, "device", json_object_new_string(current_device));
- json_object_object_add(result, "user", json_object_new_string(current_user));
- AFB_INFO("[logout] device: %s", device);
- afb_event_broadcast(evt_logout, NULL);
-
- free_string(¤t_device);
- free_string(¤t_user);
- }
- else
- {
- json_object_object_add(result, "message", json_object_new_string("The unplugged device wasn't the user key!"));
- AFB_INFO("The unplugged device wasn't the user key!");
- afb_event_broadcast(evt_failed, result);
- }
- json_object_put(result);
-}
-
-/**
- * @brief UDev's monitoring thread.
- */
-void* udev_monitoring_thread(void* arg)
-{
- struct udev_device* dev;
- struct pollfd pfd;
- int action;
-
- pfd.fd = udev_monitor_get_fd(udev_mon);
- pfd.events = POLLIN;
-
- while(1)
- {
- if (poll(&pfd, 1, UDEV_MONITOR_POLLING_TIMEOUT))
- {
- dev = udev_monitor_receive_device(udev_mon);
- if (dev)
- {
- if (!strcmp(udev_device_get_devtype(dev), "disk"))
- {
- action = udev_device_get_action_int(dev);
- switch(action)
- {
- case UDEV_ACTION_ADD:
- AFB_INFO("A device is plugged-in");
- print_udev_device_info(dev);
- login(udev_device_get_devnode(dev));
- break;
- case UDEV_ACTION_REMOVE:
- AFB_INFO("A device is plugged-out");
- print_udev_device_info(dev);
- logout(udev_device_get_devnode(dev));
- break;
- default:
- AFB_DEBUG("Unsupported udev action");
- break;
- }
- }
- udev_device_unref(dev);
- }
- else
- {
- AFB_ERROR("No Device from udev_monitor_receive_device().");
- }
- }
- else
- {
- AFB_DEBUG("Udev polling timeout");
- }
- }
- return NULL;
-}
-
-/**
- * @brief API's verb 'getuser'. Try to get user informations.
- * @param[in] req The request object.
- */
-static void verb_getuser(struct afb_req req)
-{
- if (!current_device || !current_user)
- {
- afb_req_fail(req, "there is no logged user!", NULL);
- return;
- }
-
- json_object* result = json_object_new_object();
- json_object_object_add(result, "user", json_object_new_string(current_user));
- json_object_object_add(result, "device", json_object_new_string(current_device));
-
- afb_req_success(req, result, NULL);
-}
-
-/**
- * @brief Do the cleanup when init fails.
- * @param[in] error Error message.
- * @param[in] retcode Error code to return.
- * @return An exit code equals to @c retcode.
- */
-static inline int ll_auth_init_cleanup(const char* error, int retcode)
-{
- AFB_ERROR("%s", error);
- free_string(¤t_user);
- free_string(¤t_device);
-
- free_udev_monitor(&udev_mon);
- free_udev_context(&udev_context);
- return retcode;
-}
-
-/**
- * @brief Initialize the binding.
- */
-int ll_auth_init()
-{
- evt_login = afb_daemon_make_event("login");
- evt_logout = afb_daemon_make_event("logout");
- evt_failed = afb_daemon_make_event("failed");
-
- if (!afb_event_is_valid(evt_login) || !afb_event_is_valid(evt_logout) || !afb_event_is_valid(evt_failed))
- return ll_auth_init_cleanup("Can't create events", -1);
-
- udev_context = udev_new();
- if (!udev_context)
- return ll_auth_init_cleanup("Can't initialize udev's context", -1);
-
- udev_mon = udev_monitor_new_from_netlink(udev_context, "udev");
- if (!udev_mon)
- return ll_auth_init_cleanup("Can't initialize udev's monitor", -1);
-
- udev_monitor_filter_add_match_subsystem_devtype(udev_mon, "block", NULL);
- udev_monitor_enable_receiving(udev_mon);
-
- if (pthread_create(&udev_monitoring_thread_handle, NULL, udev_monitoring_thread, NULL))
- return ll_auth_init_cleanup("Can't start the udev's monitoring thread", -1);
-
- AFB_INFO("ll-auth-binding is ready");
- return 0;
-}
-
-static const afb_verb_v2 _ll_auth_binding_verbs[]= {
- {
- .verb = "getuser",
- .callback = verb_getuser,
- .auth = NULL,
- .info = NULL,
- .session = AFB_SESSION_NONE_V2
- },
- { .verb=NULL}
-};
-
-const struct afb_binding_v2 afbBindingV2 = {
- .api = "ll-auth",
- .specification = NULL,
- .verbs = _ll_auth_binding_verbs,
- .preinit = NULL,
- .init = ll_auth_init,
- .onevent = NULL,
- .noconcurrency = 0
-};
+++ /dev/null
-#!/bin/bash
-
-afb-daemon --port=9000 --token='' --binding=$PWD/build/src/afb-ll-auth-binding.so --verbose --roothttp=$PWD/htdocs
+++ /dev/null
-###########################################################################
-# Copyright 2015, 2016, 2017 IoT.bzh
-#
-# author: Loïc Collignon <loic.collignon@iot.bzh>
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-# http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-###########################################################################
-
-cmake_minimum_required(VERSION 3.3)
-project(pam_agl)
-
-include(FindPkgConfig)
-
-# Require PAM but there is no find_package
-set(PAM_INCLUDE_DIR "/usr/include/")
-set(PAM_LIBRARY "/lib64/libpam.so.0")
-include_directories(${PAM_INCLUDE_DIR})
-if (NOT DEFINED CMAKE_INSTALL_LIBDIR)
- get_filename_component(CMAKE_INSTALL_LIBDIR ${PAM_LIBRARY} DIRECTORY)
-endif()
-
-# Find json-c
-pkg_check_modules(${JSON_C} REQUIRED json-c)
-include_directories(${${JSON_C}_INCLUDE_DIRS})
-add_compile_options(${${JSON_C}_CFLAGS})
-
-# Add the pam_agl_usb target
-add_library(pam_agl_usb SHARED pam_agl_usb.c)
-target_link_libraries(pam_agl_usb ${PAM_LIBRARY} ${${JSON_C}_LIBRARIES})
-set_property(TARGET pam_agl_usb PROPERTY POSITION_INDEPENDENT_CODE ON)
-set_property(TARGET pam_agl_usb PROPERTY PREFIX "")
-
-install(TARGETS pam_agl_usb
- LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}/security/")
-
-# Add the pam_agl_nfc target
-add_library(pam_agl_nfc SHARED pam_agl_nfc.c)
-target_link_libraries(pam_agl_nfc ${PAM_LIBRARY} ${${JSON_C}_LIBRARIES})
-set_property(TARGET pam_agl_nfc PROPERTY POSITION_INDEPENDENT_CODE ON)
-set_property(TARGET pam_agl_nfc PROPERTY PREFIX "")
-
-install(TARGETS pam_agl_nfc
- LIBRARY DESTINATION "${CMAKE_INSTALL_LIBDIR}/security/")
+++ /dev/null
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <uuid/uuid.h>
-#include <json-c/json.h>
-
-#define PAM_SM_AUTH
-#define PAM_SM_ACCOUNT
-#define PAM_SM_SESSION
-#define PAM_SM_PASSWORD
-#include <security/pam_modules.h>
-#include <security/pam_appl.h>
-
-#include <security/pam_client.h>
-#include <security/pam_ext.h>
-#include <security/pam_filter.h>
-#include <security/pam_misc.h>
-#include <security/pam_modutil.h>
-
-#define DATABASE_FILE "/etc/agl/keys.json"
-
-int authenticate(pam_handle_t* pamh, const char* uid)
-{
- struct json_object* database;
- struct json_object* nfc;
- struct json_object* key;
-
- database = json_object_from_file(DATABASE_FILE);
- if (!database)
- {
- printf("[PAM DEBUG] Failed to parse the database\n");
- return PAM_SERVICE_ERR;
- }
-
- if (json_object_object_get_ex(database, "nfc", &nfc))
- {
- if (json_object_object_get_ex(nfc, uid, &key))
- {
- printf("[PAM] Key found!\n");
- printf("[PAM DEBUG] pam_set_item(\"%s\")\n", uid);
- pam_set_item(pamh, PAM_USER, uid);
-
- const char* pam_authtok;
- if (pam_get_item(pamh, PAM_AUTHTOK, (const void**)&pam_authtok) == PAM_SUCCESS && !pam_authtok)
- pam_set_item(pamh, PAM_AUTHTOK, uid);
-
- json_object_put(database);
- return PAM_SUCCESS;
- }
- }
-
- printf("[PAM] Key not found!\n");
- if (database) json_object_put(database);
- return PAM_AUTH_ERR;
-}
-
-int check_device(pam_handle_t* pamh, const char* device)
-{
- char* idkey;
- int ret;
-
- ret = read_device(device, &idkey);
- if (ret != PAM_SUCCESS) return ret;
-
- printf("[PAM DEBUG] Data read:\n%s\n", idkey);
-
- json_object* idkey_json = json_tokener_parse(idkey);
- if (!idkey_json)
- {
- free(idkey);
- printf("[PAM DEBUG] Failed to parse json data!\n");
- return PAM_SERVICE_ERR;
- }
-
- json_object* uuid_json;
- if(!json_object_object_get_ex(idkey_json, "uuid", &uuid_json))
- {
- free(idkey);
- printf("[PAM DEBUG] The json does not contains a valid uuid\n");
- return PAM_SERVICE_ERR;
- }
-
- const char* uuid = json_object_get_string(uuid_json);
- printf("[PAM DEBUG] uuid: %s\n", uuid);
-
- ret = authenticate(pamh, uuid);
- free(idkey);
- json_object_put(idkey_json);
- return ret;
-}
-
-void log_pam(const char* fname, int flags, int argc, const char** argv, const char* device)
-{
- printf("[PAM DEBUG] ---------- %s ----------\n", fname);
- printf("[PAM DEBUG] flags: %d\n", flags);
- for(int i = 0; i < argc; ++i)
- {
- printf("[PAM DEBUG] argv[%d]: %s\n", i, argv[i]);
- }
- printf("[PAM DEBUG] device: %s\n", device);
- printf("[PAM DEBUG] ----------------------------------------\n");
-}
-
-/*!
- @brief The pam_sm_authenticate function is the service module's implementation
- of the pam_authenticate(3) interface.
- This function performs the task of authenticating the user.
-
- @param[in] pamh Unknown.
- @param[in] flags PAM_SILENT and/or PAM_DISALLOW_NULL_AUTHTOK.
- @return PAM_SUCCESS if ok.
-*/
-PAM_EXTERN int pam_sm_authenticate(pam_handle_t* pamh, int flags, int argc, const char** argv)
-{
- const char* uid = pam_getenv(pamh, "UID");
- log_pam("pam_sm_authenticate", flags, argc, argv, uid);
- return authenticate(pamh, uid);
-}
-
-PAM_EXTERN int pam_sm_setcred(pam_handle_t* pamh, int flags, int argc, const char** argv)
-{
- log_pam("pam_sm_setcred", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
- return PAM_SUCCESS;
-}
-
-PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const char** argv)
-{
- log_pam("pam_sm_acct_mgmt", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
- return PAM_SUCCESS;
-}
-
-PAM_EXTERN int pam_sm_open_session(pam_handle_t* pamh, int flags, int argc, const char** argv)
-{
- log_pam("pam_sm_open_session", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
- return PAM_SUCCESS;
-}
-
-PAM_EXTERN int pam_sm_close_session(pam_handle_t* pamh, int flags, int argc, const char** argv)
-{
- log_pam("pam_sm_close_session", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
- return PAM_SUCCESS;
-}
-
-PAM_EXTERN int pam_sm_chauthtok(pam_handle_t* pamh, int flags, int argc, const char** argv)
-{
- log_pam("pam_sm_chauthtok", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
- return PAM_SUCCESS;
-}
+++ /dev/null
-#include <fcntl.h>
-#include <stdarg.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <unistd.h>
-#include <uuid/uuid.h>
-#include <json-c/json.h>
-
-#define PAM_SM_AUTH
-#define PAM_SM_ACCOUNT
-#define PAM_SM_SESSION
-#define PAM_SM_PASSWORD
-#include <security/pam_modules.h>
-#include <security/pam_appl.h>
-
-#define DATABASE_FILE "/etc/agl/keys.json"
-
-#define BLOCK_SIZE 4096
-typedef struct header_
-{
- char mn[4];
- size_t size;
-} header;
-
-int is_valid_mn(const char* v)
-{
- return v && v[0] == 'I' && v[1] == 'D' && v[2] == 'K' && v[3] == 'Y';
-}
-
-int read_device(const char* device, char** idkey)
-{
- int fd;
- ssize_t sz;
- header h;
-
- printf("[PAM DEBUG] check_device %s...\n", device);
- fd = open(device, O_RDONLY);
- if (fd == -1)
- {
- printf("[PAM DEBUG] Failed to open the device %s!\n", device);
- return PAM_SERVICE_ERR;
- }
-
- sz = read(fd, &h, sizeof(header));
- if (sz != sizeof(header) || !is_valid_mn(h.mn) || h.size < 1) { close(fd); printf("[PAM DEBUG]: bad header!\n"); return PAM_SERVICE_ERR; }
- printf("[PAM DEBUG]: data size=%lu\n", h.size);
-
- *idkey = (char*)malloc(h.size + 1);
- if (!*idkey) { close(fd); printf("[PAM DEBUG] Bad alloc!\n"); return PAM_SERVICE_ERR; }
-
- memset(*idkey, 0, h.size + 1);
- sz = read(fd, *idkey, h.size);
- close(fd);
- if (sz != h.size) { free(idkey); printf("[PAM DEBUG] Bad data read!\n"); return PAM_SERVICE_ERR; }
- return PAM_SUCCESS;
-}
-
-int authenticate(pam_handle_t* pamh, const char* uuid)
-{
- struct json_object* database;
- struct json_object* usb;
- struct json_object* key;
-
- database = json_object_from_file(DATABASE_FILE);
- if (!database)
- {
- printf("[PAM DEBUG] Failed to parse the database\n");
- return PAM_SERVICE_ERR;
- }
-
- if (json_object_object_get_ex(database, "usb", &usb))
- {
- if (json_object_object_get_ex(usb, uuid, &key))
- {
- printf("[PAM] Key found!\n");
- printf("[PAM DEBUG] pam_set_item(\"%s\")\n", uuid);
- pam_set_item(pamh, PAM_USER, uuid);
-
- const char* pam_authtok;
- if (pam_get_item(pamh, PAM_AUTHTOK, (const void**)&pam_authtok) == PAM_SUCCESS && !pam_authtok)
- pam_set_item(pamh, PAM_AUTHTOK, uuid);
-
- json_object_put(database);
- return PAM_SUCCESS;
- }
- }
-
- printf("[PAM] Key not found!\n");
- if (database) json_object_put(database);
- return PAM_AUTH_ERR;
-}
-
-int check_device(pam_handle_t* pamh, const char* device)
-{
- char* idkey;
- int ret;
-
- ret = read_device(device, &idkey);
- if (ret != PAM_SUCCESS) return ret;
-
- printf("[PAM DEBUG] Data read:\n%s\n", idkey);
-
- json_object* idkey_json = json_tokener_parse(idkey);
- if (!idkey_json)
- {
- free(idkey);
- printf("[PAM DEBUG] Failed to parse json data!\n");
- return PAM_SERVICE_ERR;
- }
-
- json_object* uuid_json;
- if(!json_object_object_get_ex(idkey_json, "uuid", &uuid_json))
- {
- free(idkey);
- printf("[PAM DEBUG] The json does not contains a valid uuid\n");
- return PAM_SERVICE_ERR;
- }
-
- const char* uuid = json_object_get_string(uuid_json);
- printf("[PAM DEBUG] uuid: %s\n", uuid);
-
- ret = authenticate(pamh, uuid);
- free(idkey);
- json_object_put(idkey_json);
- return ret;
-}
-
-void log_pam(const char* fname, int flags, int argc, const char** argv, const char* device)
-{
- printf("[PAM DEBUG] ---------- %s ----------\n", fname);
- printf("[PAM DEBUG] flags: %d\n", flags);
- for(int i = 0; i < argc; ++i)
- {
- printf("[PAM DEBUG] argv[%d]: %s\n", i, argv[i]);
- }
- printf("[PAM DEBUG] device: %s\n", device);
- printf("[PAM DEBUG] ----------------------------------------\n");
-}
-
-/*!
- @brief The pam_sm_authenticate function is the service module's implementation
- of the pam_authenticate(3) interface.
- This function performs the task of authenticating the user.
-
- @param[in] pamh Unknown.
- @param[in] flags PAM_SILENT and/or PAM_DISALLOW_NULL_AUTHTOK.
- @return PAM_SUCCESS if ok.
-*/
-PAM_EXTERN int pam_sm_authenticate(pam_handle_t* pamh, int flags, int argc, const char** argv)
-{
- const char* device = pam_getenv(pamh, "DEVICE");
- log_pam("pam_sm_authenticate", flags, argc, argv, device);
- return check_device(pamh, device);
-}
-
-PAM_EXTERN int pam_sm_setcred(pam_handle_t* pamh, int flags, int argc, const char** argv)
-{
- log_pam("pam_sm_setcred", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
- return PAM_SUCCESS;
-}
-
-PAM_EXTERN int pam_sm_acct_mgmt(pam_handle_t* pamh, int flags, int argc, const char** argv)
-{
- log_pam("pam_sm_acct_mgmt", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
- return PAM_SUCCESS;
-}
-
-PAM_EXTERN int pam_sm_open_session(pam_handle_t* pamh, int flags, int argc, const char** argv)
-{
- log_pam("pam_sm_open_session", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
- return PAM_SUCCESS;
-}
-
-PAM_EXTERN int pam_sm_close_session(pam_handle_t* pamh, int flags, int argc, const char** argv)
-{
- log_pam("pam_sm_close_session", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
- return PAM_SUCCESS;
-}
-
-PAM_EXTERN int pam_sm_chauthtok(pam_handle_t* pamh, int flags, int argc, const char** argv)
-{
- log_pam("pam_sm_chauthtok", flags, argc, argv, pam_getenv(pamh, "DEVICE"));
- return PAM_SUCCESS;
-}