Lemonldap-NG-Portal

 view release on metacpan or  search on metacpan

MANIFEST  view on Meta::CPAN

site/templates/bootstrap/customLoginFooter.tpl
site/templates/bootstrap/customLoginHeader.tpl
site/templates/bootstrap/decryptvalue.tpl
site/templates/bootstrap/error.tpl
site/templates/bootstrap/errormsg.tpl
site/templates/bootstrap/ext2fcheck.tpl
site/templates/bootstrap/finduser.tpl
site/templates/bootstrap/footer.tpl
site/templates/bootstrap/generic2fregister.tpl
site/templates/bootstrap/globallogout.tpl
site/templates/bootstrap/gpgform.tpl
site/templates/bootstrap/header.tpl
site/templates/bootstrap/idpchoice.tpl
site/templates/bootstrap/impersonation.tpl
site/templates/bootstrap/info.tpl
site/templates/bootstrap/ldapPpGrace.tpl
site/templates/bootstrap/login.tpl
site/templates/bootstrap/mail.tpl
site/templates/bootstrap/menu.tpl
site/templates/bootstrap/noHistory.tpl
site/templates/bootstrap/notification.tpl

MANIFEST  view on Meta::CPAN

t/crowdsec-scenarii/http-cve-test/patterns.re
t/crowdsec-scenarii/http-sensitive-files/.scenario
t/crowdsec-scenarii/http-sensitive-files/patterns.txt
t/crowdsec-scenarii/legacy.url.re
t/crowdsec-scenarii/urlskip/allowed.txt
t/Custom.pm
t/CustomMenu.pm
t/DbiCustomHash.pm
t/geoip/GeoIP2-City-Test.mmdb
t/geoip/GeoIP2-Country-Test.mmdb
t/gpghome/key.asc
t/gpghome/openpgp-revocs.d/9482CEFB055809CBAFE6D71AAB2D5542891D1677.rev
t/gpghome/private-keys-v1.d/A076B0E7DB141A919271EE8B581CDFA8DA42F333.key
t/gpghome/private-keys-v1.d/B7219440BCCD85200121CFB89F94C8D98C0397B3.key
t/gpghome/pubring.kbx
t/gpghome/tofu.db
t/gpghome/trustdb.gpg
t/HistoryPlugin.pm
t/lib/Apache/Session/Timeout.pm
t/lib/Lemonldap/NG/Common/Conf/Backends/Timeout.pm
t/lib/Lemonldap/NG/Handler/Test.pm
t/lib/Lemonldap/NG/Portal/Auth/LDAPPolicy.pm
t/lib/Lemonldap/NG/Portal/Custom.pm
t/lmConf-1.json
t/LogoutFail.pm
t/main-idps-renater-metadata.xml
t/main-sps-renater-metadata.xml

lib/Lemonldap/NG/Portal/Auth/GPG.pm  view on Meta::CPAN

has tmp => (
    is      => 'rw',
    default => sub {
        tempdir( CLEANUP => 1 );
    },
);

sub init {
    my $self = shift;

    $self->db( $self->conf->{gpgDb} );
    unless ( $self->db ) {
        $self->error("gpgDb not set");
        return 0;
    }
    unless ( -r $self->db ) {
        $self->error( "Unable to read " . $self->db );
        return 0;
    }

    return $self->SUPER::init();
}

