/// =-=-=-=-=-=-=- /// @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( ¶ms, 0, sizeof( params ) ); int status = applyRuleUpdateParams( "acPreConnect(*OUT)", ¶ms, &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( ¶ms, "*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( ¶ms, 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
/// =-=-=-=-=-=-=- /// @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