src/plugins/down-root/Makefile
tests/Makefile
tests/unit_tests/Makefile
+ tests/unit_tests/plugins/Makefile
+ tests/unit_tests/plugins/auth-pam/Makefile
tests/unit_tests/example_test/Makefile
vendor/Makefile
sample/Makefile
endif
openvpn_plugin_auth_pam_la_SOURCES = \
+ utils.c \
auth-pam.c \
pamdl.c pamdl.h \
auth-pam.exports
#include <stdio.h>
#include <string.h>
#include <ctype.h>
-#include <stdbool.h>
#include <unistd.h>
#include <stdlib.h>
#include <sys/types.h>
#include <fcntl.h>
#include <signal.h>
#include <syslog.h>
-#include <stdint.h>
+#include "utils.h"
#include <openvpn-plugin.h>
/* Background process function */
static void pam_server (int fd, const char *service, int verb, const struct name_value_list *name_value_list);
-/* Read 'tosearch', replace all occurences of 'searchfor' with 'replacewith' and return
- * a pointer to the NEW string. Does not modify the input strings. Will not enter an
- * infinite loop with clever 'searchfor' and 'replacewith' strings.
- * Daniel Johnson - Progman2000@usa.net / djohnson@progman.us
- *
- * Retuns NULL when
- * - any parameter is NULL
- * - the worst-case result is to large ( >= SIZE_MAX)
- */
-static char *
-searchandreplace(const char *tosearch, const char *searchfor, const char *replacewith)
-{
- if (!tosearch || !searchfor || !replacewith) return NULL;
-
- size_t tosearchlen = strlen(tosearch);
- size_t replacewithlen = strlen(replacewith);
- size_t templen = tosearchlen * replacewithlen;
-
- if (tosearchlen == 0 || strlen(searchfor) == 0 || replacewithlen == 0) {
- return NULL;
- }
-
- bool is_potential_integer_overflow = (templen == SIZE_MAX) || (templen / tosearchlen != replacewithlen);
-
- if (is_potential_integer_overflow) {
- return NULL;
- }
-
- // state: all parameters are valid
-
- const char *searching=tosearch;
- char *scratch;
-
- char temp[templen+1];
- temp[0]=0;
-
- scratch = strstr(searching,searchfor);
- if (!scratch) return strdup(tosearch);
-
- while (scratch) {
- strncat(temp,searching,scratch-searching);
- strcat(temp,replacewith);
-
- searching=scratch+strlen(searchfor);
- scratch = strstr(searching,searchfor);
- }
- return strdup(temp);
-}
-
-/*
- * Given an environmental variable name, search
- * the envp array for its value, returning it
- * if found or NULL otherwise.
- */
-static const char *
-get_env (const char *name, const char *envp[])
-{
- if (envp)
- {
- int i;
- const int namelen = strlen (name);
- for (i = 0; envp[i]; ++i)
- {
- if (!strncmp (envp[i], name, namelen))
- {
- const char *cp = envp[i] + namelen;
- if (*cp == '=')
- return cp + 1;
- }
- }
- }
- return NULL;
-}
-
-/*
- * Return the length of a string array
- */
-static int
-string_array_len (const char *array[])
-{
- int i = 0;
- if (array)
- {
- while (array[i])
- ++i;
- }
- return i;
-}
/*
* Socket read/write functions.
--- /dev/null
+/*
+ * OpenVPN -- An application to securely tunnel IP networks
+ * over a single TCP/UDP port, with support for SSL/TLS-based
+ * session authentication and key exchange,
+ * packet encryption, packet authentication, and
+ * packet compression.
+ *
+ * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+/*
+ * OpenVPN plugin module to do PAM authentication using a split
+ * privilege model.
+ */
+#ifdef HAVE_CONFIG_H
+#include <config.h>
+#endif
+
+
+#include <string.h>
+#include <ctype.h>
+#include <stdbool.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <stdint.h>
+
+#include "utils.h"
+
+char *
+searchandreplace(const char *tosearch, const char *searchfor, const char *replacewith)
+{
+ if (!tosearch || !searchfor || !replacewith) return NULL;
+
+ size_t tosearchlen = strlen(tosearch);
+ size_t replacewithlen = strlen(replacewith);
+ size_t templen = tosearchlen * replacewithlen;
+
+ if (tosearchlen == 0 || strlen(searchfor) == 0 || replacewithlen == 0) {
+ return NULL;
+ }
+
+ bool is_potential_integer_overflow = (templen == SIZE_MAX) || (templen / tosearchlen != replacewithlen);
+
+ if (is_potential_integer_overflow) {
+ return NULL;
+ }
+
+ // state: all parameters are valid
+
+ const char *searching=tosearch;
+ char *scratch;
+
+ char temp[templen+1];
+ temp[0]=0;
+
+ scratch = strstr(searching,searchfor);
+ if (!scratch) return strdup(tosearch);
+
+ while (scratch) {
+ strncat(temp,searching,scratch-searching);
+ strcat(temp,replacewith);
+
+ searching=scratch+strlen(searchfor);
+ scratch = strstr(searching,searchfor);
+ }
+ return strdup(temp);
+}
+
+const char *
+get_env (const char *name, const char *envp[])
+{
+ if (envp)
+ {
+ int i;
+ const int namelen = strlen (name);
+ for (i = 0; envp[i]; ++i)
+ {
+ if (!strncmp (envp[i], name, namelen))
+ {
+ const char *cp = envp[i] + namelen;
+ if (*cp == '=')
+ return cp + 1;
+ }
+ }
+ }
+ return NULL;
+}
+
+int
+string_array_len (const char *array[])
+{
+ int i = 0;
+ if (array)
+ {
+ while (array[i])
+ ++i;
+ }
+ return i;
+}
--- /dev/null
+/*
+ * OpenVPN -- An application to securely tunnel IP networks
+ * over a single TCP/UDP port, with support for SSL/TLS-based
+ * session authentication and key exchange,
+ * packet encryption, packet authentication, and
+ * packet compression.
+ *
+ * Copyright (C) 2002-2010 OpenVPN Technologies, Inc. <sales@openvpn.net>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License version 2
+ * as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program (see the file COPYING included with this
+ * distribution); if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+ */
+
+#ifndef _PLUGIN_AUTH_PAM_UTILS__H
+#define _PLUGIN_AUTH_PAM_UTILS__H
+
+/**
+ * Read 'tosearch', replace all occurences of 'searchfor' with 'replacewith' and return
+ * a pointer to the NEW string. Does not modify the input strings. Will not enter an
+ * infinite loop with clever 'searchfor' and 'replacewith' strings.
+ *
+ * @author Daniel Johnson - Progman2000@usa.net / djohnson@progman.us
+ *
+ * @param tosearch haystack to search in
+ * @param searchfor needle to search for in the haystack
+ * @param replacewith when a match is found, replace needle with this string
+ *
+ * @return Retuns NULL when any parameter is NULL or the worst-case result is to large ( >= SIZE_MAX).
+ * Otherwise it returns a pointer to a new buffer containing the modified input
+ */
+char *
+searchandreplace(const char *tosearch, const char *searchfor, const char *replacewith);
+
+/**
+ * Given an environmental variable name, search
+ * the envp array for its value
+ *
+ * @param name Environment variable to look up
+ * @param envp Environment variable table with all key/value pairs
+ *
+ * @return Returns a pointer to the value of the enviroment variable if found, otherwise NULL is returned.
+ */
+const char *
+get_env (const char *name, const char *envp[]);
+
+/**
+ * Return the length of a string array
+ *
+ * @param array Pointer to the array to calculate size of
+ *
+ */
+int
+string_array_len (const char *array[]);
+
+#endif
AUTOMAKE_OPTIONS = foreign
-SUBDIRS = example_test
+SUBDIRS = example_test plugins
--- /dev/null
+AUTOMAKE_OPTIONS = foreign
+
+SUBDIRS = auth-pam
--- /dev/null
+AUTOMAKE_OPTIONS = foreign
+
+if ENABLE_PLUGIN_AUTH_PAM
+check_PROGRAMS = auth_pam_testdriver
+TESTS = $(check_PROGRAMS)
+endif
+
+sut_sourcedir = $(top_srcdir)/src/plugins/auth-pam
+
+auth_pam_testdriver_SOURCES = test_search_and_replace.c $(sut_sourcedir)/utils.h $(sut_sourcedir)/utils.c
+auth_pam_testdriver_CFLAGS = @TEST_CFLAGS@ -I$(sut_sourcedir)
+auth_pam_testdriver_LDFLAGS = @TEST_LDFLAGS@
--- /dev/null
+#include <stdio.h>
+#include <unistd.h>
+#include <stdlib.h>
+#include <stdarg.h>
+#include <string.h>
+#include <setjmp.h>
+#include <cmocka.h>
+
+#include "utils.h"
+
+static void pass_any_null_param__returns_null() {
+
+ char DUMMY[] = "DUMMY";
+
+ assert_null(searchandreplace(NULL,DUMMY,DUMMY));
+ assert_null(searchandreplace(DUMMY,NULL,DUMMY));
+ assert_null(searchandreplace(DUMMY,DUMMY,NULL));
+}
+
+static void pass_any_empty_string__returns_null() {
+
+ char DUMMY[] = "DUMMY";
+ char EMPTY[] = "";
+
+ assert_null(searchandreplace(EMPTY,DUMMY,DUMMY));
+ assert_null(searchandreplace(DUMMY,EMPTY,DUMMY));
+ assert_null(searchandreplace(DUMMY,DUMMY,EMPTY));
+}
+
+static void replace_single_char__one_time__match_is_replaced() {
+ char *replaced = searchandreplace("X","X","Y");
+
+ assert_non_null(replaced);
+ assert_string_equal("Y", replaced);
+
+ free(replaced);
+}
+
+static void replace_single_char__multiple_times__match_all_matches_are_replaced() {
+ char *replaced = searchandreplace("XaX","X","Y");
+
+ assert_non_null(replaced);
+ assert_string_equal ("YaY", replaced);
+
+ free(replaced);
+}
+
+static void replace_longer_text__multiple_times__match_all_matches_are_replaced() {
+ char *replaced = searchandreplace("XXaXX","XX","YY");
+
+ assert_non_null(replaced);
+ assert_string_equal ("YYaYY", replaced);
+
+ free(replaced);
+}
+
+static void pattern_not_found__returns_original() {
+ char *replaced = searchandreplace("abc","X","Y");
+
+ assert_non_null(replaced);
+ assert_string_equal ("abc", replaced);
+
+ free(replaced);
+}
+
+
+int main(void) {
+ const struct CMUnitTest tests[] = {
+ cmocka_unit_test(pass_any_null_param__returns_null),
+ cmocka_unit_test(pass_any_empty_string__returns_null),
+ cmocka_unit_test(replace_single_char__one_time__match_is_replaced),
+ cmocka_unit_test(replace_single_char__multiple_times__match_all_matches_are_replaced),
+ cmocka_unit_test(replace_longer_text__multiple_times__match_all_matches_are_replaced),
+ cmocka_unit_test(pattern_not_found__returns_original),
+ };
+
+ return cmocka_run_group_tests_name("searchandreplace", tests, NULL, NULL);
+}