From 11f2c30f5b58de7c543ffc3e93fd508e3c8bcab3 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 12 May 2015 16:35:54 +0200 Subject: [PATCH 01/10] Split module into a helper executable and a minimal module --- CMakeLists.txt | 34 ++++++ FindPAM.cmake | 15 +++ Findlibnm_glib.cmake | 20 ++++ Makefile | 7 -- config.h.in | 31 +++++ pam_wlan.c | 253 +++-------------------------------------- pam_wlan_helper.c | 261 +++++++++++++++++++++++++++++++++++++++++++ 7 files changed, 377 insertions(+), 244 deletions(-) create mode 100644 CMakeLists.txt create mode 100644 FindPAM.cmake create mode 100644 Findlibnm_glib.cmake delete mode 100644 Makefile create mode 100644 config.h.in create mode 100644 pam_wlan_helper.c diff --git a/CMakeLists.txt b/CMakeLists.txt new file mode 100644 index 0000000..1bb7f49 --- /dev/null +++ b/CMakeLists.txt @@ -0,0 +1,34 @@ +cmake_minimum_required(VERSION 2.8.3) +project(PAM_WLAN C) + +set(CMAKE_MODULE_PATH ${PAM_WLAN_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_WLAN_HELPER_DIR "${CMAKE_INSTALL_PREFIX}/lib/security/pam_wlan" CACHE STRING "pam_wlan_helper install directory") + +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_wlan_helper pam_wlan_helper.c) +set_property(TARGET pam_wlan_helper PROPERTY COMPILE_DEFINITIONS "_DEFAULT_SOURCE;_BSD_SOURCE") +set_property(TARGET pam_wlan_helper PROPERTY COMPILE_FLAGS "-std=c99 -Wall ${LIBNM_GLIB_CFLAGS_OTHER}") +set_property(TARGET pam_wlan_helper PROPERTY LINK_FLAGS "${LIBNM_GLIB_LDFLAGS_OTHER}") +target_link_libraries(pam_wlan_helper ${LIBNM_GLIB_LIBRARIES}) + +add_executable(pam_wlan_test pam_wlan.c) +set_property(TARGET pam_wlan_test PROPERTY COMPILE_DEFINITIONS "_DEFAULT_SOURCE;_BSD_SOURCE;TEST") +set_property(TARGET pam_wlan_test PROPERTY COMPILE_FLAGS "-std=c99 -Wall") + +add_library(pam_wlan MODULE pam_wlan.c) +set_property(TARGET pam_wlan PROPERTY COMPILE_DEFINITIONS "_DEFAULT_SOURCE;_BSD_SOURCE") +set_property(TARGET pam_wlan PROPERTY COMPILE_FLAGS "-std=c99 -Wall") + +install(TARGETS pam_wlan pam_wlan_helper + RUNTIME DESTINATION "${PAM_WLAN_HELPER_DIR}" + LIBRARY DESTINATION "${PAM_MODULE_DIR}" +) diff --git a/FindPAM.cmake b/FindPAM.cmake new file mode 100644 index 0000000..bccdf9b --- /dev/null +++ b/FindPAM.cmake @@ -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) diff --git a/Findlibnm_glib.cmake b/Findlibnm_glib.cmake new file mode 100644 index 0000000..3256940 --- /dev/null +++ b/Findlibnm_glib.cmake @@ -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) diff --git a/Makefile b/Makefile deleted file mode 100644 index 0f62ec7..0000000 --- a/Makefile +++ /dev/null @@ -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 diff --git a/config.h.in b/config.h.in new file mode 100644 index 0000000..e5d6a26 --- /dev/null +++ b/config.h.in @@ -0,0 +1,31 @@ +/* + Copyright (c) 2015, Kristof Stahl + Copyright (c) 2015, Matthias Schiffer + 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_WLAN_HELPER "@PAM_WLAN_HELPER_DIR@/pam_wlan_helper" diff --git a/pam_wlan.c b/pam_wlan.c index 181bb6a..81abe8a 100644 --- a/pam_wlan.c +++ b/pam_wlan.c @@ -26,27 +26,17 @@ /* - 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-util/0.9/ */ #define PAM_SM_AUTH -#ifdef TEST - #include - -#endif - -#include -#include #include #include @@ -54,237 +44,25 @@ #include -#include -#include -#include -#include -#include -#include -#include -#include +#include -#define TIMEOUT 10 -#define CONNECTION_ID "UzL-Wlan" -#define CONNECTION_UUID "af7b7f0b-3e09-442e-8841-f7d7482fa7b0" +#define UNUSED __attribute__((unused)) -#define CONNECTION_SSID "UzL-Wlan" -#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) { - size_t len = strlen(str); - GByteArray *ba = g_byte_array_sized_new(len); - - g_byte_array_append(ba, (const unsigned char *)str, len); - - return ba; -} - -static int setup_connection(NMConnection *con, const char *user, const char *pass) { - NMSetting *setting; - - /* NMSettingConnection */ - setting = nm_setting_connection_new(); - g_object_set(G_OBJECT(setting), - NM_SETTING_CONNECTION_UUID, CONNECTION_UUID, - NM_SETTING_CONNECTION_ID, CONNECTION_ID, - NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, - NULL); - nm_connection_add_setting(con, setting); - - /* NMSettingWireless */ - setting = nm_setting_wireless_new(); - GByteArray *ssid = string_to_byte_array(CONNECTION_SSID); - g_object_set(G_OBJECT(setting), - NM_SETTING_WIRELESS_SSID, ssid, - NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA, - NULL); - g_byte_array_unref(ssid); - nm_connection_add_setting(con, setting); - - /* NMSettingWirelessSecurity */ - setting = nm_setting_wireless_security_new(); - g_object_set(G_OBJECT(setting), - NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, CONNECTION_AUTH_ALG, - NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, CONNECTION_KEY_MGMT, - NULL); - nm_connection_add_setting(con, setting); - - /* NMSetting8021x */ - setting = nm_setting_802_1x_new(); - /* TODO: Add certificate and subject check */ - nm_setting_802_1x_add_eap_method(NM_SETTING_802_1X(setting), CONNECTION_EAP); - g_object_set(setting, - NM_SETTING_802_1X_IDENTITY, user, - NM_SETTING_802_1X_PASSWORD, pass, - NM_SETTING_802_1X_PHASE2_AUTHEAP, CONNECTION_PHASE2_AUTHEAP, - NULL); - nm_connection_add_setting(con, setting); - - /* NMSettingIP4Config */ - setting = nm_setting_ip4_config_new(); - g_object_set(G_OBJECT(setting), - NM_SETTING_IP4_CONFIG_METHOD, "auto", - NULL); - nm_connection_add_setting(con, setting); - - /* NMSettingIP6Config */ - setting = nm_setting_ip6_config_new(); - g_object_set(G_OBJECT(setting), - NM_SETTING_IP6_CONFIG_METHOD, "auto", - NULL); - nm_connection_add_setting(con, setting); - - return PAM_SUCCESS; -} - -typedef struct { - int ret; - GMainLoop *loop; - NMClient *client; -} cb_arg; - - -static NMDevice * find_device(NMClient *client) { - size_t i; - const GPtrArray *devices = nm_client_get_devices(client); - - for (i = 0; i < devices->len; i++) { - NMDevice *device = g_ptr_array_index(devices, i); - - if (nm_device_get_device_type(device) == NM_DEVICE_TYPE_WIFI) - return device; - } - - return NULL; -} - -static void state_cb(NMDevice *device, GParamSpec *pspec, gpointer user_data) { - cb_arg *arg = user_data; - - NMActiveConnection *active_connection = nm_device_get_active_connection(device); - if (!active_connection) - return; - - NMActiveConnectionState state = nm_active_connection_get_state(active_connection); - - if (state != NM_ACTIVE_CONNECTION_STATE_ACTIVATING && state != NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) { - if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) - arg->ret = PAM_SUCCESS; - - g_main_loop_quit(arg->loop); - } -} - -static void activate_cb(NMClient *client, NMActiveConnection *active_connection, GError *error, gpointer user_data) { - cb_arg *arg = user_data; - - if (error) - goto error; - - - return; - - error: - g_main_loop_quit(arg->loop); -} - -static void add_cb(NMRemoteSettings *settings, NMRemoteConnection *con, GError *error, gpointer user_data) { - cb_arg *arg = user_data; - - if (error) - goto error; - - NMDevice *device = find_device(arg->client); - if (!device) - goto error; - - 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); - return; - - error: - g_main_loop_quit(arg->loop); -} - -static int do_authenticate(const char *user, const char *pass) { - DBusGConnection *dbus = NULL; - NMRemoteSettings *settings = NULL; - NMConnection *con = NULL; - cb_arg arg = {}; - - arg.ret = PAM_SYSTEM_ERR; - arg.loop = g_main_loop_new(NULL, FALSE); - - arg.client = nm_client_new(); - if (!arg.client) - goto end; - - dbus = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL); - if (!dbus) - goto end; - - settings = nm_remote_settings_new(dbus); - if (!settings) - goto end; - - con = nm_connection_new(); - setup_connection(con, user, pass); - - if (!nm_remote_settings_add_connection_unsaved(settings, con, add_cb, &arg)) - goto end; - - arg.ret = PAM_AUTH_ERR; - - g_main_loop_run(arg.loop); - - end: - g_object_unref(con); - - g_object_unref(settings); - dbus_g_connection_unref(dbus); - g_object_unref(arg.client); - g_main_loop_unref(arg.loop); - - return arg.ret; -} static int authenticate(const char *user, const char *pass) { - int status; - int fds[2]; - if (pipe(fds)) + FILE *stream = popen(PAM_WLAN_HELPER, "we"); + + fputs(user, stream); + fputc(0, stream); + fputs(pass, stream); + + int status = fclose(stream); + + if (WIFEXITED(status)) + return WEXITSTATUS(status); + else return PAM_SYSTEM_ERR; - - pid_t pid = fork(); - if (pid < 0) - return PAM_SYSTEM_ERR; - - if (pid == 0) { - close(fds[0]); - status = do_authenticate(user, pass); - write(fds[1], &status, sizeof(status)); - close(fds[1]); - _exit(0); - } - - close(fds[1]); - - if (waitpid(pid, NULL, 0) < 0) - goto error; - - if (read(fds[0], &status, sizeof(status)) != sizeof(status)) - goto error; - - close(fds[0]); - return status; - - error: - close(fds[0]); - return PAM_SYSTEM_ERR; } #ifdef TEST @@ -304,7 +82,7 @@ int main(int argc, char *argv[]) { #else -PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, __attribute__((unused)) int flags, __attribute__((unused)) int argc, __attribute__((unused)) const char **argv) { +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; @@ -319,4 +97,5 @@ PAM_EXTERN int pam_sm_authenticate(pam_handle_t *pamh, __attribute__((unused)) i return authenticate(user, pass); } + #endif diff --git a/pam_wlan_helper.c b/pam_wlan_helper.c new file mode 100644 index 0000000..76db00a --- /dev/null +++ b/pam_wlan_helper.c @@ -0,0 +1,261 @@ +/* + Copyright (c) 2015, Kristof Stahl + Copyright (c) 2015, Matthias Schiffer + 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: + + https://developer.gnome.org/libnm-glib/0.9/ + https://developer.gnome.org/libnm-util/0.9/ +*/ + +#include +#include + +#include + +#include +#include +#include +#include +#include +#include +#include +#include + + +#define TIMEOUT 10 +#define CONNECTION_ID "UzL-Wlan" +#define CONNECTION_UUID "af7b7f0b-3e09-442e-8841-f7d7482fa7b0" + +#define CONNECTION_SSID "UzL-Wlan" +#define CONNECTION_AUTH_ALG "open" +#define CONNECTION_KEY_MGMT "wpa-eap" +#define CONNECTION_EAP "ttls" +#define CONNECTION_PHASE2_AUTHEAP "mschapv2" + + +#define UNUSED __attribute__((unused)) + + +static GByteArray * string_to_byte_array(const char *str) { + size_t len = strlen(str); + GByteArray *ba = g_byte_array_sized_new(len); + + g_byte_array_append(ba, (const unsigned char *)str, len); + + return ba; +} + +static int setup_connection(NMConnection *con, const char *user, const char *pass) { + NMSetting *setting; + + /* NMSettingConnection */ + setting = nm_setting_connection_new(); + g_object_set(G_OBJECT(setting), + NM_SETTING_CONNECTION_UUID, CONNECTION_UUID, + NM_SETTING_CONNECTION_ID, CONNECTION_ID, + NM_SETTING_CONNECTION_TYPE, NM_SETTING_WIRELESS_SETTING_NAME, + NULL); + nm_connection_add_setting(con, setting); + + /* NMSettingWireless */ + setting = nm_setting_wireless_new(); + GByteArray *ssid = string_to_byte_array(CONNECTION_SSID); + g_object_set(G_OBJECT(setting), + NM_SETTING_WIRELESS_SSID, ssid, + NM_SETTING_WIRELESS_MODE, NM_SETTING_WIRELESS_MODE_INFRA, + NULL); + g_byte_array_unref(ssid); + nm_connection_add_setting(con, setting); + + /* NMSettingWirelessSecurity */ + setting = nm_setting_wireless_security_new(); + g_object_set(G_OBJECT(setting), + NM_SETTING_WIRELESS_SECURITY_AUTH_ALG, CONNECTION_AUTH_ALG, + NM_SETTING_WIRELESS_SECURITY_KEY_MGMT, CONNECTION_KEY_MGMT, + NULL); + nm_connection_add_setting(con, setting); + + /* NMSetting8021x */ + setting = nm_setting_802_1x_new(); + /* TODO: Add certificate and subject check */ + nm_setting_802_1x_add_eap_method(NM_SETTING_802_1X(setting), CONNECTION_EAP); + g_object_set(setting, + NM_SETTING_802_1X_IDENTITY, user, + NM_SETTING_802_1X_PASSWORD, pass, + NM_SETTING_802_1X_PHASE2_AUTHEAP, CONNECTION_PHASE2_AUTHEAP, + NULL); + nm_connection_add_setting(con, setting); + + /* NMSettingIP4Config */ + setting = nm_setting_ip4_config_new(); + g_object_set(G_OBJECT(setting), + NM_SETTING_IP4_CONFIG_METHOD, "auto", + NULL); + nm_connection_add_setting(con, setting); + + /* NMSettingIP6Config */ + setting = nm_setting_ip6_config_new(); + g_object_set(G_OBJECT(setting), + NM_SETTING_IP6_CONFIG_METHOD, "auto", + NULL); + nm_connection_add_setting(con, setting); + + return PAM_SUCCESS; +} + +typedef struct { + int ret; + GMainLoop *loop; + NMClient *client; +} cb_arg; + + +static NMDevice * find_device(NMClient *client) { + size_t i; + const GPtrArray *devices = nm_client_get_devices(client); + + for (i = 0; i < devices->len; i++) { + NMDevice *device = g_ptr_array_index(devices, i); + + if (nm_device_get_device_type(device) == NM_DEVICE_TYPE_WIFI) + return device; + } + + return NULL; +} + +static void state_cb(NMDevice *device, UNUSED GParamSpec *pspec, gpointer user_data) { + cb_arg *arg = user_data; + + NMActiveConnection *active_connection = nm_device_get_active_connection(device); + if (!active_connection) + return; + + NMActiveConnectionState state = nm_active_connection_get_state(active_connection); + + if (state != NM_ACTIVE_CONNECTION_STATE_ACTIVATING && state != NM_ACTIVE_CONNECTION_STATE_DEACTIVATING) { + if (state == NM_ACTIVE_CONNECTION_STATE_ACTIVATED) + arg->ret = PAM_SUCCESS; + + g_main_loop_quit(arg->loop); + } +} + +static void activate_cb(UNUSED NMClient *client, UNUSED NMActiveConnection *active_connection, GError *error, gpointer user_data) { + cb_arg *arg = user_data; + + if (error) + goto error; + + return; + + error: + g_main_loop_quit(arg->loop); +} + +static void add_cb(UNUSED NMRemoteSettings *settings, NMRemoteConnection *con, GError *error, gpointer user_data) { + cb_arg *arg = user_data; + + if (error) + goto error; + + NMDevice *device = find_device(arg->client); + if (!device) + goto error; + + 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); + return; + + error: + g_main_loop_quit(arg->loop); +} + +static int authenticate(const char *user, const char *pass) { + DBusGConnection *dbus = NULL; + NMRemoteSettings *settings = NULL; + NMConnection *con = NULL; + cb_arg arg = {}; + + arg.ret = PAM_SERVICE_ERR; + arg.loop = g_main_loop_new(NULL, FALSE); + + arg.client = nm_client_new(); + if (!arg.client) + goto end; + + dbus = dbus_g_bus_get(DBUS_BUS_SYSTEM, NULL); + if (!dbus) + goto end; + + settings = nm_remote_settings_new(dbus); + if (!settings) + goto end; + + con = nm_connection_new(); + setup_connection(con, user, pass); + + if (!nm_remote_settings_add_connection_unsaved(settings, con, add_cb, &arg)) + goto end; + + arg.ret = PAM_AUTH_ERR; + + g_main_loop_run(arg.loop); + + end: + g_object_unref(con); + + g_object_unref(settings); + dbus_g_connection_unref(dbus); + g_object_unref(arg.client); + g_main_loop_unref(arg.loop); + + return arg.ret; +} + +int main() { + char buf[1024]; + size_t len = 0; + + while (len < sizeof(buf)-1) { + size_t r = fread(buf+len, 1, sizeof(buf)-len-1, stdin); + if (!r) + break; + + len += r; + } + + buf[len] = 0; + + const char *user = buf; + const char *pass = user + strlen(user) + 1; + if (pass > buf+len) + return PAM_SYSTEM_ERR; + + return authenticate(user, pass); +} From 464a817a787374ba35776f5492367faa6f5cd3f8 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 12 May 2015 16:53:15 +0200 Subject: [PATCH 02/10] Fix library prefix --- CMakeLists.txt | 1 + 1 file changed, 1 insertion(+) diff --git a/CMakeLists.txt b/CMakeLists.txt index 1bb7f49..d762cd7 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -27,6 +27,7 @@ set_property(TARGET pam_wlan_test PROPERTY COMPILE_FLAGS "-std=c99 -Wall") add_library(pam_wlan MODULE pam_wlan.c) set_property(TARGET pam_wlan PROPERTY COMPILE_DEFINITIONS "_DEFAULT_SOURCE;_BSD_SOURCE") set_property(TARGET pam_wlan PROPERTY COMPILE_FLAGS "-std=c99 -Wall") +set_property(TARGET pam_wlan PROPERTY PREFIX "") install(TARGETS pam_wlan pam_wlan_helper RUNTIME DESTINATION "${PAM_WLAN_HELPER_DIR}" From 2f6cbf0a54775245f79b8c34cf0ba0cda3ae5583 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 12 May 2015 17:17:49 +0200 Subject: [PATCH 03/10] Make WLAN configuration configurable --- .gitignore | 2 -- CMakeLists.txt | 9 +++++++++ config.h.in | 10 ++++++++++ pam_wlan_helper.c | 11 +---------- 4 files changed, 20 insertions(+), 12 deletions(-) diff --git a/.gitignore b/.gitignore index 8d73a56..b25c15b 100644 --- a/.gitignore +++ b/.gitignore @@ -1,3 +1 @@ *~ -pam_wlan.so -pam_wlan_test diff --git a/CMakeLists.txt b/CMakeLists.txt index d762cd7..17a8385 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -9,6 +9,15 @@ find_package(libnm_glib REQUIRED) set(PAM_MODULE_DIR "${CMAKE_INSTALL_PREFIX}/lib/security" CACHE STRING "PAM module directory") set(PAM_WLAN_HELPER_DIR "${CMAKE_INSTALL_PREFIX}/lib/security/pam_wlan" CACHE STRING "pam_wlan_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}) diff --git a/config.h.in b/config.h.in index e5d6a26..6c83480 100644 --- a/config.h.in +++ b/config.h.in @@ -29,3 +29,13 @@ #define PAM_WLAN_HELPER "@PAM_WLAN_HELPER_DIR@/pam_wlan_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@" diff --git a/pam_wlan_helper.c b/pam_wlan_helper.c index 76db00a..7043ade 100644 --- a/pam_wlan_helper.c +++ b/pam_wlan_helper.c @@ -46,16 +46,7 @@ #include #include - -#define TIMEOUT 10 -#define CONNECTION_ID "UzL-Wlan" -#define CONNECTION_UUID "af7b7f0b-3e09-442e-8841-f7d7482fa7b0" - -#define CONNECTION_SSID "UzL-Wlan" -#define CONNECTION_AUTH_ALG "open" -#define CONNECTION_KEY_MGMT "wpa-eap" -#define CONNECTION_EAP "ttls" -#define CONNECTION_PHASE2_AUTHEAP "mschapv2" +#include #define UNUSED __attribute__((unused)) From b25738c7099997ede646aea1058cec5d2724df83 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 12 May 2015 17:20:03 +0200 Subject: [PATCH 04/10] Add LICENSE --- LICENSE | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) create mode 100644 LICENSE diff --git a/LICENSE b/LICENSE new file mode 100644 index 0000000..28f845a --- /dev/null +++ b/LICENSE @@ -0,0 +1,23 @@ +Copyright (c) 2015, Kristof Stahl +Copyright (c) 2015, Matthias Schiffer +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. From ccd489515476125f2c0e900d2d94531c6f88c037 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 12 May 2015 17:29:57 +0200 Subject: [PATCH 05/10] Use pclose instead of fclose --- pam_wlan.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pam_wlan.c b/pam_wlan.c index 81abe8a..3fed59d 100644 --- a/pam_wlan.c +++ b/pam_wlan.c @@ -57,7 +57,7 @@ static int authenticate(const char *user, const char *pass) { fputc(0, stream); fputs(pass, stream); - int status = fclose(stream); + int status = pclose(stream); if (WIFEXITED(status)) return WEXITSTATUS(status); From 7f6f56a7d5b406bd86ea3ca36fcb6ec8e4b915db Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 2 Jun 2015 14:57:13 +0200 Subject: [PATCH 06/10] Rename to pam_network_manager --- CMakeLists.txt | 34 +++++++++---------- config.h.in | 2 +- pam_wlan.c => pam_network_manager.c | 4 +-- ...n_helper.c => pam_network_manager_helper.c | 0 4 files changed, 20 insertions(+), 20 deletions(-) rename pam_wlan.c => pam_network_manager.c (95%) rename pam_wlan_helper.c => pam_network_manager_helper.c (100%) diff --git a/CMakeLists.txt b/CMakeLists.txt index 17a8385..74cddb8 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -1,13 +1,13 @@ cmake_minimum_required(VERSION 2.8.3) -project(PAM_WLAN C) +project(PAM_NETWORK_MANAGER C) -set(CMAKE_MODULE_PATH ${PAM_WLAN_SOURCE_DIR}) +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_WLAN_HELPER_DIR "${CMAKE_INSTALL_PREFIX}/lib/security/pam_wlan" CACHE STRING "pam_wlan_helper install 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") @@ -23,22 +23,22 @@ link_directories(${LIBNM_GLIB_LIBRARY_DIRS}) configure_file(${CMAKE_CURRENT_SOURCE_DIR}/config.h.in ${CMAKE_CURRENT_BINARY_DIR}/config.h) -add_executable(pam_wlan_helper pam_wlan_helper.c) -set_property(TARGET pam_wlan_helper PROPERTY COMPILE_DEFINITIONS "_DEFAULT_SOURCE;_BSD_SOURCE") -set_property(TARGET pam_wlan_helper PROPERTY COMPILE_FLAGS "-std=c99 -Wall ${LIBNM_GLIB_CFLAGS_OTHER}") -set_property(TARGET pam_wlan_helper PROPERTY LINK_FLAGS "${LIBNM_GLIB_LDFLAGS_OTHER}") -target_link_libraries(pam_wlan_helper ${LIBNM_GLIB_LIBRARIES}) +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_wlan_test pam_wlan.c) -set_property(TARGET pam_wlan_test PROPERTY COMPILE_DEFINITIONS "_DEFAULT_SOURCE;_BSD_SOURCE;TEST") -set_property(TARGET pam_wlan_test PROPERTY COMPILE_FLAGS "-std=c99 -Wall") +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_wlan MODULE pam_wlan.c) -set_property(TARGET pam_wlan PROPERTY COMPILE_DEFINITIONS "_DEFAULT_SOURCE;_BSD_SOURCE") -set_property(TARGET pam_wlan PROPERTY COMPILE_FLAGS "-std=c99 -Wall") -set_property(TARGET pam_wlan PROPERTY PREFIX "") +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_wlan pam_wlan_helper - RUNTIME DESTINATION "${PAM_WLAN_HELPER_DIR}" +install(TARGETS pam_network_manager pam_network_manager_helper + RUNTIME DESTINATION "${PAM_NETWORK_MANAGER_HELPER_DIR}" LIBRARY DESTINATION "${PAM_MODULE_DIR}" ) diff --git a/config.h.in b/config.h.in index 6c83480..a0ab8bc 100644 --- a/config.h.in +++ b/config.h.in @@ -28,7 +28,7 @@ #pragma once -#define PAM_WLAN_HELPER "@PAM_WLAN_HELPER_DIR@/pam_wlan_helper" +#define PAM_NETWORK_MANAGER_HELPER "@PAM_NETWORK_MANAGER_HELPER_DIR@/pam_network_manager_helper" #define CONNECTION_TIMEOUT @CONNECTION_TIMEOUT@ diff --git a/pam_wlan.c b/pam_network_manager.c similarity index 95% rename from pam_wlan.c rename to pam_network_manager.c index 3fed59d..15a2f3c 100644 --- a/pam_wlan.c +++ b/pam_network_manager.c @@ -51,7 +51,7 @@ static int authenticate(const char *user, const char *pass) { - FILE *stream = popen(PAM_WLAN_HELPER, "we"); + FILE *stream = popen(PAM_NETWORK_MANAGER_HELPER, "we"); fputs(user, stream); fputc(0, stream); @@ -69,7 +69,7 @@ static int authenticate(const char *user, const char *pass) { int main(int argc, char *argv[]) { if (argc != 2) { - fprintf(stderr, "Usage: pam_wlan_test \n"); + fprintf(stderr, "Usage: pam_network_manager_test \n"); return 1; } diff --git a/pam_wlan_helper.c b/pam_network_manager_helper.c similarity index 100% rename from pam_wlan_helper.c rename to pam_network_manager_helper.c From 4bc3bc211d2214374ad249468973c7f3c1a4df0d Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 2 Jun 2015 15:48:27 +0200 Subject: [PATCH 07/10] Add timeout support, delete connection on errors --- pam_network_manager_helper.c | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/pam_network_manager_helper.c b/pam_network_manager_helper.c index 7043ade..1027591 100644 --- a/pam_network_manager_helper.c +++ b/pam_network_manager_helper.c @@ -123,6 +123,7 @@ typedef struct { int ret; GMainLoop *loop; NMClient *client; + NMRemoteConnection *con; } cb_arg; @@ -140,6 +141,13 @@ static NMDevice * find_device(NMClient *client) { return NULL; } +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; @@ -179,14 +187,24 @@ static void add_cb(UNUSED NMRemoteSettings *settings, NMRemoteConnection *con, G if (!device) goto error; + arg->con = con; + 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); + + g_timeout_add_seconds(CONNECTION_TIMEOUT, timeout_cb, arg); return; error: g_main_loop_quit(arg->loop); } +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 int authenticate(const char *user, const char *pass) { DBusGConnection *dbus = NULL; NMRemoteSettings *settings = NULL; @@ -218,6 +236,16 @@ static int authenticate(const char *user, const char *pass) { g_main_loop_run(arg.loop); + if (arg.ret == PAM_SUCCESS) + goto end; + + /* Error */ + if (arg.con) { + nm_remote_connection_delete(arg.con, delete_cb, &arg); + + g_main_loop_run(arg.loop); + } + end: g_object_unref(con); From bb2788366187b080303e1cb6ec680024fb84a88e Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 2 Jun 2015 17:27:26 +0200 Subject: [PATCH 08/10] Delete old connection if it exists --- pam_network_manager_helper.c | 44 +++++++++++++++++++++++++++++++----- 1 file changed, 38 insertions(+), 6 deletions(-) diff --git a/pam_network_manager_helper.c b/pam_network_manager_helper.c index 1027591..c90fa8c 100644 --- a/pam_network_manager_helper.c +++ b/pam_network_manager_helper.c @@ -205,6 +205,30 @@ static void delete_cb(UNUSED NMRemoteConnection *connection, UNUSED GError *erro 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 handle_old_connection(NMRemoteSettings *settings, 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; + + 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; NMRemoteSettings *settings = NULL; @@ -226,7 +250,13 @@ static int authenticate(const char *user, const char *pass) { if (!settings) goto end; + if (handle_old_connection(settings, &arg)) { + arg.ret = PAM_SUCCESS; + goto end; + } + con = nm_connection_new(); + setup_connection(con, user, pass); if (!nm_remote_settings_add_connection_unsaved(settings, con, add_cb, &arg)) @@ -242,16 +272,18 @@ static int authenticate(const char *user, const char *pass) { /* Error */ if (arg.con) { nm_remote_connection_delete(arg.con, delete_cb, &arg); - g_main_loop_run(arg.loop); } end: - g_object_unref(con); - - g_object_unref(settings); - dbus_g_connection_unref(dbus); - g_object_unref(arg.client); + if (con) + g_object_unref(con); + if (settings) + g_object_unref(settings); + if (dbus) + dbus_g_connection_unref(dbus); + if (arg.client) + g_object_unref(arg.client); g_main_loop_unref(arg.loop); return arg.ret; From d309e3d0dfb81b7363858b715d59cf867a6edbda Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Thu, 4 Jun 2015 16:31:58 +0200 Subject: [PATCH 09/10] Don't delete the connection when it is already established for the correct user --- pam_network_manager_helper.c | 39 ++++++++++++++++++++++++++++++++---- 1 file changed, 35 insertions(+), 4 deletions(-) diff --git a/pam_network_manager_helper.c b/pam_network_manager_helper.c index c90fa8c..8447211 100644 --- a/pam_network_manager_helper.c +++ b/pam_network_manager_helper.c @@ -201,7 +201,6 @@ static void add_cb(UNUSED NMRemoteSettings *settings, NMRemoteConnection *con, G static void delete_cb(UNUSED NMRemoteConnection *connection, UNUSED GError *error, gpointer user_data) { cb_arg *arg = user_data; - g_main_loop_quit(arg->loop); } @@ -210,7 +209,36 @@ static void read_cb(UNUSED NMRemoteSettings *settings, gpointer user_data) { g_main_loop_quit(arg->loop); } -static gboolean handle_old_connection(NMRemoteSettings *settings, cb_arg *arg) { +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, @@ -222,6 +250,9 @@ static gboolean handle_old_connection(NMRemoteSettings *settings, cb_arg *arg) { 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); @@ -250,8 +281,8 @@ static int authenticate(const char *user, const char *pass) { if (!settings) goto end; - if (handle_old_connection(settings, &arg)) { - arg.ret = PAM_SUCCESS; + if (handle_old_connection(settings, user, &arg)) { + arg.ret = PAM_IGNORE; goto end; } From 409dbf4891ad8376ffac3ba7385fc32bbf1d63e5 Mon Sep 17 00:00:00 2001 From: Matthias Schiffer Date: Tue, 9 Jun 2015 16:08:01 +0200 Subject: [PATCH 10/10] Change IPv6 method to link-local --- pam_network_manager_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pam_network_manager_helper.c b/pam_network_manager_helper.c index 8447211..e4153f4 100644 --- a/pam_network_manager_helper.c +++ b/pam_network_manager_helper.c @@ -112,7 +112,7 @@ static int setup_connection(NMConnection *con, const char *user, const char *pas /* NMSettingIP6Config */ setting = nm_setting_ip6_config_new(); g_object_set(G_OBJECT(setting), - NM_SETTING_IP6_CONFIG_METHOD, "auto", + NM_SETTING_IP6_CONFIG_METHOD, "link-local", NULL); nm_connection_add_setting(con, setting);