Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[TACACS+] Add plugin support to bash. #8660

Merged
merged 29 commits into from
Oct 11, 2021
Merged
Show file tree
Hide file tree
Changes from 28 commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
cda3fa8
[TACACS] Add plugin support to bash.
liuh-80 Sep 2, 2021
cadfc8f
Build bash from source code
Sep 3, 2021
79b5004
Change diff file to based on 5.0-4 version
liuh-80 Sep 3, 2021
bea3b28
Change make file to apply plugin support diff.
liuh-80 Sep 3, 2021
2a167f5
Fix whitespace issue.
liuh-80 Sep 3, 2021
6b57fe2
Improve build config
Sep 3, 2021
6dc2564
Improve build config
Sep 3, 2021
1904a40
Improve build config
Sep 3, 2021
f1b55e8
Improve PR code
liuh-80 Sep 6, 2021
de63753
Merge branch 'dev/liuh/bash_plugin_support' of https://github.com/liu…
liuh-80 Sep 6, 2021
da9d484
Add files.
liuh-80 Sep 6, 2021
c6cef30
Improve PR.
liuh-80 Sep 6, 2021
ff0af03
Install patched bash package.
liuh-80 Sep 6, 2021
1b46066
Use quilt to manage patches.
liuh-80 Sep 9, 2021
3cfd4ce
Fix PR comments
liuh-80 Sep 9, 2021
e85a16b
Integrate UT.
liuh-80 Sep 9, 2021
112a656
Fix UT build issue.
liuh-80 Sep 9, 2021
84e57cc
Fix build issue.
liuh-80 Sep 10, 2021
a0593bc
Merge branch 'dev/liuh/bash_plugin_support' of https://github.com/liu…
liuh-80 Sep 10, 2021
9fa560c
Improve code.
liuh-80 Sep 10, 2021
989c52c
Fix CUnit missing issue
Sep 14, 2021
614c2ce
Fix CUnit missing issue
Sep 14, 2021
317619d
Merge branch 'dev/liuh/bash_plugin_support' of https://github.com/liu…
liuh-80 Sep 14, 2021
c8a7734
Fix UT build issue.
liuh-80 Sep 14, 2021
d4d1846
Fix UT build break issue.
liuh-80 Sep 15, 2021
fa97701
Improve code by PR comments.
liuh-80 Sep 16, 2021
849a9a8
Merge branch 'dev/liuh/bash_plugin_support' of https://github.com/liu…
liuh-80 Sep 16, 2021
a1c51f9
Merge remote-tracking branch 'origin/master' into dev/liuh/bash_plugi…
liuh-80 Sep 17, 2021
ec852b4
Change to use 5.1-2 for debian-11 bullseye.
liuh-80 Oct 8, 2021
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions files/build_templates/sonic_debian_extension.j2
Original file line number Diff line number Diff line change
Expand Up @@ -265,6 +265,10 @@ sudo rm -rf $FILESYSTEM_ROOT/$SONIC_UTILITIES_PY3_WHEEL_NAME
sudo dpkg --root=$FILESYSTEM_ROOT -i $debs_path/sonic-utilities-data_*.deb || \
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f

# Install customized bash version to patch bash plugin support.
sudo dpkg --root=$FILESYSTEM_ROOT -i target/debs/bash_*.deb || \
sudo LANG=C DEBIAN_FRONTEND=noninteractive chroot $FILESYSTEM_ROOT apt-get -y install -f

# sonic-utilities-data installs bash-completion as a dependency. However, it is disabled by default
# in bash.bashrc, so we copy a version of the file with it enabled here.
sudo cp -f $IMAGE_CONFIGS/bash/bash.bashrc $FILESYSTEM_ROOT/etc/
Expand Down
14 changes: 6 additions & 8 deletions rules/bash.mk
Original file line number Diff line number Diff line change
@@ -1,14 +1,12 @@
# bash package
#
# Created to patch memory-leak issue in the bash-package included in Debian-8 (Jessie)
# release. This rule file, and the associated building-infra created to solve this
# bug (src/bash/), should be eliminated once the migration to Debian-9 (Stretch) is
# completed.
# Created to patch plugin support in the bash-package included in Debian-10 (Buster)
# release.

