/// =-=-=-=-=-=-=-
/// @brief function which manages the TLS and Auth negotiations with the client
    error client_server_negotiation_for_server(
        irods::network_object_ptr _ptr,
        std::string&               _result ) {
        // =-=-=-=-=-=-=-
        // manufacture an rei for the applyRule
        ruleExecInfo_t rei;
        memset( ( char* )&rei, 0, sizeof( ruleExecInfo_t ) );

        // =-=-=-=-=-=-=-
        // if it is, then call the pre PEP and get the result
        msParamArray_t params;
        memset( &params, 0, sizeof( params ) );
        int status = applyRuleUpdateParams(
                         "acPreConnect(*OUT)",
                         &params,
                         &rei,
                         NO_SAVE_REI );
        if ( 0 != status ) {
            return ERROR( status, "failed in call to applyRuleUpdateParams" );
        }

        // =-=-=-=-=-=-=-
        // extract the value from the outgoing param to pass out to the operation
        char* rule_result_ptr = 0;
        msParam_t* out_ms_param = getMsParamByLabel( &params, "*OUT" );
        if ( out_ms_param ) {
            rule_result_ptr = reinterpret_cast< char* >( out_ms_param->inOutStruct );

        }
        else {
            return ERROR( SYS_INVALID_INPUT_PARAM, "null out parameter" );

        }

        if ( !rule_result_ptr ) {
            return ERROR( SYS_INVALID_INPUT_PARAM, "rule_result is null" );

        }

        std::string rule_result( rule_result_ptr );
        clearMsParamArray( &params, 0 );

        // =-=-=-=-=-=-=-
        // check to see if a negoation was requested
        if ( !do_client_server_negotiation_for_server() ) {
            // =-=-=-=-=-=-=-
            // if it was not but we require SSL then error out
            if ( CS_NEG_REQUIRE == rule_result ) {
                std::stringstream msg;
                msg << "SSL is required by the server but not requested by the client";
                return ERROR( SYS_INVALID_INPUT_PARAM, msg.str() );

            }
            else {
                // =-=-=-=-=-=-=-
                // a negotiation was not requested, bail
                return SUCCESS();
            }

        }

        // =-=-=-=-=-=-=-
        // pass the PEP result to the client, send CS_NEG_SVR_1_MSG
        irods::cs_neg_t cs_neg;
        cs_neg.status_ = CS_NEG_STATUS_SUCCESS;
        snprintf( cs_neg.result_, sizeof( cs_neg.result_ ), "%s", rule_result.c_str() );
        error err = send_client_server_negotiation_message( _ptr, cs_neg );
        if ( !err.ok() ) {
            std::stringstream msg;
            msg << "failed with PEP value of [" << rule_result << "]";
            return PASSMSG( msg.str(), err );
        }

        // =-=-=-=-=-=-=-
        // get the response from CS_NEG_CLI_1_MSG
        boost::shared_ptr< cs_neg_t > read_cs_neg;
        err = read_client_server_negotiation_message( _ptr, read_cs_neg );
        if ( !err.ok() ) {
            return PASS( err );
        }

        // =-=-=-=-=-=-=-
        // get the result from the key val pair
        if ( strlen( read_cs_neg->result_ ) != 0 ) {
            irods::kvp_map_t kvp;
            err = irods::parse_kvp_string(
                      read_cs_neg->result_,
                      kvp );
            if ( err.ok() ) {

                // =-=-=-=-=-=-=-
                // extract the signed SID
                if ( kvp.find( CS_NEG_SID_KW ) != kvp.end() ) {
                    std::string svr_sid = kvp[ CS_NEG_SID_KW ];
                    if ( !svr_sid.empty() ) {
                        // =-=-=-=-=-=-=-
                        // get our SID to compare
                        server_properties& props = server_properties::getInstance();
                        err = props.capture_if_needed();
                        if ( !err.ok() ) {
                            return PASS( err );
                        }

                        // =-=-=-=-=-=-=-
                        // check SID against our SIDs
                        err = check_sent_sid(
                                  props,
                                  svr_sid );
                        if ( !err.ok() ) {
                            rodsLog(
                                LOG_DEBUG,
                                "[%s]",
                                PASS( err ).status() );
                        }
                        else {
                            // =-=-=-=-=-=-=-
                            // store property that states this is an
                            // Agent-Agent connection
                            props.set_property <
                            std::string > (
                                AGENT_CONN_KW,
                                svr_sid );
                        }

                    } // if sid is not empty
                    else {
                        rodsLog(
                            LOG_DEBUG,
                            "%s - sent SID is empty",
                            __FUNCTION__ );
                    }
                }

                // =-=-=-=-=-=-=-
                // check to see if the result string has the SSL negotiation results
                _result = kvp[ CS_NEG_RESULT_KW ];
                if ( _result.empty() ) {
                    return ERROR(
                               UNMATCHED_KEY_OR_INDEX,
                               "SSL result string missing from response" );
                }

            }
            else {
                // =-=-=-=-=-=-=-
                // support 4.0 client-server negotiation which did not
                // use key-val pairs
                _result = read_cs_neg->result_;

            }

        } // if result strlen > 0

        // =-=-=-=-=-=-=-
        // if the response is favorable, return success
        if ( CS_NEG_STATUS_SUCCESS == read_cs_neg->status_ ) {
            return SUCCESS();
        }

        // =-=-=-=-=-=-=-
        // else, return a failure
        return ERROR( -1, "failure detected from client" );

    } // client_server_negotiation_for_server