sub extractFormInfo {
    my ( $self, $req ) = @_;

    unless ( $self->ottRule->( $req, {} ) ) {
        $self->error("OTT isn't set, unable to use GPG");
    }

    # Keep token data for later use
    my ( $token, $gpgToken );
    if ( $token = $req->param('token') ) {
        $gpgToken = $self->ott->getToken($token);
        $req->data->{tokenVerified} = 1 if ($gpgToken);
    }
    my $res = $self->SUPER::extractFormInfo($req);
    return $res if ($res);
    my $signed = $req->data->{password};
    unless ( $signed =~ /SIGNATURE/s ) {
        $self->userLogger->error("Bad signature content");
        $self->userLogger->debug($signed);
        $self->setSecurity($req);
        return PE_BADCREDENTIALS;
    }
    unless ( $signed =~ /\b\Q$token\E\b/ ) {
        $self->userLogger->error("User replayed a bad token in GPG !");
        $self->setSecurity($req);
        return PE_BADCREDENTIALS;
    }
    my ( $out, $err );
    $self->logger->debug(
"Launching:\ngpgv --homedir /dev/null --keyring $self->{db} <<EOF\n$signed\nEOF"
    );
    my ( $lang, $language ) = ( $ENV{LANG}, $ENV{LANGUAGE} );
    $ENV{LANG} = $ENV{LANGUAGE} = 'C';
    IPC::Run::run( [ 'gpgv', '--homedir', '/dev/null', '--keyring', $self->db ],
        \$signed, \$out, \$err, IPC::Run::timeout(10) );
    if ( $? >> 8 != 0 ) {
        $self->userLogger->error("GPG verification fails:\n$out\n# # #\n$err");
        $self->setSecurity($req);
        return PE_BADCREDENTIALS;
    }
    $self->setSecurity($req);
    $self->userLogger->notice("Good GPG signature");
    $self->userLogger->debug("GPG out:\n$out\n$err");
    my $key;
    if ( $err =~ /using .*? key (.*)$/m ) {
        $key = $1;
        chomp $key;
    }
    else {
        $self->logger->error("Unable to parse gpgv result:\n$err");
        return PE_ERROR;
    }
    $self->logger->debug("GPG full sign key: $key");
    my $in;
    IPC::Run::run( [
            'gpg',     '--homedir',  $self->tmp, '--keyring',
            $self->db, '--list-key', $key
        ],
        \$in,
        \$out,
        \$err,
        IPC::Run::timeout(10)
    );
    ( $ENV{LANG}, $ENV{LANGUAGE} ) = ( $lang, $language );
    if ( $? >> 8 != 0 ) {
        $self->logger->error("gpg --list-key return an error:\n$err");
        return PE_ERROR;
    }

    if ( $out =~ /pub [^\n]*\r?\n +([^\n]+)\n/ ) {
        $key = $1;
        chomp $key;
    }
    else {
        $self->logger->error(
            "Unable to parse gpg --list-key result:\n$out\n$err\n");
        return PE_ERROR;
    }
    $self->logger->debug("GPG full master key: $key");

    # Keep only gpgKeyLength characters
    my $length = $self->conf->{gpgKeyLength} || 8;
    $length = 8 if ( $length < 8 );
    $key =~ s/.*?(.{8,$length})$/$1/;
    $self->logger->info("User key: $key");

    my @identities = ( $out =~ /uid\s+(.*)$/gm );
    my $mail       = $req->param('user');
    foreach (@identities) {
        if (/^(.*)\s+<\Q$mail\E>/) {
            $req->data->{gpgFullName} = $1;
            $req->data->{gpgMail}     = $mail;
            $req->user($mail);
            $self->userLogger->notice("GPG user $mail authenticated");
            return PE_OK;
        }
    }
    $self->userLogger->warn("Given mail does not match with gpg key");
    $self->setSecurity($req);
    return PE_BADCREDENTIALS;
}

sub authenticate {
    return PE_OK;
}

sub setAuthSessionInfo {
    my ( $self, $req ) = @_;
    $req->sessionInfo->{gpgMail}             = $req->data->{gpgMail};
    $req->sessionInfo->{authenticationLevel} = $self->conf->{gpgAuthnLevel};
    return PE_OK;
}

sub authLogout {
    return PE_OK;
}

sub getDisplayType {
    return "gpgform";
}

1;

lib/Lemonldap/NG/Portal/Auth/GitHub.pm  view on Meta::CPAN

        $_[0]->conf->{githubPublicKeysEndpoint}
          || 'https://api.github.com/user/keys';
    }
);

has githubGPGKeysEndpoint => (
    is      => 'ro',
    lazy    => 1,
    default => sub {
        $_[0]->conf->{githubGPGKeysEndpoint}
          || 'https://api.github.com/user/gpg_keys';
    }
);

