<commit_before>/* -*- mode: c++; fill-column: 132; c-basic-offset: 4; indent-tabs-mode: nil -*- */

// =-=-=-=-=-=-=-
// irods includes
#include "rodsDef.hpp"
#include "msParam.hpp"
#include "reGlobalsExtern.hpp"
#include "rcConnect.hpp"
#include "authRequest.hpp"
#include "authResponse.hpp"
#include "authCheck.hpp"
#include "miscServerFunct.hpp"
#include "authPluginRequest.hpp"

// =-=-=-=-=-=-=-
#include "irods_auth_plugin.hpp"
#include "irods_auth_constants.hpp"
#include "irods_native_auth_object.hpp"
#include "irods_stacktrace.hpp"
#include "irods_kvp_string_parser.hpp"

// =-=-=-=-=-=-=-
// stl includes
#include <sstream>
#include <string>
#include <iostream>
#include <termios.h>
#include <unistd.h>

int get64RandomBytes( char *buf );
void setSessionSignatureClientside( char* _sig );
void _rsSetAuthRequestGetChallenge( const char* _c );

static irods::error check_proxy_user_privileges(
    rsComm_t *rsComm,
    int proxyUserPriv ) {
    irods::error result = SUCCESS();

    if ( strcmp( rsComm->proxyUser.userName, rsComm->clientUser.userName ) != 0 ) {

        /* remote privileged user can only do things on behalf of users from
         * the same zone */
        result = ASSERT_ERROR( proxyUserPriv >= LOCAL_PRIV_USER_AUTH ||
                               ( proxyUserPriv >= REMOTE_PRIV_USER_AUTH &&
                                 strcmp( rsComm->proxyUser.rodsZone, rsComm->clientUser.rodsZone ) == 0 ),
                               SYS_PROXYUSER_NO_PRIV,
                               "Proxyuser: \"%s\" with %d no priv to auth clientUser: \"%s\".",
                               rsComm->proxyUser.userName, proxyUserPriv, rsComm->clientUser.userName );
    }

    return result;
}


