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

Add PAM module stub generator, modules implmentations and integration tests #13

Open
wants to merge 24 commits into
base: master
Choose a base branch
from

Conversation

3v1n0
Copy link
Collaborator

@3v1n0 3v1n0 commented Oct 5, 2023

For the way go-pam is structured it made easy to create pam applications, but most of the code can be useful also for implementing modules in go.

As per this:

  • Define ModuleTransaction struct that is similar to Transaction, but with less methods
  • Add a pam-moduler (github.com/msteinert/pam/cmd/pam-moduler) to generate pam-module cgo stubs
  • Add a go (simpler) implementation of pam_debug.so and test it
  • Add an interaction testing module that uses an unix socket to dialog with a loader and that can be instructed to perform any operation on module side
  • Add module methods to set/get module data, and to initiate text-based and binary conversations
  • Test all these cases via integration tests (the only way to do that, since we need a pam-module-side handler).

Keeping this as a draft for now as it requires some refactors that were part of #12, but also it may be adapted a bit if we want to change Transaction errors to be less prone to potential races.

@3v1n0 3v1n0 changed the title Draft: Add PAM module stub generator, modules implmentations and integration tests Add PAM module stub generator, modules implmentations and integration tests Oct 5, 2023
@3v1n0 3v1n0 marked this pull request as draft October 5, 2023 04:07
@3v1n0 3v1n0 force-pushed the pam-moduler branch 7 times, most recently from 65b004b to bceb1f8 Compare October 10, 2023 09:48
@3v1n0
Copy link
Collaborator Author

3v1n0 commented Oct 12, 2023

This is now rebased on #15 instead as it makes few things better to handle.

@3v1n0 3v1n0 force-pushed the pam-moduler branch 2 times, most recently from d3a5880 to 589d109 Compare December 1, 2023 22:41
@3v1n0 3v1n0 requested a review from msteinert December 1, 2023 22:45
3v1n0 added 21 commits February 18, 2024 18:32
…inds

A pam handler can be used both by a module and by an Application, go-pam
is meant to be used in the application side right now, but it can be
easily changed to also create modules.

This is the prerequisite work to support this.
This allows to easily define go-handlers for module operations.

We need to expose few more types externally so that it's possible to
create the module transaction handler and return specific transaction
errors
If returned binaries are nil, we should pass them as nil and not as an
empty bytes array.
A PAM module can be generated using pam-moduler and implemented fully in
go without having to manually deal with the C setup.

Module can be compiled using go generate, so go:generate directives can be
used to make this process automatic, with a single go generate call as shown
in the example.
This will make it easier to avoid exporting unexpected symbols to the
generated PAM libraries.

Also it makes less messy handling C code inside go files.
This function is only needed when using go PAM for creating applications
so it's not something we expect to have exported to library modules.

To prevent this use an `asPamModule` tag to prevent compilation of
application-only features.
In this way all these features not even compiled when creating modules,
avoiding generating unused code.
So we can reduce the generated code and add more unit tests
… works

We mimic what pam_debug.so does by default, by implementing a similar
module fully in go, generated using pam-moduler.

This requires various utilities to generate the module and run the tests
that are in a separate internal modules so that it can be shared between
multiple implementations
In order to properly test the interaction of a module transaction from
the application point of view, we need to perform operation in the
module and ensure that the expected values are returned and handled

In order to do this, without using the PAM apis that we want to test,
use a simple trick:
 - Create an application that works as server using an unix socket
 - Create a module that connects to it
 - Pass the socket to the module via the module service file arguments
 - Add some basic protocol that allows the application to send a request
   and to the module to reply to that.
 - Use reflection and serialization to automatically call module methods
   and return the values to the application where we do the check
We can now finally test this properly both using a mock and through the
interactive module that will do the request for us in various conditions.
Module data is data associated with a module handle that is available
for the whole module loading time so it can be used also during
different operations.

We use cgo handles to preserve the life of the go objects so any value
can be associated with a pam transaction.
Modules have the ability to start PAM conversations, so while the
transaction code can handle them we did not have a way to init them.
Yet.

So add some APIs allowing this, making it easier from the go side to
handle the conversations.

In this commit we only support text-based conversations, but code is
designed with the idea of supporting binary cases too.

Added the integration tests using the module that is now able to both
start conversation and handle them using Go only.
A module can now initiate a binary conversation decoding the native
pointer value as it wants.

Added tests to verify the main cases
Pam conversations per se may also run in parallel, but this implies that
the application supports this.

Since this normally not the case, do not create modules that may invoke
the pam conversations in parallel by default, adding a mutex to protect
such calls.
We have lots of cgo interaction here so better to check things fully.

This also requires manually checking for leaks, so add support for this.
…andler

This requires the allocating function to provide a binary pointer that
will be free'd by the conversation handlers finalizers.

This is for a more advanced usage scenario where the binary conversion
may be handled manually.
We have test utils in other packages that are not shown as tested, while
they definitely are.
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants