Firefox-Marionette

 view release on metacpan or  search on metacpan

ssh-auth-cmd-marionette  view on Meta::CPAN

                chomp $EVAL_ERROR;
                Sys::Syslog::openlog( $ident, 'cons', $parameters{facility} );
                Sys::Syslog::syslog( Sys::Syslog::LOG_ERR(), $EVAL_ERROR );
                Sys::Syslog::closelog();
            };
            exit 1;
        }
        else {
            die "Failed to fork:$EXTENDED_OS_ERROR\n";
        }
    }
    return $regex;
}

eval {
    Getopt::Long::GetOptions(
        \%options,                          'help',
        'version',                          'facility:s',
        'allow-binary:s@',                  'force-binary:s',
        'regex-allow-binary-directories:s', 'regex-allow-binary-paths:s',
        'regex-allow-binary:s',             'scp-only',
    );
    if ( $options{help} ) {
        require Pod::Simple::Text;
        my $parser = Pod::Simple::Text->new();
        $parser->parse_from_file($PROGRAM_NAME);
        exit 0;
    }
    elsif ( $options{version} ) {
        print "$VERSION\n"
          or die "Failed to print to STDOUT:$EXTENDED_OS_ERROR\n";
        exit 0;
    }
    my $tmp_directory_regex = _tmp_directory_regex(%options);
    my $tmp_directory       = $ENV{TMPDIR} || '/tmp';
    $tmp_directory =~ s/\/$//smx;    # remove trailing / for darwin
    my $root_dir_regex;
    my $quoted_tmp_directory = quotemeta $tmp_directory;
    if ( $tmp_directory =~
s/^(${tmp_directory_regex}\/firefox_marionette_remote\w+)(?:\/tmp)?$/$1/smx
      )
    {
        $quoted_tmp_directory = quotemeta $tmp_directory;
        $root_dir_regex       = qr/$quoted_tmp_directory/smx;
    }
    else {
        $quoted_tmp_directory = quotemeta $tmp_directory;
        $root_dir_regex =
          qr/${$tmp_directory_regex}\/firefox_marionette_remote\w+/smx;
    }
    %options = _validate_parameters(%options);
    my ( $allowed_binary_directories_regex,
        $allowed_binary_paths_regex, $allowed_binary_regex )
      = _filesystem_regexes(%options);
    my $sub_directory_regex = qr/(?:profile|downloads|tmp|addons|certs)/smx;
    my $profile_names       = q[(?:] . (
        join q[|],
        map { quotemeta } (
            qw(
              bookmarks.html
              prefs.js
              mimeTypes.rdf
              search.json.mozlz4
            )
        )
    ) . q[)];
    my $profile_file_regex    = qr/profile\/$profile_names/smx;
    my $file_regex            = qr/[+\w\-()]{1,255}(?:[.][+\w\-()]{1,255})*/smx;
    my $downloads_regex       = qr/downloads\/$file_regex/smx;
    my $addons_regex          = qr/(?:addons|profile)\/$file_regex/smx;
    my $ca_name_regex         = qr/Firefox::Marionette[ ]Root[ ]CA/smx;
    my $version_updates_regex = q[(?:]
      . (
        join q[|], qr/active\-update[.]xml/smx, qr/application[.]ini/smx,
        qr/updates\/\d+\/update[.]status/smx
      ) . q[)];
    my $xvfb_regex =
      qr/xvfb\-run[ ]\-a[ ]\-s[ ]"-screen[ ]0[ ]\d+x\d+x\d+"[ ]/smx;
    my $certutil_arguments_regex = join q[],
      qr/[ ]\-A/smx,
      qr/[ ]\-d[ ](?:dbm|sql):$root_dir_regex\/profile/smx,
      qr/[ ]\-i[ ]$root_dir_regex\/certs\/root_ca_\d{1,10}[.]cer/smx,
      qr/[ ]\-n[ ]$ca_name_regex[ ]\d{1,10}[ ]\-t[ ]TC,,/smx;
    my $firefox_arguments_regex = join q[],
      qr/[ ]\-marionette/smx,
      qr/(?:[ ]\-remote\-allow\-system\-access)?/smx,
      qr/(?:[ ]\-width[ ]\d{1,8})?/smx,
      qr/(?:[ ]\-height[ ]\d{1,8})?/smx,
      qr/(?:[ ]\-\-jsconsole)?/smx,
      qr/(?:[ ]\-MOZ_LOG=[[:alnum:],:]+)?/smx,
      qr/(?:[ ]-safe\-mode)?/smx,
      qr/(?:[ ]\-headless)?/smx,
      qr/[ ](?:\-profile[ ]$root_dir_regex\/profile|\-P[ ][[:alnum:]]+)/smx,
      qr/(?:[ ]\-\-no\-remote)?/smx,
      qr/(?:[ ]\-\-new\-instance)?/smx,
      qr/(?:[ ]\-\-devtools)?/smx,
      qr/(?:[ ]\-\-kiosk)?/smx;
    my $prefs_grep_patterns_regex = join q[],
      qr/\-e[ ]marionette[ ]/smx,
      qr/\-e[ ]security[ ]/smx;
    my @darwin_regexes;

    if ( $OSNAME eq 'darwin' ) {
        my $plist_prefix_regex =
          _get_plist_prefix_regex( @{ $options{'allow-binary'} } );
        @darwin_regexes = (
            qr/ls[ ]-1[ ]"$allowed_binary_regex"/smx,
qr/plutil[ ]-convert[ ]json[ ]-o[ ]-[ ]"(?:$plist_prefix_regex)\/Info[.]plist"/smx,
        );
    }

    my @sftp_server_regexs;
    if ( !$options{'scp-only'} ) {
        @sftp_server_regexs = (
            map { qr/${_}[ ]?/smx }
              ( # Adding a space for new sftp-server in Fedora 40 (openssh-9.6p1)
                quotemeta '/usr/libexec/openssh/sftp-server',   # Redhat, Debian
                quotemeta '/usr/libexec/sftp-server',           # FreeBSD
              )
        );
    }
    my $darwin_profile_regex =
      qr/Library\/Application\\[ ]Support\/Firefox\/Profiles/smx;
    my $named_profile_regex =
      qr/(?:[.]mozilla\/firefox|$darwin_profile_regex)/smx;
    my $profile_path_regex =
      qr/(?:$root_dir_regex\/profile|$named_profile_regex\/[[:alnum:].\-]+)/smx;
    my $scp_parameters_regex =
      qr/(?:[ ]\-v)?[ ]\-p[ ]\-[tf][ ](?:-P[ ]\d{2}[ ])?(?:\-v[ ])?/smx;
    my $quoted_linux_profiles_ini = quotemeta q[.mozilla/firefox];
    my $quoted_darwin_profiles_ini =
      quotemeta q[Library/Application Support/Firefox];
    my $profiles_ini_regex =
qr/(?:$quoted_linux_profiles_ini|$quoted_darwin_profiles_ini)\/profiles[.]ini/smx;
    my $allowed_commands_regex = join q[|],
      qr/"$allowed_binary_regex"[ ]\-\-version/smx,
      @darwin_regexes,
      @sftp_server_regexs,
      qr/uname[ ][|][|][ ]ver/smx,
      qr/echo[ ]"TMPDIR=\\"\$TMPDIR\\""/smx,
      qr/echo[ ]"DISPLAY=\\"\$DISPLAY\\""/smx,
      qr/echo[ ]"TMP=\\"\$TMP\\""/smx,
      qr/mkdir[ ](?:\-m[ ]700[ ])?$root_dir_regex/smx,
      qr/mkdir[ ](?:\-m[ ]700[ ])?$root_dir_regex\/$sub_directory_regex/smx,
      qr/scp$scp_parameters_regex"?$root_dir_regex\/$profile_file_regex"?/smx,
      qr/scp(?:[ ]\-v)?[ ]\-p[ ]\-t[ ]"?$root_dir_regex\/$addons_regex"?/smx,
      qr/scp[ ]\-p[ ]\-t[ ]$root_dir_regex\/certs\/root_ca_\d{1,10}[.]cer/smx,
qr/scp[ ]\-p[ ]\-[fT][ ](?:\-P[ ])?$allowed_binary_directories_regex\/$version_updates_regex/smx,
qr/scp(?:[ ]\-v)?[ ]\-p[ ]\-[tf][ ]"?$root_dir_regex\/$downloads_regex"?/smx,
      qr/scp[ ]\-p[ ]\-[tf][ ]"?$profiles_ini_regex"?/smx,
      qr/kill[ ]\-0[ ]\d{1,8}/smx,
      qr/which[ ]$allowed_binary_regex/smx,
      qr/readlink[ ]\-f[ ]$allowed_binary_paths_regex/smx,
qr/rm[ ]\-Rf[ ]$root_dir_regex(?:[ ]$quoted_tmp_directory\/Temp\-[\d\-a-f]{1,255})*/smx,
qr/ls[ ]-1[ ]"$allowed_binary_directories_regex(?:\/updates(?:\/\d+)?)?"/smx,
      qr/ls[ ]-1[ ]"$root_dir_regex\/downloads"/smx,
      qr/certutil$certutil_arguments_regex/smx,
      qr/(?:$xvfb_regex)?"$allowed_binary_regex"$firefox_arguments_regex/smx,
      qr/grep[ ]$prefs_grep_patterns_regex$profile_path_regex\/prefs[.]js/smx;

    my $user_name = getpwuid $EFFECTIVE_USER_ID;
    if ( $ENV{SSH_ORIGINAL_COMMAND} =~ m/^($allowed_commands_regex)$/smx ) {
        my ($command_and_arguments) = ($1);
        if ( $options{'force-binary'} ) {
            $command_and_arguments =~
              s/^"$allowed_binary_regex"/"$options{'force-binary'}"/smx;
        }
        Sys::Syslog::openlog( $ident, 'cons', $options{facility} );
        Sys::Syslog::syslog( Sys::Syslog::LOG_INFO(),
            "Executing '$command_and_arguments' as '$user_name' from "
              . _origin() );
        Sys::Syslog::closelog();
        exec $command_and_arguments
          or die "Failed to '$command_and_arguments':$EXTENDED_OS_ERROR\n";
    }
    else {
        my $origin = _origin();
        Sys::Syslog::openlog( $ident, 'cons', $options{facility} );
        Sys::Syslog::syslog( Sys::Syslog::LOG_WARNING(),
                'Unrecognisable command "'
              . $ENV{SSH_ORIGINAL_COMMAND}
              . "\" as '$user_name' from $origin with a quoted TMPDIR of \"$quoted_tmp_directory\" and a root directory regex of \"$root_dir_regex\""
        );
        Sys::Syslog::closelog();
    }
    1;
} or do {
    my $eval_error = $EVAL_ERROR;
    chomp $eval_error;
    Sys::Syslog::openlog( $ident, 'cons', $options{facility} );
    Sys::Syslog::syslog( Sys::Syslog::LOG_ERR(), $eval_error );
    Sys::Syslog::closelog();
};
exit 1;