Exemplo n.º 2
0
/// =-=-=-=-=-=-=-
/// @brief function which manages the TLS and Auth negotiations with the client
    error client_server_negotiation_for_client(
        irods::network_object_ptr _ptr,
        std::string&              _result ) {

        // =-=-=-=-=-=-=-
        // we requested a negotiation, wait for the response from CS_NEG_SVR_1_MSG
        boost::shared_ptr< cs_neg_t > cs_neg;
        error err = read_client_server_negotiation_message( _ptr, cs_neg );
        if ( !err.ok() ) {
            return PASS( err );
        }

        // =-=-=-=-=-=-=-
        // get the server requested policy
        std::string svr_policy( cs_neg->result_ );
        if ( svr_policy.empty() || cs_neg->status_ != CS_NEG_STATUS_SUCCESS ) {
            std::stringstream msg;
            msg << "invalid result [" << cs_neg->result_ << "]  or status: " << cs_neg->status_;
            return ERROR( -1, msg.str() );
        }

        // =-=-=-=-=-=-=-
        // get the irods environment so we can compare the
        // policy in the .irodsEnv file
        rodsEnv rods_env;
        int status = getRodsEnv( &rods_env );
        if ( status < 0 ) {
            return ERROR( status, "failed in getRodsEnv" );
        }

        // =-=-=-=-=-=-=-
        // if the policy is empty, then default to DONT_CARE
        std::string cli_policy( rods_env.rodsClientServerPolicy );
        if ( cli_policy.empty() ) {
            cli_policy = CS_NEG_DONT_CARE;

        }

        // =-=-=-=-=-=-=-
        // perform the negotiation
        client_server_negotiations_context negotiate;
        std::string result;
        error neg_err = negotiate( cli_policy, svr_policy, result );

        // =-=-=-=-=-=-=-
        // aggregate the error stack if necessary
        error ret = SUCCESS();
        if ( !neg_err.ok() ) {
            ret = PASSMSG( "failed in negotiation context", neg_err );
        }

        // =-=-=-=-=-=-=-
        // handle failure - send a failure msg back to client
        if ( !err.ok() || CS_NEG_FAILURE == result ) {
            // =-=-=-=-=-=-=-
            // send CS_NEG_CLI_1_MSG, failure message to the server
            cs_neg_t send_cs_neg;
            send_cs_neg.status_ = CS_NEG_STATUS_FAILURE;
            strncpy( send_cs_neg.result_, CS_NEG_FAILURE.c_str(), MAX_NAME_LEN );
            error send_err = send_client_server_negotiation_message(
                                 _ptr,
                                 send_cs_neg );
            if ( !send_err.ok() ) {
                ret = PASSMSG( "failed to send CS_NEG_CLI1_MSG Failure Messsage", send_err );
            }

            std::stringstream msg;
            msg << "client-server negoations failed for server request [";
            msg << svr_policy << "] and client request [" << cli_policy << "]";
            ret = PASSMSG( msg.str(), ret );
            return ret;
        }

        // =-=-=-=-=-=-=-
        // send CS_NEG_CLI_1_MSG, success message to the server with our choice
        cs_neg_t send_cs_neg;
        send_cs_neg.status_ = CS_NEG_STATUS_SUCCESS;
        strncpy( send_cs_neg.result_, result.c_str(), MAX_NAME_LEN );
        err = send_client_server_negotiation_message(
                  _ptr,
                  send_cs_neg );
        if ( !err.ok() ) {
            return PASSMSG( "failed to send CS_NEG_CLI_1_MSG Success Message", err );
        }

        // =-=-=-=-=-=-=-
        // set the out variable and return
        _result = result;

        return SUCCESS();

    } // client_server_negotiation_for_client