# Bash major release-number corresponding to Debian-8 (Jessie)
BASH_VERSION_MAJOR = 4.3
# Bash complete release-number. This image contains all 4.3 fixes up to patch '42'.
BASH_VERSION_FULL = $(BASH_VERSION_MAJOR)-14
# Bash major release-number corresponding to Debian-10 (Buster)
BASH_VERSION_MAJOR = 5.0
Copy link
Collaborator

@qiluo-msft qiluo-msft Sep 18, 2021

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

5.0

Bullseye is using even newer version. It is not a good idea to build an old version for it. #Closed

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Bullseye using 5.1-2+b3 version: https://packages.debian.org/stable/shells/bash
will change to this version.

Copy link
Contributor Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Fixed.

# Bash complete release-number. This image contains all 5.0 fixes up to patch '4'.
BASH_VERSION_FULL = $(BASH_VERSION_MAJOR)-4

export BASH_VERSION_MAJOR BASH_VERSION_FULL

Expand Down
3 changes: 2 additions & 1 deletion slave.mk
Original file line number Diff line number Diff line change
Expand Up @@ -910,7 +910,8 @@ $(addprefix $(TARGET_PATH)/, $(SONIC_INSTALLERS)) : $(TARGET_PATH)/% : \
$(PYTHON_SWSSCOMMON) \
$(PYTHON3_SWSSCOMMON) \
$(SONIC_UTILITIES_DATA) \
$(SONIC_HOST_SERVICES_DATA)) \
$(SONIC_HOST_SERVICES_DATA) \
$(BASH)) \
$$(addprefix $(TARGET_PATH)/,$$($$*_DOCKERS)) \
$$(addprefix $(TARGET_PATH)/,$$(SONIC_PACKAGES_LOCAL)) \
$$(addprefix $(FILES_PATH)/,$$($$*_FILES)) \
Expand Down
6 changes: 6 additions & 0 deletions sonic-slave-bullseye/Dockerfile.j2
Original file line number Diff line number Diff line change
Expand Up @@ -250,6 +250,12 @@ RUN apt-get update && apt-get install -y \
iproute2 \
# For bash
texi2html \
sharutils \
locales \
time \
man2html-base \
libcunit1 \
libcunit1-dev \
# For initramfs
shellcheck \
bash-completion \
Expand Down
6 changes: 6 additions & 0 deletions sonic-slave-buster/Dockerfile.j2
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,12 @@ RUN apt-get update && apt-get install -y \
iproute2 \
# For bash
texi2html \
sharutils \
locales \
time \
man2html-base \
libcunit1 \
libcunit1-dev \
# For initramfs
shellcheck \
bash-completion \
Expand Down
6 changes: 6 additions & 0 deletions sonic-slave-jessie/Dockerfile.j2
Original file line number Diff line number Diff line change
Expand Up @@ -231,6 +231,12 @@ RUN apt-get update && apt-get install -y \
texlive-latex-recommended \
# For bash
texi2html \
sharutils \
locales \
time \
man2html-base \
libcunit1 \
libcunit1-dev \
# For initramfs
bash-completion \
{% if CONFIGURED_ARCH == "amd64" -%}
Expand Down
6 changes: 6 additions & 0 deletions sonic-slave-stretch/Dockerfile.j2
Original file line number Diff line number Diff line change
Expand Up @@ -254,6 +254,12 @@ RUN apt-get update && apt-get install -y \
iproute2 \
# For bash
texi2html \
sharutils \
locales \
time \
man2html-base \
libcunit1 \
libcunit1-dev \
# For initramfs
bash-completion \
{%- if CONFIGURED_ARCH == "amd64" %}
Expand Down
4 changes: 4 additions & 0 deletions src/bash/.gitignore
Original file line number Diff line number Diff line change
@@ -1,3 +1,7 @@
*
!.gitignore
!Makefile
!Files/
!Files/*
!patches/
!patches/*
18 changes: 18 additions & 0 deletions src/bash/Files/unittest/Makefile
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
#disable some warning because UT need test functions not in header file.
CFLAGS = -Wno-parentheses -Wno-format-security -Wno-implicit-function-declaration -c
IFLAGS = -I.. -I../include -I../lib
MFLAG = -DDEBUG -DBASH_PLUGIN_UT

all:
gcc plugin_test.c $(IFLAGS) $(CFLAGS) -o plugin_test.o
gcc mock_helper.c $(IFLAGS) $(CFLAGS) -o mock_helper.o
gcc ../plugin.c $(IFLAGS) $(CFLAGS) $(MFLAG) -o plugin.o
gcc plugin_test.o mock_helper.o plugin.o -o plugin_test -lc -lcunit

test:
# run unit test, if UT failed, build will break
./plugin_test
liuh-80 marked this conversation as resolved.
Show resolved Hide resolved

clean:
rm *.o
rm plugin_test
6 changes: 6 additions & 0 deletions src/bash/Files/unittest/bash_plugins.conf
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
# tacacs authorization plugin
plugin=/home/liuh/tacacs-bash-plugin/tacacs-authorization.so
plugin=/usr/lib/bash-plugins/another_test_plugin.so # test comments


# test line
218 changes: 218 additions & 0 deletions src/bash/Files/unittest/mock_helper.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,218 @@
/* mock_helper.c -- mock helper for bash plugin UT. */
#include <stdarg.h>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <CUnit/CUnit.h>
#include <CUnit/Basic.h>
#include "mock_helper.h"