sub _validate_parameters {
    my (%parameters) = @_;
    my $facility = $parameters{facility};
    eval { $parameters{facility} = Sys::Syslog->$facility(); } or do {
        my $original = $parameters{facility};
        $parameters{facility} = Sys::Syslog::LOG_LOCAL0();
        Sys::Syslog::openlog( $ident, 'cons', $parameters{facility} );
        Sys::Syslog::syslog( Sys::Syslog::LOG_WARNING(),
            "Failed to parse --facility argument of '$original':$EVAL_ERROR" );
        Sys::Syslog::closelog();
    };
    if ( !defined $ENV{SSH_ORIGINAL_COMMAND} ) {
        die
"$PROGRAM_NAME requires the SSH_ORIGINAL_COMMAND environment variable to be defined\n";
    }
    if ( !defined $parameters{'allow-binary'} ) {
        $parameters{'allow-binary'} = ['firefox'];
        if ( $OSNAME eq 'darwin' ) {
            push @{ $parameters{'allow-binary'} },
              '/Applications/Firefox.app/Contents/MacOS/firefox',
'/Applications/Firefox Developer Edition.app/Contents/MacOS/firefox',
              '/Applications/Firefox Nightly.app/Contents/MacOS/firefox',
              '/Applications/Waterfox Current.app/Contents/MacOS/waterfox';
        }



( run in 2.775 seconds using v1.01-cache-2.11-cpan-5a3173703d6 )