extern "C" {

    // =-=-=-=-=-=-=-
    // NOTE:: this needs to become a property
    // Set requireServerAuth to 1 to fail authentications from
    // un-authenticated Servers (for example, if the LocalZoneSID
    // is not set)
    const int requireServerAuth = 1;

    // =-=-=-=-=-=-=-
    // NOTE:: this needs to become a property
    // If set, then SIDs are always required, errors will be return if a SID
    // is not locally set for a remote server
    const int requireSIDs = 0;

    // =-=-=-=-=-=-=-
    // given the client connection and context string, set up the
    // native auth object with relevant informaiton: user, zone, etc
    irods::error native_auth_client_start(
        irods::auth_plugin_context& _ctx,
        rcComm_t*                    _comm,
        const char*                  _context ) {
        irods::error result = SUCCESS();
        irods::error ret;

        // =-=-=-=-=-=-=-
        // validate incoming parameters
        ret = _ctx.valid< irods::native_auth_object >();
        if ( ( result = ASSERT_PASS( ret, "Invalid plugin context." ) ).ok() ) {

            if ( ( result = ASSERT_ERROR( _comm, SYS_INVALID_INPUT_PARAM, "Null rcConn_t pointer." ) ).ok() ) {

                // =-=-=-=-=-=-=-
                // get the native auth object
                irods::native_auth_object_ptr ptr = boost::dynamic_pointer_cast<irods::native_auth_object >( _ctx.fco() );

                // =-=-=-=-=-=-=-
                // set the user name from the conn
                ptr->user_name( _comm->proxyUser.userName );

                // =-=-=-=-=-=-=-
                // set the zone name from the conn
                ptr->zone_name( _comm->proxyUser.rodsZone );
            }
        }

        return result;

    } // native_auth_client_start

    // =-=-=-=-=-=-=-
    // establish context - take the auth request results and massage them
    // for the auth response call
    irods::error native_auth_establish_context(
        irods::auth_plugin_context& _ctx ) {
        irods::error result = SUCCESS();
        irods::error ret;

        // =-=-=-=-=-=-=-
        // validate incoming parameters
        ret = _ctx.valid< irods::native_auth_object >();
        if ( ( result = ASSERT_PASS( ret, "Invalid plugin context." ) ).ok() ) {

            // =-=-=-=-=-=-=-
            // build a buffer for the challenge hash
            char md5_buf[ CHALLENGE_LEN + MAX_PASSWORD_LEN + 2 ];
            memset( md5_buf, 0, sizeof( md5_buf ) );

            // =-=-=-=-=-=-=-
            // get the native auth object
            irods::native_auth_object_ptr ptr = boost::dynamic_pointer_cast<irods::native_auth_object >( _ctx.fco() );

            // =-=-=-=-=-=-=-
            // copy the challenge into the md5 buffer
            strncpy( md5_buf, ptr->request_result().c_str(), CHALLENGE_LEN );

            // =-=-=-=-=-=-=-
            // Save a representation of some of the challenge string for use
            // as a session signiture
            setSessionSignatureClientside( md5_buf );

            // =-=-=-=-=-=-=-
            // determine if a password challenge is needed,
            // are we anonymous or not?
            int need_password = 0;
            if ( strncmp( ANONYMOUS_USER, ptr->user_name().c_str(), NAME_LEN ) == 0 ) {

                // =-=-=-=-=-=-=-
                // its an anonymous user - set the flag
                md5_buf[CHALLENGE_LEN + 1] = '\0';
                need_password = 0;

            }
            else {
                // =-=-=-=-=-=-=-
                // determine if a password is already in place
                need_password = <PASSWORD>( md5_buf + CHALLENGE_LEN );
            }

            // =-=-=-=-=-=-=-
            // prompt for a password if necessary
            if ( 0 != need_password ) {
#ifdef WIN32
                HANDLE hStdin = GetStdHandle( STD_INPUT_HANDLE );
                DWORD mode;
                GetConsoleMode( hStdin, &mode );
                DWORD lastMode = mode;
                mode &= ~ENABLE_ECHO_INPUT;
                BOOL error = !SetConsoleMode( hStdin, mode );
                int errsv = -1;
#else
                struct termios tty;
                tcgetattr( STDIN_FILENO, &tty );
                tcflag_t oldflag = tty.c_lflag;
                tty.c_lflag &= ~ECHO;
                int error = tcsetattr( STDIN_FILENO, TCSANOW, &tty );
                int errsv = errno;
#endif
                if ( error ) {
                    printf( "WARNING: Error %d disabling echo mode. Password will be displayed in plaintext.", errsv );
                }
                printf( "Enter your current iRODS password:" );
                std::string password = "";
                getline( cin, password );
                strncpy( md5_buf + CHALLENGE_LEN, password.c_str(), MAX_PASSWORD_LEN );
#ifdef WIN32
                if ( !SetConsoleMode( hStdin, lastMode ) ) {
                    printf( "Error reinstating echo mode." );
                }
#else
                tty.c_lflag = oldflag;
                if ( tcsetattr( STDIN_FILENO, TCSANOW, &tty ) ) {
                    printf( "Error reinstating echo mode." );
                }
#endif
            } // if need_password

            // =-=-=-=-=-=-=-
            // create a md5 hash of the challenge
            MD5_CTX context;<commit_msg>[#1376] initialized memory being passed to syscalls<commit_after>/* -*- mode: c++; fill-column: 132; c-basic-offset: 4; indent-tabs-mode: nil -*- */

// =-=-=-=-=-=-=-
// irods includes
#include "rodsDef.hpp"
#include "msParam.hpp"
#include "reGlobalsExtern.hpp"
#include "rcConnect.hpp"
#include "authRequest.hpp"
#include "authResponse.hpp"
#include "authCheck.hpp"
#include "miscServerFunct.hpp"
#include "authPluginRequest.hpp"

// =-=-=-=-=-=-=-
#include "irods_auth_plugin.hpp"
#include "irods_auth_constants.hpp"
#include "irods_native_auth_object.hpp"
#include "irods_stacktrace.hpp"
#include "irods_kvp_string_parser.hpp"

// =-=-=-=-=-=-=-
// stl includes
#include <sstream>
#include <string>
#include <iostream>
#include <termios.h>
#include <unistd.h>

int get64RandomBytes( char *buf );
void setSessionSignatureClientside( char* _sig );
void _rsSetAuthRequestGetChallenge( const char* _c );

static irods::error check_proxy_user_privileges(
    rsComm_t *rsComm,
    int proxyUserPriv ) {
    irods::error result = SUCCESS();

    if ( strcmp( rsComm->proxyUser.userName, rsComm->clientUser.userName ) != 0 ) {

        /* remote privileged user can only do things on behalf of users from
         * the same zone */
        result = ASSERT_ERROR( proxyUserPriv >= LOCAL_PRIV_USER_AUTH ||
                               ( proxyUserPriv >= REMOTE_PRIV_USER_AUTH &&
                                 strcmp( rsComm->proxyUser.rodsZone, rsComm->clientUser.rodsZone ) == 0 ),
                               SYS_PROXYUSER_NO_PRIV,
                               "Proxyuser: \"%s\" with %d no priv to auth clientUser: \"%s\".",
                               rsComm->proxyUser.userName, proxyUserPriv, rsComm->clientUser.userName );
    }

    return result;
}


extern "C" {

    // =-=-=-=-=-=-=-
    // NOTE:: this needs to become a property
    // Set requireServerAuth to 1 to fail authentications from
    // un-authenticated Servers (for example, if the LocalZoneSID
    // is not set)
    const int requireServerAuth = 1;

    // =-=-=-=-=-=-=-
    // NOTE:: this needs to become a property
    // If set, then SIDs are always required, errors will be return if a SID
    // is not locally set for a remote server
    const int requireSIDs = 0;

    // =-=-=-=-=-=-=-
    // given the client connection and context string, set up the
    // native auth object with relevant informaiton: user, zone, etc
    irods::error native_auth_client_start(
        irods::auth_plugin_context& _ctx,
        rcComm_t*                    _comm,
        const char*                  _context ) {
        irods::error result = SUCCESS();
        irods::error ret;

        // =-=-=-=-=-=-=-
        // validate incoming parameters
        ret = _ctx.valid< irods::native_auth_object >();
        if ( ( result = ASSERT_PASS( ret, "Invalid plugin context." ) ).ok() ) {

            if ( ( result = ASSERT_ERROR( _comm, SYS_INVALID_INPUT_PARAM, "Null rcConn_t pointer." ) ).ok() ) {

                // =-=-=-=-=-=-=-
                // get the native auth object
                irods::native_auth_object_ptr ptr = boost::dynamic_pointer_cast<irods::native_auth_object >( _ctx.fco() );

                // =-=-=-=-=-=-=-
                // set the user name from the conn
                ptr->user_name( _comm->proxyUser.userName );

                // =-=-=-=-=-=-=-
                // set the zone name from the conn
                ptr->zone_name( _comm->proxyUser.rodsZone );
            }
        }

        return result;

    } // native_auth_client_start

    // =-=-=-=-=-=-=-
    // establish context - take the auth request results and massage them
    // for the auth response call
    irods::error native_auth_establish_context(
        irods::auth_plugin_context& _ctx ) {
        irods::error result = SUCCESS();
        irods::error ret;

        // =-=-=-=-=-=-=-
        // validate incoming parameters
        ret = _ctx.valid< irods::native_auth_object >();
        if ( ( result = ASSERT_PASS( ret, "Invalid plugin context." ) ).ok() ) {

            // =-=-=-=-=-=-=-
            // build a buffer for the challenge hash
            char md5_buf[ CHALLENGE_LEN + MAX_PASSWORD_LEN + 2 ];
            memset( md5_buf, 0, sizeof( md5_buf ) );

            // =-=-=-=-=-=-=-
            // get the native auth object
            irods::native_auth_object_ptr ptr = boost::dynamic_pointer_cast<irods::native_auth_object >( _ctx.fco() );

            // =-=-=-=-=-=-=-
            // copy the challenge into the md5 buffer
            strncpy( md5_buf, ptr->request_result().c_str(), CHALLENGE_LEN );

            // =-=-=-=-=-=-=-
            // Save a representation of some of the challenge string for use
            // as a session signiture
            setSessionSignatureClientside( md5_buf );

            // =-=-=-=-=-=-=-
            // determine if a password challenge is needed,
            // are we anonymous or not?
            int need_password = 0;
            if ( strncmp( ANONYMOUS_USER, ptr->user_name().c_str(), NAME_LEN ) == 0 ) {

                // =-=-=-=-=-=-=-
                // its an anonymous user - set the flag
                md5_buf[CHALLENGE_LEN + 1] = '\0';
                need_password = 0;

            }
            else {
                // =-=-=-=-=-=-=-
                // determine if a password is already in place
                need_password = obfGetPw( md5_buf + CHALLENGE_LEN );
            }

            // =-=-=-=-=-=-=-
            // prompt for a password if necessary
            if ( 0 != need_password ) {
#ifdef WIN32
                HANDLE hStdin = GetStdHandle( STD_INPUT_HANDLE );
                DWORD mode;
                GetConsoleMode( hStdin, &mode );
                DWORD lastMode = mode;
                mode &= ~ENABLE_ECHO_INPUT;
                BOOL error = !SetConsoleMode( hStdin, mode );
                int errsv = -1;
#else
                struct termios tty;
                memset( &tty, 0, sizeof( tty ) );
                tcgetattr( STDIN_FILENO, &tty );
                tcflag_t oldflag = tty.c_lflag;
                tty.c_lflag &= ~ECHO;
                int error = tcsetattr( STDIN_FILENO, TCSANOW, &tty );
                int errsv = errno;
#endif
                if ( error ) {
                    printf( "WARNING: Error %d disabling echo mode. Password will be displayed in plaintext.", errsv );
                }
                printf( "Enter your current iRODS password:" );
                std::string password = "";
                getline( cin, password );
                strncpy( md5_buf + CHALLENGE_LEN, password.c_str(), MAX_PASSWORD_LEN );
#ifdef WIN32
                if ( !SetConsoleMode( hStdin, lastMode ) ) {
                    printf( "Error reinstating echo mode." );
                }
#else
                tty.c_lflag = oldflag;
                if ( tcsetattr( STDIN_FILENO, TCSANOW, &tty ) ) {
                    printf( "Error reinstating echo mode." );
                }
#endif
            } // if need_password

            // =-=-=-=-=-=-=-
            // create a md5 hash of the challenge
            MD5_CTX context;
{'fraction_non_alphanumeric': 0.13716254218222723, 'fraction_numerical': 0.005272778402699662, 'mean_word_length': 1.6789077212806027, 'pattern_counts': {'":': 0, '<': 22, '<?xml version=': 0, '>': 50, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 4, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '2866595', 'n_tokens_mistral': 4383, 'n_tokens_neox': 4013, 'n_words': 1072}