// define BASH_PLUGIN_UT_DEBUG to output UT debug message.
//#define BASH_PLUGIN_UT_DEBUG
#if defined (BASH_PLUGIN_UT_DEBUG)
# define debug_printf printf
#else
# define debug_printf
#endif

/* itrace buffer */
char mock_itrace_message_buffer[1024];

/* bash run command buffer */
char mock_onshell_execve_command_buffer[1024];

/* plugin handles. */
void* mock_plugin_handle = (void*)TEST_MOCK_PLUGIN_HANDLE;
void* mock_plugin_default_function_handle = (void*)0x2234;
void* mock_plugin_on_shell_execve_handle = (void*)0x3234;
char* mock_dlerror_failed = "MOCK error";
char* mock_dlerror = NULL;

/* define test scenarios for mock functions return different value by scenario. */
int test_scenario;

/* define test scenarios for different return value. */
int plugin_init_status;

/* define memory allocate counter. */
int memory_allocate_count;

/* Set test scenario for test*/
void set_test_scenario(int scenario)
{
test_scenario = scenario;
}

/* Get test scenario for test*/
int get_test_scenario()
{
return test_scenario;
}

/* Set plugin init status for test*/
void set_plugin_init_status(int status)
{
plugin_init_status = status;
}

/* Get plugin init status for test*/
int get_plugin_init_status()
{
return plugin_init_status;
}

/* Set memory allocate count for test*/
void set_memory_allocate_count(int count)
{
memory_allocate_count = count;
}

/* Get memory allocate count for test*/
int get_memory_allocate_count()
{
return memory_allocate_count;
}

/* MOCK plugin_init method*/
int mock_plugin_init()
{
set_plugin_init_status(PLUGIN_INITIALIZED);
}

/* MOCK plugin_init method*/
int mock_plugin_uninit()
{
set_plugin_init_status(PLUGIN_NOT_INITIALIZE);
}

