Compare commits
10 commits
6ae9a6a164
...
409dbf4891
Author | SHA1 | Date | |
---|---|---|---|
409dbf4891 | |||
d309e3d0df | |||
bb27883661 | |||
4bc3bc211d | |||
7f6f56a7d5 | |||
ccd4895154 | |||
b25738c709 | |||
2f6cbf0a54 | |||
464a817a78 | |||
11f2c30f5b |
9 changed files with 362 additions and 106 deletions
2
.gitignore
vendored
2
.gitignore
vendored
|
@ -1,3 +1 @@
|
||||||
*~
|
*~
|
||||||
pam_wlan.so
|
|
||||||
pam_wlan_test
|
|
||||||
|
|
44
CMakeLists.txt
Normal file
44
CMakeLists.txt
Normal file
|
@ -0,0 +1,44 @@
|
||||||
|
cmake_minimum_required(VERSION 2.8.3)
|
||||||
|
project(PAM_NETWORK_MANAGER C)
|
||||||
|
|
||||||
|
set(CMAKE_MODULE_PATH ${PAM_NETWORK_MANAGER_SOURCE_DIR})
|
||||||
|
|
||||||
|
find_package(PAM REQUIRED)
|
||||||
|
find_package(libnm_glib REQUIRED)
|
||||||
|
|
||||||
|
set(PAM_MODULE_DIR "${CMAKE_INSTALL_PREFIX}/lib/security" CACHE STRING "PAM module directory")
|
||||||
|
set(PAM_NETWORK_MANAGER_HELPER_DIR "${CMAKE_INSTALL_PREFIX}/lib/security/pam_network_manager" CACHE STRING "pam_network_manager_helper install directory")
|
||||||
|
|
||||||
|
set(CONNECTION_TIMEOUT "10" CACHE STRING "Connection timeout")
|
||||||
|
set(CONNECTION_ID "" CACHE STRING "Connection ID")
|
||||||
|
set(CONNECTION_UUID "" CACHE STRING "Connection UUID")
|
||||||
|
set(CONNECTION_SSID "" CACHE STRING "Connection SSID")
|
||||||
|
set(CONNECTION_AUTH_ALG "open" CACHE STRING "Connection authentication algorithm")
|
||||||
|
set(CONNECTION_KEY_MGMT "wpa-eap" CACHE STRING "Connection key management method")
|
||||||
|
set(CONNECTION_EAP "ttls" CACHE STRING "Connection EAP method")
|
||||||
|
set(CONNECTION_PHASE2_AUTHEAP "mschapv2" CACHE STRING "Connection EAP phase2 authentication method")
|
||||||
|
|
||||||
|
include_directories(${CMAKE_CURRENT_BINARY_DIR} ${PAM_INCLUDE_DIR} ${LIBNM_GLIB_INCLUDE_DIRS})
|
||||||
|
link_directories(${LIBNM_GLIB_LIBRARY_DIRS})
|
||||||
|
|
||||||
|
configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h)
|
||||||
|
|
||||||
|
add_executable(pam_network_manager_helper pam_network_manager_helper.c)
|
||||||
|
set_property(TARGET pam_network_manager_helper PROPERTY COMPILE_DEFINITIONS "_DEFAULT_SOURCE;_BSD_SOURCE")
|
||||||
|
set_property(TARGET pam_network_manager_helper PROPERTY COMPILE_FLAGS "-std=c99 -Wall ${LIBNM_GLIB_CFLAGS_OTHER}")
|
||||||
|
set_property(TARGET pam_network_manager_helper PROPERTY LINK_FLAGS "${LIBNM_GLIB_LDFLAGS_OTHER}")
|
||||||
|
target_link_libraries(pam_network_manager_helper ${LIBNM_GLIB_LIBRARIES})
|
||||||
|
|
||||||
|
add_executable(pam_network_manager_test pam_network_manager.c)
|
||||||
|
set_property(TARGET pam_network_manager_test PROPERTY COMPILE_DEFINITIONS "_DEFAULT_SOURCE;_BSD_SOURCE;TEST")
|
||||||
|
set_property(TARGET pam_network_manager_test PROPERTY COMPILE_FLAGS "-std=c99 -Wall")
|
||||||
|
|
||||||
|
add_library(pam_network_manager MODULE pam_network_manager.c)
|
||||||
|
set_property(TARGET pam_network_manager PROPERTY COMPILE_DEFINITIONS "_DEFAULT_SOURCE;_BSD_SOURCE")
|
||||||
|
set_property(TARGET pam_network_manager PROPERTY COMPILE_FLAGS "-std=c99 -Wall")
|
||||||
|
set_property(TARGET pam_network_manager PROPERTY PREFIX "")
|
||||||
|
|
||||||
|
install(TARGETS pam_network_manager pam_network_manager_helper
|
||||||
|
RUNTIME DESTINATION "${PAM_NETWORK_MANAGER_HELPER_DIR}"
|
||||||
|
LIBRARY DESTINATION "${PAM_MODULE_DIR}"
|
||||||
|
)
|
15
FindPAM.cmake
Normal file
15
FindPAM.cmake
Normal file
|
@ -0,0 +1,15 @@
|
||||||
|
FIND_PATH(PAM_INCLUDE_DIR security/pam_modules.h)
|
||||||
|
|
||||||
|
IF (PAM_INCLUDE_DIR)
|
||||||
|
SET(PAM_FOUND TRUE)
|
||||||
|
ENDIF (PAM_INCLUDE_DIR)
|
||||||
|
|
||||||
|
IF (PAM_FOUND)
|
||||||
|
IF (NOT PAM_FIND_QUIETLY)
|
||||||
|
MESSAGE(STATUS "Found PAM (include path: ${PAM_INCLUDE_DIR})")
|
||||||
|
ENDIF (NOT PAM_FIND_QUIETLY)
|
||||||
|
ELSE (PAM_FOUND)
|
||||||
|
IF (PAM_FIND_REQUIRED)
|
||||||
|
MESSAGE(FATAL_ERROR "Could not find PAM")
|
||||||
|
ENDIF (PAM_FIND_REQUIRED)
|
||||||
|
ENDIF (PAM_FOUND)
|
20
Findlibnm_glib.cmake
Normal file
20
Findlibnm_glib.cmake
Normal file
|
@ -0,0 +1,20 @@
|
||||||
|
# Defines the following variables:
|
||||||
|
# LIBNM_GLIB_FOUND
|
||||||
|
# LIBNM_GLIB_INCLUDE_DIRS
|
||||||
|
# LIBNM_GLIB_CFLAGS_OTHER
|
||||||
|
# LIBNM_GLIB_LIBRARIES
|
||||||
|
# LIBNM_GLIB_LIBRARY_DIRS
|
||||||
|
# LIBNM_GLIB_LDFLAGS_OTHER
|
||||||
|
|
||||||
|
|
||||||
|
find_package(PkgConfig REQUIRED QUIET)
|
||||||
|
pkg_check_modules(_LIBNM_GLIB libnm-glib)
|
||||||
|
|
||||||
|
set(LIBNM_GLIB_INCLUDE_DIRS "${_LIBNM_GLIB_INCLUDE_DIRS}" CACHE STRING "Include directories for libnm-glib")
|
||||||
|
set(LIBNM_GLIB_CFLAGS_OTHER "${_LIBNM_GLIB_CFLAGS_OTHER}" CACHE STRING "Additional compiler flags for libnm-glib")
|
||||||
|
set(LIBNM_GLIB_LIBRARY_DIRS "${_LIBNM_GLIB_LIBRARY_DIRS}" CACHE STRING "Library directories for libnm-glib")
|
||||||
|
set(LIBNM_GLIB_LIBRARIES "${_LIBNM_GLIB_LIBRARIES}" CACHE STRING "Libraries for libnm-glib")
|
||||||
|
set(LIBNM_GLIB_LDFLAGS_OTHER "${_LIBNM_GLIB_LDFLAGS_OTHER}" CACHE STRING "Additional linker flags for libnm-glib")
|
||||||
|
|
||||||
|
find_package_handle_standard_args(LIBNM_GLIB REQUIRED_VARS LIBNM_GLIB_LIBRARIES LIBNM_GLIB_INCLUDE_DIRS)
|
||||||
|
mark_as_advanced(LIBNM_GLIB_INCLUDE_DIRS LIBNM_GLIB_CFLAGS_OTHER LIBNM_GLIB_LIBRARIES LIBNM_GLIB_LIBRARY_DIRS LIBNM_GLIB_LDFLAGS_OTHER)
|
23
LICENSE
Normal file
23
LICENSE
Normal file
|
@ -0,0 +1,23 @@
|
||||||
|
Copyright (c) 2015, Kristof Stahl <stahl@itsc.uni-luebeck.de>
|
||||||
|
Copyright (c) 2015, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||||
|
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.
|
||||||
|
|
||||||
|
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 HOLDER 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.
|
7
Makefile
7
Makefile
|
@ -1,7 +0,0 @@
|
||||||
all : pam_wlan.so pam_wlan_test
|
|
||||||
|
|
||||||
pam_wlan.so : pam_wlan.c
|
|
||||||
$(CC) -fPIC -shared -o pam_wlan.so pam_wlan.c $(shell pkg-config --cflags --libs libnm-glib) -Wall
|
|
||||||
|
|
||||||
pam_wlan_test : pam_wlan.c
|
|
||||||
$(CC) -g -DTEST -o pam_wlan_test pam_wlan.c $(shell pkg-config --cflags --libs libnm-glib) -Wall
|
|
41
config.h.in
Normal file
41
config.h.in
Normal file
|
@ -0,0 +1,41 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2015, Kristof Stahl <stahl@itsc.uni-luebeck.de>
|
||||||
|
Copyright (c) 2015, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||||
|
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.
|
||||||
|
|
||||||
|
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 HOLDER 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
#pragma once
|
||||||
|
|
||||||
|
|
||||||
|
#define PAM_NETWORK_MANAGER_HELPER "@PAM_NETWORK_MANAGER_HELPER_DIR@/pam_network_manager_helper"
|
||||||
|
|
||||||
|
|
||||||
|
#define CONNECTION_TIMEOUT @CONNECTION_TIMEOUT@
|
||||||
|
#define CONNECTION_ID "@CONNECTION_ID@"
|
||||||
|
#define CONNECTION_UUID "@CONNECTION_UUID@"
|
||||||
|
#define CONNECTION_SSID "@CONNECTION_SSID@"
|
||||||
|
#define CONNECTION_AUTH_ALG "@CONNECTION_AUTH_ALG@"
|
||||||
|
#define CONNECTION_KEY_MGMT "@CONNECTION_KEY_MGMT@"
|
||||||
|
#define CONNECTION_EAP "@CONNECTION_EAP@"
|
||||||
|
#define CONNECTION_PHASE2_AUTHEAP "@CONNECTION_PHASE2_AUTHEAP@"
|
101
pam_network_manager.c
Normal file
101
pam_network_manager.c
Normal file
|
@ -0,0 +1,101 @@
|
||||||
|
/*
|
||||||
|
Copyright (c) 2015, Kristof Stahl <stahl@itsc.uni-luebeck.de>
|
||||||
|
Copyright (c) 2015, Matthias Schiffer <mschiffer@universe-factory.net>
|
||||||
|
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.
|
||||||
|
|
||||||
|
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 HOLDER 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.
|
||||||
|
*/
|
||||||
|
|
||||||
|
|
||||||
|
/*
|
||||||
|
See:
|
||||||
|
|
||||||
|
http://www.linux-pam.org/Linux-PAM-html/mwg-expected-of-module-auth.html
|
||||||
|
http://www.linux-pam.org/Linux-PAM-html/mwg-expected-by-module-item.html
|
||||||
|
http://www.linux-pam.org/Linux-PAM-html/mwg-see-programming-libs.html
|
||||||
|
some (bad) example.. https://github.com/beatgammit/simple-pam/blob/master/src/mypam.c
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define PAM_SM_AUTH
|
||||||
|
|
||||||
|
#include <stdio.h>
|
||||||
|
#include <unistd.h>
|
||||||
|
|
||||||
|
#include <sys/types.h>
|
||||||
|
#include <sys/wait.h>
|
||||||
|
|
||||||
|
#include <security/pam_modules.h>
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
|
|
||||||
|
#define UNUSED __attribute__((unused))
|
||||||
|
|
||||||
|
|
||||||
|
static int authenticate(const char *user, const char *pass) {
|
||||||
|
FILE *stream = popen(PAM_NETWORK_MANAGER_HELPER, "we");
|
||||||
|
|
||||||
|
fputs(user, stream);
|
||||||
|
fputc(0, stream);
|
||||||
|
fputs(pass, stream);
|
||||||
|
|
||||||
|
int status = pclose(stream);
|
||||||
|
|
||||||
|
if (WIFEXITED(status))
|
||||||
|
return WEXITSTATUS(status);
|
||||||
|
else
|
||||||
|
return PAM_SYSTEM_ERR;
|
||||||
|
}
|
||||||
|
|
||||||
|
#ifdef TEST
|
||||||
|
|
||||||
|
int main(int argc, char *argv[]) {
|
||||||
|
if (argc != 2) {
|
||||||
|
fprintf(stderr, "Usage: pam_network_manager_test <user>\n");
|
||||||
|
return 1;
|
||||||
|
}
|
||||||
|
|
||||||
|
char *pass = getpass("Password: ");
|
||||||
|
|
||||||
|
fprintf(stderr, "Return: %i\n", authenticate(argv[1], pass));
|
||||||
|
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
#else
|
||||||
|
|
||||||
|
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, UNUSED int flags, UNUSED int argc, UNUSED const char **argv) {
|
||||||
|
const void *pass;
|
||||||
|
const void *user;
|
||||||
|
int result;
|
||||||
|
|
||||||
|
result = pam_get_item(pamh, PAM_USER, &user);
|
||||||
|
if (result != PAM_SUCCESS)
|
||||||
|
return PAM_INCOMPLETE;
|
||||||
|
|
||||||
|
result = pam_get_item(pamh, PAM_AUTHTOK, &pass);
|
||||||
|
if (result != PAM_SUCCESS)
|
||||||
|
return PAM_INCOMPLETE;
|
||||||
|
|
||||||
|
return authenticate(user, pass);
|
||||||
|
}
|
||||||
|
|
||||||
|
#endif
|
|
@ -26,31 +26,14 @@
|
||||||
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
Helpful pages:
|
See:
|
||||||
|
|
||||||
http://www.linux-pam.org/Linux-PAM-html/mwg-expected-of-module-auth.html
|
|
||||||
http://www.linux-pam.org/Linux-PAM-html/mwg-expected-by-module-item.html
|
|
||||||
http://www.linux-pam.org/Linux-PAM-html/mwg-see-programming-libs.html
|
|
||||||
some (bad) example.. https://github.com/beatgammit/simple-pam/blob/master/src/mypam.c
|
|
||||||
|
|
||||||
https://developer.gnome.org/libnm-glib/0.9/
|
https://developer.gnome.org/libnm-glib/0.9/
|
||||||
https://developer.gnome.org/libnm-util/0.9/
|
https://developer.gnome.org/libnm-util/0.9/
|
||||||
*/
|
*/
|
||||||
|
|
||||||
#define PAM_SM_AUTH
|
|
||||||
|
|
||||||
#ifdef TEST
|
|
||||||
|
|
||||||
#include <stdio.h>
|
#include <stdio.h>
|
||||||
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#include <stdlib.h>
|
|
||||||
#include <string.h>
|
#include <string.h>
|
||||||
#include <unistd.h>
|
|
||||||
|
|
||||||
#include <sys/types.h>
|
|
||||||
#include <sys/wait.h>
|
|
||||||
|
|
||||||
#include <security/pam_modules.h>
|
#include <security/pam_modules.h>
|
||||||
|
|
||||||
|
@ -63,16 +46,10 @@
|
||||||
#include <nm-setting-ip4-config.h>
|
#include <nm-setting-ip4-config.h>
|
||||||
#include <nm-setting-ip6-config.h>
|
#include <nm-setting-ip6-config.h>
|
||||||
|
|
||||||
|
#include <config.h>
|
||||||
|
|
||||||
#define TIMEOUT 10
|
|
||||||
#define CONNECTION_ID "UzL-Wlan"
|
|
||||||
#define CONNECTION_UUID "af7b7f0b-3e09-442e-8841-f7d7482fa7b0"
|
|
||||||
|
|
||||||
#define CONNECTION_SSID "UzL-Wlan"
|
#define UNUSED __attribute__((unused))
|
||||||
#define CONNECTION_AUTH_ALG "open"
|
|
||||||
#define CONNECTION_KEY_MGMT "wpa-eap"
|
|
||||||
#define CONNECTION_EAP "ttls"
|
|
||||||
#define CONNECTION_PHASE2_AUTHEAP "mschapv2"
|
|
||||||
|
|
||||||
|
|
||||||
static GByteArray * string_to_byte_array(const char *str) {
|
static GByteArray * string_to_byte_array(const char *str) {
|
||||||
|
@ -135,7 +112,7 @@ static int setup_connection(NMConnection *con, const char *user, const char *pas
|
||||||
/* NMSettingIP6Config */
|
/* NMSettingIP6Config */
|
||||||
setting = nm_setting_ip6_config_new();
|
setting = nm_setting_ip6_config_new();
|
||||||
g_object_set(G_OBJECT(setting),
|
g_object_set(G_OBJECT(setting),
|
||||||
NM_SETTING_IP6_CONFIG_METHOD, "auto",
|
NM_SETTING_IP6_CONFIG_METHOD, "link-local",
|
||||||
NULL);
|
NULL);
|
||||||
nm_connection_add_setting(con, setting);
|
nm_connection_add_setting(con, setting);
|
||||||
|
|
||||||
|
@ -146,6 +123,7 @@ typedef struct {
|
||||||
int ret;
|
int ret;
|
||||||
GMainLoop *loop;
|
GMainLoop *loop;
|
||||||
NMClient *client;
|
NMClient *client;
|
||||||
|
NMRemoteConnection *con;
|
||||||
} cb_arg;
|
} cb_arg;
|
||||||
|
|
||||||
|
|
||||||
|
@ -163,7 +141,14 @@ static NMDevice * find_device(NMClient *client) {
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void state_cb(NMDevice *device, GParamSpec *pspec, gpointer user_data) {
|
static gboolean timeout_cb(gpointer user_data) {
|
||||||
|
cb_arg *arg = user_data;
|
||||||
|
g_main_loop_quit(arg->loop);
|
||||||
|
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static void state_cb(NMDevice *device, UNUSED GParamSpec *pspec, gpointer user_data) {
|
||||||
cb_arg *arg = user_data;
|
cb_arg *arg = user_data;
|
||||||
|
|
||||||
NMActiveConnection *active_connection = nm_device_get_active_connection(device);
|
NMActiveConnection *active_connection = nm_device_get_active_connection(device);
|
||||||
|
@ -180,20 +165,19 @@ static void state_cb(NMDevice *device, GParamSpec *pspec, gpointer user_data) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static void activate_cb(NMClient *client, NMActiveConnection *active_connection, GError *error, gpointer user_data) {
|
static void activate_cb(UNUSED NMClient *client, UNUSED NMActiveConnection *active_connection, GError *error, gpointer user_data) {
|
||||||
cb_arg *arg = user_data;
|
cb_arg *arg = user_data;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
g_main_loop_quit(arg->loop);
|
g_main_loop_quit(arg->loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
static void add_cb(NMRemoteSettings *settings, NMRemoteConnection *con, GError *error, gpointer user_data) {
|
static void add_cb(UNUSED NMRemoteSettings *settings, NMRemoteConnection *con, GError *error, gpointer user_data) {
|
||||||
cb_arg *arg = user_data;
|
cb_arg *arg = user_data;
|
||||||
|
|
||||||
if (error)
|
if (error)
|
||||||
|
@ -203,21 +187,86 @@ static void add_cb(NMRemoteSettings *settings, NMRemoteConnection *con, GError *
|
||||||
if (!device)
|
if (!device)
|
||||||
goto error;
|
goto error;
|
||||||
|
|
||||||
|
arg->con = con;
|
||||||
|
|
||||||
g_signal_connect(device, "notify::state", G_CALLBACK(state_cb), arg);
|
g_signal_connect(device, "notify::state", G_CALLBACK(state_cb), arg);
|
||||||
nm_client_activate_connection(arg->client, NM_CONNECTION(con), device, NULL, activate_cb, arg);
|
nm_client_activate_connection(arg->client, NM_CONNECTION(con), device, NULL, activate_cb, arg);
|
||||||
|
|
||||||
|
g_timeout_add_seconds(CONNECTION_TIMEOUT, timeout_cb, arg);
|
||||||
return;
|
return;
|
||||||
|
|
||||||
error:
|
error:
|
||||||
g_main_loop_quit(arg->loop);
|
g_main_loop_quit(arg->loop);
|
||||||
}
|
}
|
||||||
|
|
||||||
static int do_authenticate(const char *user, const char *pass) {
|
static void delete_cb(UNUSED NMRemoteConnection *connection, UNUSED GError *error, gpointer user_data) {
|
||||||
|
cb_arg *arg = user_data;
|
||||||
|
g_main_loop_quit(arg->loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void read_cb(UNUSED NMRemoteSettings *settings, gpointer user_data) {
|
||||||
|
cb_arg *arg = user_data;
|
||||||
|
g_main_loop_quit(arg->loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean match_connection_user(NMConnection *connection, const char *user) {
|
||||||
|
NMSetting8021x *setting = nm_connection_get_setting_802_1x(connection);
|
||||||
|
if (!setting)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
const char *identity = nm_setting_802_1x_get_identity(setting);
|
||||||
|
if (!identity)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
return (strcmp(identity, user) == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean is_connection_active(NMConnection *connection, cb_arg *arg) {
|
||||||
|
NMDevice *device = find_device(arg->client);
|
||||||
|
if (!device)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
NMActiveConnection *active_connection = nm_device_get_active_connection(device);
|
||||||
|
if (!active_connection)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
if (strcmp(nm_connection_get_path(connection), nm_active_connection_get_connection(active_connection)) != 0)
|
||||||
|
return FALSE;
|
||||||
|
|
||||||
|
NMActiveConnectionState state = nm_active_connection_get_state(active_connection);
|
||||||
|
|
||||||
|
return (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED);
|
||||||
|
}
|
||||||
|
|
||||||
|
static gboolean handle_old_connection(NMRemoteSettings *settings, const char *user, cb_arg *arg) {
|
||||||
|
NMRemoteConnection *con = NULL;
|
||||||
|
|
||||||
|
g_signal_connect(settings, NM_REMOTE_SETTINGS_CONNECTIONS_READ,
|
||||||
|
G_CALLBACK(read_cb), arg);
|
||||||
|
|
||||||
|
g_main_loop_run(arg->loop);
|
||||||
|
|
||||||
|
con = nm_remote_settings_get_connection_by_uuid(settings, CONNECTION_UUID);
|
||||||
|
if (!con)
|
||||||
|
goto end;
|
||||||
|
|
||||||
|
if (match_connection_user(NM_CONNECTION(con), user) && is_connection_active(NM_CONNECTION(con), arg))
|
||||||
|
return TRUE;
|
||||||
|
|
||||||
|
nm_remote_connection_delete(con, delete_cb, arg);
|
||||||
|
g_main_loop_run(arg->loop);
|
||||||
|
|
||||||
|
end:
|
||||||
|
return FALSE;
|
||||||
|
}
|
||||||
|
|
||||||
|
static int authenticate(const char *user, const char *pass) {
|
||||||
DBusGConnection *dbus = NULL;
|
DBusGConnection *dbus = NULL;
|
||||||
NMRemoteSettings *settings = NULL;
|
NMRemoteSettings *settings = NULL;
|
||||||
NMConnection *con = NULL;
|
NMConnection *con = NULL;
|
||||||
cb_arg arg = {};
|
cb_arg arg = {};
|
||||||
|
|
||||||
arg.ret = PAM_SYSTEM_ERR;
|
arg.ret = PAM_SERVICE_ERR;
|
||||||
arg.loop = g_main_loop_new(NULL, FALSE);
|
arg.loop = g_main_loop_new(NULL, FALSE);
|
||||||
|
|
||||||
arg.client = nm_client_new();
|
arg.client = nm_client_new();
|
||||||
|
@ -232,7 +281,13 @@ static int do_authenticate(const char *user, const char *pass) {
|
||||||
if (!settings)
|
if (!settings)
|
||||||
goto end;
|
goto end;
|
||||||
|
|
||||||
|
if (handle_old_connection(settings, user, &arg)) {
|
||||||
|
arg.ret = PAM_IGNORE;
|
||||||
|
goto end;
|
||||||
|
}
|
||||||
|
|
||||||
con = nm_connection_new();
|
con = nm_connection_new();
|
||||||
|
|
||||||
setup_connection(con, user, pass);
|
setup_connection(con, user, pass);
|
||||||
|
|
||||||
if (!nm_remote_settings_add_connection_unsaved(settings, con, add_cb, &arg))
|
if (!nm_remote_settings_add_connection_unsaved(settings, con, add_cb, &arg))
|
||||||
|
@ -242,81 +297,47 @@ static int do_authenticate(const char *user, const char *pass) {
|
||||||
|
|
||||||
g_main_loop_run(arg.loop);
|
g_main_loop_run(arg.loop);
|
||||||
|
|
||||||
end:
|
if (arg.ret == PAM_SUCCESS)
|
||||||
g_object_unref(con);
|
goto end;
|
||||||
|
|
||||||
|
/* Error */
|
||||||
|
if (arg.con) {
|
||||||
|
nm_remote_connection_delete(arg.con, delete_cb, &arg);
|
||||||
|
g_main_loop_run(arg.loop);
|
||||||
|
}
|
||||||
|
|
||||||
|
end:
|
||||||
|
if (con)
|
||||||
|
g_object_unref(con);
|
||||||
|
if (settings)
|
||||||
g_object_unref(settings);
|
g_object_unref(settings);
|
||||||
|
if (dbus)
|
||||||
dbus_g_connection_unref(dbus);
|
dbus_g_connection_unref(dbus);
|
||||||
|
if (arg.client)
|
||||||
g_object_unref(arg.client);
|
g_object_unref(arg.client);
|
||||||
g_main_loop_unref(arg.loop);
|
g_main_loop_unref(arg.loop);
|
||||||
|
|
||||||
return arg.ret;
|
return arg.ret;
|
||||||
}
|
}
|
||||||
|
|
||||||
static int authenticate(const char *user, const char *pass) {
|
int main() {
|
||||||
int status;
|
char buf[1024];
|
||||||
int fds[2];
|
size_t len = 0;
|
||||||
if (pipe(fds))
|
|
||||||
return PAM_SYSTEM_ERR;
|
|
||||||
|
|
||||||
pid_t pid = fork();
|
while (len < sizeof(buf)-1) {
|
||||||
if (pid < 0)
|
size_t r = fread(buf+len, 1, sizeof(buf)-len-1, stdin);
|
||||||
return PAM_SYSTEM_ERR;
|
if (!r)
|
||||||
|
break;
|
||||||
|
|
||||||
if (pid == 0) {
|
len += r;
|
||||||
close(fds[0]);
|
|
||||||
status = do_authenticate(user, pass);
|
|
||||||
write(fds[1], &status, sizeof(status));
|
|
||||||
close(fds[1]);
|
|
||||||
_exit(0);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
close(fds[1]);
|
buf[len] = 0;
|
||||||
|
|
||||||
if (waitpid(pid, NULL, 0) < 0)
|
const char *user = buf;
|
||||||
goto error;
|
const char *pass = user + strlen(user) + 1;
|
||||||
|
if (pass > buf+len)
|
||||||
if (read(fds[0], &status, sizeof(status)) != sizeof(status))
|
|
||||||
goto error;
|
|
||||||
|
|
||||||
close(fds[0]);
|
|
||||||
return status;
|
|
||||||
|
|
||||||
error:
|
|
||||||
close(fds[0]);
|
|
||||||
return PAM_SYSTEM_ERR;
|
return PAM_SYSTEM_ERR;
|
||||||
}
|
|
||||||
|
|
||||||
#ifdef TEST
|
|
||||||
|
|
||||||
int main(int argc, char *argv[]) {
|
|
||||||
if (argc != 2) {
|
|
||||||
fprintf(stderr, "Usage: pam_wlan_test <user>\n");
|
|
||||||
return 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
char *pass = getpass("Password: ");
|
|
||||||
|
|
||||||
fprintf(stderr, "Return: %i\n", authenticate(argv[1], pass));
|
|
||||||
|
|
||||||
return 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
#else
|
|
||||||
|
|
||||||
PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, __attribute__((unused)) int flags, __attribute__((unused)) int argc, __attribute__((unused)) const char **argv) {
|
|
||||||
const void *pass;
|
|
||||||
const void *user;
|
|
||||||
int result;
|
|
||||||
|
|
||||||
result = pam_get_item(pamh, PAM_USER, &user);
|
|
||||||
if (result != PAM_SUCCESS)
|
|
||||||
return PAM_INCOMPLETE;
|
|
||||||
|
|
||||||
result = pam_get_item(pamh, PAM_AUTHTOK, &pass);
|
|
||||||
if (result != PAM_SUCCESS)
|
|
||||||
return PAM_INCOMPLETE;
|
|
||||||
|
|
||||||
return authenticate(user, pass);
|
return authenticate(user, pass);
|
||||||
}
|
}
|
||||||
#endif
|
|
Reference in a new issue