sub init {
    my ($self) = @_;

    my $ret = 1;
    foreach my $arg (qw(githubClientID githubClientSecret)) {
        unless ( $self->conf->{$arg} ) {
            $ret = 0;

lib/Lemonldap/NG/Portal/Auth/GitHub.pm  view on Meta::CPAN

            if ($@) {
                $self->logger->error(
                    "Unable to decode JSON $public_keys_content");
                return PE_ERROR;
            }

            $req->data->{githubData}->{"public_keys"} = $json_hash;
        }

        # Fetch GPG keys
        if ( $self->conf->{githubScope} =~ /gpg_key/ ) {
            $self->logger->debug("Scope gpg_key requested, fetch SSH keys");

            my $gpg_keys_response =
              $self->ua->get( $self->githubGPGKeysEndpoint,
                "Authorization" => "token $access_token" );

            if ( $gpg_keys_response->is_error ) {
                $self->logger->error( "Bad authorization response: "
                      . $gpg_keys_response->message );
                $self->logger->debug( $gpg_keys_response->content );
                return PE_ERROR;
            }

            my $gpg_keys_content = $gpg_keys_response->decoded_content;

            $self->logger->debug(
                "Response from GitHub GPG Keys API: $gpg_keys_content");

            eval {
                $json_hash =
                  from_json( $gpg_keys_content, { allow_nonref => 1 } );
            };
            if ($@) {
                $self->logger->error("Unable to decode JSON $gpg_keys_content");
                return PE_ERROR;
            }

            $req->data->{githubData}->{"gpg_keys"} = $json_hash;
        }

        # Extract state
        if ($state) {
            my $stateSession = $self->p->getApacheSession( $state, 1 );

            $req->urldc( $stateSession->data->{urldc} );
            $req->{checkLogins} = $stateSession->data->{checkLogins};

            $stateSession->remove;

lib/Lemonldap/NG/Portal/Main/Display.pm  view on Meta::CPAN

                    DISPLAY_FORM => $displayType =~ /\bstandardform\b/ ? 1
                    : 0,
                    DISPLAY_OPENID_FORM => $displayType =~ /\bopenidform\b/ ? 1
                    : 0,
                    DISPLAY_YUBIKEY_FORM => $displayType =~ /\byubikeyform\b/
                    ? 1
                    : 0,
                    DISPLAY_SSL_FORM      => $displayType =~ /sslform/ ? 1 : 0,
                    DISPLAY_WEBAUTHN_FORM => $displayType =~ /webauthnform/ ? 1
                    : 0,
                    DISPLAY_GPG_FORM  => $displayType =~ /gpgform/ ? 1 : 0,
                    DISPLAY_LOGO_FORM => $displayType eq "logo"    ? 1 : 0,
                    DISPLAY_FINDUSER  => scalar @$fields,
                    module            => $displayType eq "logo"
                    ? $self->getModule( $req, 'auth' )
                    : "",
                    AUTH_LOOP  => [],
                    PORTAL_URL => ( $displayType eq "logo" ? $req->portal : 0 ),
                    MSG        => $req->info(),
                    MANDATORY  => $mandatory,
                    FIELDS     => $fields,

site/templates/bootstrap/gpgform.tpl  view on Meta::CPAN

<span trspan="Please sign the following text with your GPG key"></span>
<pre>echo -n "<TMPL_VAR NAME="TOKEN">"| gpg --clear-sign</pre>
<div class="form">
  <div class="input-group mb-3">
    <div class="input-group-prepend">
      <span class="input-group-text"><label for="userfield" class="mb-0"><i class="fa fa-user"></i></label></span>
    </div>
    <input id="userfield" name="user" type="text" class="form-control" value="<TMPL_VAR NAME="LOGIN" ESCAPE=HTML>" trplaceholder="mail" required aria-required="true" />
  </div>

  <div class="input-group mb-3">
    <div class="input-group-prepend">

site/templates/bootstrap/login.tpl  view on Meta::CPAN


            <TMPL_IF NAME="webauthnform">
              <TMPL_INCLUDE NAME="webauthnform.tpl">

              <!-- Remember my authentication choice for this module -->
              <TMPL_IF NAME="REMEMBERAUTHCHOICE">
                <input type="hidden" id="rememberauthchoice" name="rememberauthchoice" value="<TMPL_IF NAME="REMEMBERAUTHCHOICEDEFAULTCHECKED">true</TMPL_IF>" />
              </TMPL_IF>
            </TMPL_IF>

            <TMPL_IF NAME="gpgform">
              <TMPL_INCLUDE NAME="gpgform.tpl">
            </TMPL_IF>

            <TMPL_IF NAME="logo">

              <div class="form">

                <TMPL_IF NAME="logoFile">
                  <img src="<TMPL_VAR NAME="STATIC_PREFIX">common/modules/<TMPL_VAR NAME="logoFile">" alt="<TMPL_VAR NAME="module">" class="img-thumbnail mb-3" />
                </TMPL_IF>

site/templates/bootstrap/login.tpl  view on Meta::CPAN

  <TMPL_IF NAME="module">
    <form id="lform" action="#" method="post" class="login <TMPL_VAR NAME="module">" role="form">
  <TMPL_ELSE>
    <form id="lform" action="#" method="post" class="login" role="form">
  </TMPL_IF>
    <!-- Hidden fields -->
    <TMPL_VAR NAME="HIDDEN_INPUTS">
    <input type="hidden" name="url" value="<TMPL_VAR NAME="AUTH_URL">" />
    <input type="hidden" name="timezone" />
    <input type="hidden" name="skin" value="<TMPL_VAR NAME="SKIN">" />
    <TMPL_INCLUDE NAME="gpgform.tpl">
    </form>
  </div>
  </TMPL_IF>

  <TMPL_IF NAME="DISPLAY_YUBIKEY_FORM">
  <div class="card">
  <TMPL_IF NAME="module">
    <form id="lform" action="#" method="post" class="login <TMPL_VAR NAME="module">" role="form">
  <TMPL_ELSE>
    <form id="lform" action="#" method="post" class="login" role="form">

t/28-AuthChoice-and-password.t  view on Meta::CPAN

                authentication           => 'Choice',
                userDB                   => 'Same',
                passwordDB               => 'Choice',
                portalRequireOldPassword => 1,

                authChoiceParam   => 'test',
                authChoiceModules => {
                    ldap  => 'LDAP;LDAP;LDAP',
                    sql   => 'DBI;DBI;DBI',
                    slave => 'Slave;LDAP;LDAP',
                    gpg   => 'GPG;Demo;Null'
                },

                dbiAuthChain        => "dbi:SQLite:dbname=$userdb",
                dbiAuthUser         => '',
                dbiAuthPassword     => '',
                dbiAuthTable        => 'users',
                dbiAuthLoginCol     => 'user',
                dbiAuthPasswordCol  => 'password',
                dbiAuthPasswordHash => '',

t/29-AuthGPG.t  view on Meta::CPAN

use strict;

require 't/test-lib.pm';

my $mainTests = 5;

SKIP: {
    skip "Manual skip of GPG test", $mainTests if ( $ENV{LLNG_SKIP_GPG_TEST} );
    eval "use IPC::Run 0.93 'run',";
    skip "Missing dependency", $mainTests if ($@);
    my $gpg = eval { `which gpg` };
    skip "Missing gpg", $mainTests if $@ or not $gpg;
    chomp $gpg;
    my $res;
    use_ok('Lemonldap::NG::Common::FormEncode');

    my $client = LLNG::Manager::Test->new( {
            ini => {
                logLevel       => 'error',
                authentication => 'GPG',
                userDB         => 'Null',
                gpgDb          => 't/gpghome/key.asc',
                requireToken   => 1,
            }
        }
    );
    ok( $res = $client->_get( '/', accept => 'text/html' ), 'First access' );
    my ( $host, $url, $query ) =
      expectForm( $res, '#', undef, 'user', 'token' );
    $query =~ s/user=/user=llng\@lemonldap-ng.org/;
    $query =~ /token=([^&]+)/;
    my $token = $1 or fail('No token');
    ok( $res->[2]->[0] =~ /echo -n "$token"/m, "Found instructions" );
    my ( $out, $err );
    run( [ 'gpg', '--clear-sign', '--homedir', 't/gpghome' ],
        \$token, \$out, \$err, IPC::Run::timeout(10) );

    if ( $? == 0 ) {
        pass 'Succeed to sign';
    }
    else {
        run( [ 'gpg', '--clearsign', '--homedir', 't/gpghome' ],
            \$token, \$out, \$err, IPC::Run::timeout(10) );
        unless ( $? == 0 ) {
            skip "Local GPG signature fails, aborting", 2;
        }
        pass("Succeed to sign");
    }
    $query .= '&' . build_urlencoded( password => $out );
    ok(
        $res = $client->_post(
            '/',

t/gpghome/openpgp-revocs.d/9482CEFB055809CBAFE6D71AAB2D5542891D1677.rev  view on Meta::CPAN

uid          LL::NG <llng@lemonldap-ng.org>

A revocation certificate is a kind of "kill switch" to publicly
declare that a key shall not anymore be used.  It is not possible
to retract such a revocation certificate once it has been published.

Use it to revoke this key in case of a compromise or loss of
the secret key.  However, if the secret key is still accessible,
it is better to generate a new revocation certificate and give
a reason for the revocation.  For details see the description of
of the gpg command "--generate-revocation" in the GnuPG manual.

To avoid an accidental use of this file, a colon has been inserted
before the 5 dashes below.  Remove this colon with a text editor
before importing and publishing this revocation certificate.

:-----BEGIN PGP PUBLIC KEY BLOCK-----
Comment: This is a revocation certificate

iQG2BCABCgAgFiEElILO+wVYCcuv5tcaqy1VQokdFncFAlwG+U8CHQAACgkQqy1V
QokdFndF6Qv+Pk5xMIXm43dXghosAJZQTI1VvCDDmfhvSedoU+bweANKvnnugLnA



( run in 2.266 seconds using v1.01-cache-2.11-cpan-df04353d9ac )