/* MOCK on_shell_execve method*/
int mock_on_shell_execve (char *user, int shell_level, char *cmd, char **argv)
{
// set mock command data to buffer for UT.
memset(mock_onshell_execve_command_buffer, 0, sizeof(mock_onshell_execve_command_buffer));

snprintf(mock_onshell_execve_command_buffer, sizeof(mock_onshell_execve_command_buffer), "on_shell_execve: user: %s, level: %d, command: %s, argv: %p\n", user, shell_level, cmd, argv);

debug_printf("MOCK: mock_on_shell_execve: %s\n", mock_onshell_execve_command_buffer);
}

/* MOCK dlopen*/
void *dlopen(const char *filename, int flags)
{
debug_printf("MOCK: dlopen: %s\n", filename);
if (TEST_SCEANRIO_PLUGIN_NOT_EXIT == test_scenario)
{
// return null when plugin not exist
mock_dlerror = mock_dlerror_failed;
return NULL;
}

// all other case return mock handle
mock_dlerror = NULL;
return mock_plugin_handle;
}

/* MOCK dlclose*/
int dlclose(void *handle)
{
debug_printf("MOCK: dlclose: %p\n", handle);
// check if the close handle match the opened handle
CU_ASSERT_EQUAL(handle, mock_plugin_handle);
}

/* MOCK dlsym*/
void *dlsym(void *restrict handle, const char *restrict symbol)
{
debug_printf("MOCK: dlsym: %p, %s\n", handle, symbol);
mock_dlerror = NULL;
switch (test_scenario)
{
case TEST_SCEANRIO_PLUGIN_EXECVE_NOT_EXIT:
if (strcmp(symbol, "on_shell_execve") == 0)
{
mock_dlerror = mock_dlerror_failed;
return NULL;
}

case TEST_SCEANRIO_PLUGIN_UNINIT_NOT_EXIT:
if (strcmp(symbol, "plugin_uninit") == 0)
{
mock_dlerror = mock_dlerror_failed;
return NULL;
}

case TEST_SCEANRIO_PLUGIN_INIT_NOT_EXIT:
if (strcmp(symbol, "plugin_init") == 0)
{
mock_dlerror = mock_dlerror_failed;
return NULL;
}

case TEST_SCEANRIO_PLUGIN_INIT_SUCCESS:
if (strcmp(symbol, "plugin_init") == 0)
{
// return mock method handle so plugin framework will call it to initialize
return mock_plugin_init;
}
else if (strcmp(symbol, "plugin_uninit") == 0)
{
// return mock method handle so plugin framework will call it to initialize
return mock_plugin_uninit;
}
else if (strcmp(symbol, "on_shell_execve") == 0)
{
// return mock method handle so plugin framework will call it to initialize
return mock_on_shell_execve;
}
}

return mock_plugin_default_function_handle;
}

/* MOCK dlerror*/
char *dlerror(void)
{
return mock_dlerror;
}

/* MOCK get_string_value*/
char *get_string_value(const char * str)
{
return "1";
}

/* MOCK absolute_program*/
int absolute_program (const char * str)
{
return 0;
}

/* MOCK itrace*/
void itrace (const char * format, ...)
{
// set mock message data to buffer for UT.
memset(mock_itrace_message_buffer, 0, sizeof(mock_itrace_message_buffer));

va_list args;
va_start(args, format);
// save message to buffer to UT check later
vsnprintf(mock_itrace_message_buffer, sizeof(mock_itrace_message_buffer), format, args);
va_end(args);
debug_printf("MOCK: itrace: %s\n", mock_itrace_message_buffer);
}

/* MOCK malloc method*/
void* mock_malloc (size_t size)
{
memory_allocate_count++;
debug_printf("MOCK: malloc memory count: %d\n", memory_allocate_count);
return malloc(size);
}

/* MOCK free method*/
void mock_free (void* ptr)
{
memory_allocate_count--;
debug_printf("MOCK: free memory count: %d\n", memory_allocate_count);
free(ptr);
}
Loading