int rsAuthResponse (rsComm_t *rsComm, authResponseInp_t *authResponseInp) { int status; char *bufp; authCheckInp_t authCheckInp; authCheckOut_t *authCheckOut = NULL; rodsServerHost_t *rodsServerHost; char digest[RESPONSE_LEN+2]; char md5Buf[CHALLENGE_LEN+MAX_PASSWORD_LEN+2]; char serverId[MAX_PASSWORD_LEN+2]; MD5_CTX context; bufp = _rsAuthRequestGetChallenge(); /* need to do NoLogin because it could get into inf loop for cross * zone auth */ status = getAndConnRcatHostNoLogin (rsComm, SLAVE_RCAT, rsComm->proxyUser.rodsZone, &rodsServerHost); if (status < 0) { return(status); } memset (&authCheckInp, 0, sizeof (authCheckInp)); authCheckInp.challenge = bufp; authCheckInp.response = authResponseInp->response; authCheckInp.username = authResponseInp->username; if (rodsServerHost->localFlag == LOCAL_HOST) { status = rsAuthCheck (rsComm, &authCheckInp, &authCheckOut); } else { status = rcAuthCheck (rodsServerHost->conn, &authCheckInp, &authCheckOut); /* not likely we need this connection again */ rcDisconnect(rodsServerHost->conn); rodsServerHost->conn = NULL; } if (status < 0) { rodsLog (LOG_NOTICE, "rsAuthResponse: rxAuthCheck failed, status = %d", status); return (status); } if (rodsServerHost->localFlag != LOCAL_HOST) { if (authCheckOut->serverResponse == NULL) { rodsLog(LOG_NOTICE, "Warning, cannot authenticate remote server, no serverResponse field"); if (requireServerAuth) { rodsLog(LOG_NOTICE, "Authentication disallowed, no serverResponse field"); return(REMOTE_SERVER_AUTH_NOT_PROVIDED); } } else { char *cp; int OK, len, i; if (*authCheckOut->serverResponse == '\0') { rodsLog(LOG_NOTICE, "Warning, cannot authenticate remote server, serverResponse field is empty"); if (requireServerAuth) { rodsLog(LOG_NOTICE, "Authentication disallowed, empty serverResponse"); return(REMOTE_SERVER_AUTH_EMPTY); } } else { char username2[NAME_LEN+2]; char userZone[NAME_LEN+2]; memset(md5Buf, 0, sizeof(md5Buf)); strncpy(md5Buf, authCheckInp.challenge, CHALLENGE_LEN); parseUserName(authResponseInp->username, username2, userZone); getZoneServerId(userZone, serverId); len = strlen(serverId); if (len <= 0) { rodsLog (LOG_NOTICE, "rsAuthResponse: Warning, cannot authenticate the remote server, no RemoteZoneSID defined in server.config", status); if (requireServerAuth) { rodsLog(LOG_NOTICE, "Authentication disallowed, no RemoteZoneSID defined"); return(REMOTE_SERVER_SID_NOT_DEFINED); } } else { strncpy(md5Buf+CHALLENGE_LEN, serverId, len); MD5Init (&context); MD5Update (&context, (unsigned char*)md5Buf, CHALLENGE_LEN+MAX_PASSWORD_LEN); MD5Final ((unsigned char*)digest, &context); for (i=0;i<RESPONSE_LEN;i++) { if (digest[i]=='\0') digest[i]++; /* make sure 'string' doesn't end early*/ } cp = authCheckOut->serverResponse; OK=1; for (i=0;i<RESPONSE_LEN;i++) { if (*cp++ != digest[i]) OK=0; } rodsLog(LOG_DEBUG, "serverResponse is OK/Not: %d", OK); if (OK==0) { rodsLog(LOG_NOTICE, "Server response incorrect, authentication disallowed"); return(REMOTE_SERVER_AUTHENTICATION_FAILURE); } } } } } /* Set the clientUser zone if it is null. */ if (strlen(rsComm->clientUser.rodsZone)==0) { zoneInfo_t *tmpZoneInfo; status = getLocalZoneInfo (&tmpZoneInfo); if (status < 0) { free (authCheckOut); return status; } strncpy(rsComm->clientUser.rodsZone, tmpZoneInfo->zoneName, NAME_LEN); } /* have to modify privLevel if the icat is a foreign icat because * a local user in a foreign zone is not a local user in this zone * and vice vera for a remote user */ if (rodsServerHost->rcatEnabled == REMOTE_ICAT) { /* proxy is easy because rodsServerHost is based on proxy user */ if (authCheckOut->privLevel == LOCAL_PRIV_USER_AUTH) authCheckOut->privLevel = REMOTE_PRIV_USER_AUTH; else if (authCheckOut->privLevel == LOCAL_PRIV_USER_AUTH) authCheckOut->privLevel = REMOTE_PRIV_USER_AUTH; /* adjust client user */ if (strcmp (rsComm->proxyUser.userName, rsComm->clientUser.userName) == 0) { authCheckOut->clientPrivLevel = authCheckOut->privLevel; } else { zoneInfo_t *tmpZoneInfo; status = getLocalZoneInfo (&tmpZoneInfo); if (status < 0) { free (authCheckOut); return status; } if (strcmp (tmpZoneInfo->zoneName, rsComm->clientUser.rodsZone) == 0) { /* client is from local zone */ if (authCheckOut->clientPrivLevel == REMOTE_PRIV_USER_AUTH) { authCheckOut->clientPrivLevel = LOCAL_PRIV_USER_AUTH; } else if (authCheckOut->clientPrivLevel == REMOTE_USER_AUTH) { authCheckOut->clientPrivLevel = LOCAL_USER_AUTH; } } else { /* client is from remote zone */ if (authCheckOut->clientPrivLevel == LOCAL_PRIV_USER_AUTH) { authCheckOut->clientPrivLevel = REMOTE_USER_AUTH; } else if (authCheckOut->clientPrivLevel == LOCAL_USER_AUTH) { authCheckOut->clientPrivLevel = REMOTE_USER_AUTH; } } } } else if (strcmp (rsComm->proxyUser.userName, rsComm->clientUser.userName) == 0) { authCheckOut->clientPrivLevel = authCheckOut->privLevel; } status = chkProxyUserPriv (rsComm, authCheckOut->privLevel); if (status < 0) { free (authCheckOut); return status; } rodsLog(LOG_NOTICE, "rsAuthResponse set proxy authFlag to %d, client authFlag to %d, user:%s proxy:%s client:%s", authCheckOut->privLevel, authCheckOut->clientPrivLevel, authCheckInp.username, rsComm->proxyUser.userName, rsComm->clientUser.userName); if (strcmp (rsComm->proxyUser.userName, rsComm->clientUser.userName) != 0) { rsComm->proxyUser.authInfo.authFlag = authCheckOut->privLevel; rsComm->clientUser.authInfo.authFlag = authCheckOut->clientPrivLevel; } else { /* proxyUser and clientUser are the same */ rsComm->proxyUser.authInfo.authFlag = rsComm->clientUser.authInfo.authFlag = authCheckOut->privLevel; } /*** Added by RAJA Nov 16 2010 **/ if (authCheckOut->serverResponse != NULL) free(authCheckOut->serverResponse); /*** Added by RAJA Nov 16 2010 **/ free (authCheckOut); return (status); }
int rsAuthCheck (rsComm_t *rsComm, authCheckInp_t *authCheckInp, authCheckOut_t **authCheckOut) { #ifdef RODS_CAT int status; int privLevel; int clientPrivLevel; authCheckOut_t *result; unsigned char *digest; char md5Buf[CHALLENGE_LEN+MAX_PASSWORD_LEN+2]; char ServerID[MAX_PASSWORD_LEN+2]; *authCheckOut = (authCheckOut_t*)malloc(sizeof(authCheckOut_t)); memset((char *)*authCheckOut, 0, sizeof(authCheckOut_t)); rodsLog(LOG_NOTICE, "rsAuthCheck user %s", authCheckInp->username); status = chlCheckAuth(rsComm, authCheckInp->challenge, authCheckInp->response, authCheckInp->username, &privLevel, &clientPrivLevel); if (status < 0) { rodsLog (LOG_NOTICE, "rsAuthCheck: chlCheckAuth status = %d", status); } if (status == 0) { int len, i; result = *authCheckOut; result->privLevel = privLevel; result->clientPrivLevel = clientPrivLevel; /* Add a hash to authenticate this server to the other server */ memset(md5Buf, 0, sizeof(md5Buf)); strncpy(md5Buf, authCheckInp->challenge, CHALLENGE_LEN); getZoneServerId("", ServerID); /* get our local zone SID */ len = strlen(ServerID); digest = ( unsigned char* )malloc(RESPONSE_LEN+2); if (len <=0) { rodsLog (LOG_DEBUG, "rsAuthCheck: Warning, cannot authenticate this server to remote server, no LocalZoneSID defined in server.config", status); memset(digest, 0, RESPONSE_LEN); } else { strncpy(md5Buf+CHALLENGE_LEN, ServerID, len); obfMakeOneWayHash( HASH_TYPE_DEFAULT, (unsigned char*)md5Buf, CHALLENGE_LEN+MAX_PASSWORD_LEN, (unsigned char*)digest); for (i=0;i<RESPONSE_LEN;i++) { if (digest[i]=='\0') digest[i]++; /* make sure 'string' doesn't end early */ } } result->serverResponse = (char*)digest; } return (status); #else /* this may be a gateway to the rcat host */ rodsServerHost_t *rodsServerHost; int status; status = getAndConnRcatHostNoLogin (rsComm, MASTER_RCAT, rsComm->proxyUser.rodsZone, &rodsServerHost); if (status < 0) { rodsLog (LOG_NOTICE, "rsAuthCheck:getAndConnRcatHostNoLogin() failed. erro=%d", status); return (status); } if (rodsServerHost->localFlag == LOCAL_HOST) { return ( SYS_NO_ICAT_SERVER_ERR); } else { status = rcAuthCheck (rodsServerHost->conn, authCheckInp, authCheckOut); } return status; #endif }
int rsAuthCheck( rsComm_t *rsComm, authCheckInp_t *authCheckInp, authCheckOut_t **authCheckOut ) { #ifdef RODS_CAT int status; int privLevel; int clientPrivLevel; authCheckOut_t *result; unsigned char *digest; char md5Buf[CHALLENGE_LEN + MAX_PASSWORD_LEN + 2]; char ServerID[MAX_PASSWORD_LEN + 2]; *authCheckOut = ( authCheckOut_t* )malloc( sizeof( authCheckOut_t ) ); memset( ( char * )*authCheckOut, 0, sizeof( authCheckOut_t ) ); // =-=-=-=-=-=-=- // the incoming response string might be a kvp string // holding the auth scheme as well as the response // try to parse it // NOTE :: incoming response string is longer than RESPONSE_LEN so we // cannot directly assign it, it will need to be properly terminated // and not contain any magic characters std::string scheme; std::string orig_resp = authCheckInp->response; std::string response = authCheckInp->response; irods::kvp_map_t kvp; irods::error ret = irods::parse_kvp_string( orig_resp, kvp ); if ( ret.ok() ) { if ( kvp.end() != kvp.find( irods::AUTH_SCHEME_KEY ) ) { scheme = kvp[ irods::AUTH_SCHEME_KEY ]; // =-=-=-=-=-=-=- // subset the 'response' string from the incoming kvp set size_t response_key_pos = response.find( irods::AUTH_RESPONSE_KEY ); if ( response_key_pos != std::string::npos ) { char *response_ptr = authCheckInp->response + ( response_key_pos + irods::AUTH_RESPONSE_KEY.length() + irods::KVP_DEF_ASSOCIATION.length() ); response.assign( response_ptr, RESPONSE_LEN + 2 ); } } } else { response.assign( authCheckInp->response, RESPONSE_LEN ); } status = chlCheckAuth( rsComm, scheme.c_str(), authCheckInp->challenge, const_cast< char* >( response.c_str() ), authCheckInp->username, &privLevel, &clientPrivLevel ); if ( status < 0 ) { rodsLog( LOG_NOTICE, "rsAuthCheck: chlCheckAuth status = %d", status ); } if ( status == 0 ) { int len, i; result = *authCheckOut; result->privLevel = privLevel; result->clientPrivLevel = clientPrivLevel; /* Add a hash to authenticate this server to the other server */ memset( md5Buf, 0, sizeof( md5Buf ) ); strncpy( md5Buf, authCheckInp->challenge, CHALLENGE_LEN ); getZoneServerId( "", ServerID ); /* get our local zone SID */ len = strlen( ServerID ); digest = ( unsigned char* )malloc( RESPONSE_LEN + 2 ); if ( len <= 0 ) { rodsLog( LOG_DEBUG, "rsAuthCheck: Warning, cannot authenticate this server to remote server, no LocalZoneSID defined in server_config.json", status ); memset( digest, 0, RESPONSE_LEN ); } else { strncpy( md5Buf + CHALLENGE_LEN, ServerID, len ); obfMakeOneWayHash( HASH_TYPE_DEFAULT, ( unsigned char* )md5Buf, CHALLENGE_LEN + MAX_PASSWORD_LEN, ( unsigned char* )digest ); for ( i = 0; i < RESPONSE_LEN; i++ ) { if ( digest[i] == '\0' ) { digest[i]++; } /* make sure 'string' doesn't end early */ } } result->serverResponse = ( char* )digest; } return status; #else /* this may be a gateway to the rcat host */ rodsServerHost_t *rodsServerHost; int status; status = getAndConnRcatHostNoLogin( rsComm, MASTER_RCAT, rsComm->proxyUser.rodsZone, &rodsServerHost ); if ( status < 0 ) { rodsLog( LOG_NOTICE, "rsAuthCheck:getAndConnRcatHostNoLogin() failed. erro=%d", status ); return status; } if ( rodsServerHost->localFlag == LOCAL_HOST ) { return SYS_NO_ICAT_SERVER_ERR; } else { status = rcAuthCheck( rodsServerHost->conn, authCheckInp, authCheckOut ); } return status; #endif }
// =-=-=-=-=-=-=- // handle an agent-side auth request call irods::error osauth_auth_agent_response( irods::auth_plugin_context& _ctx, authResponseInp_t* _resp ) { // =-=-=-=-=-=-=- // validate incoming parameters if ( !_ctx.valid().ok() ) { return ERROR( SYS_INVALID_INPUT_PARAM, "invalid plugin context" ); } else if ( !_resp ) { return ERROR( SYS_INVALID_INPUT_PARAM, "null authResponseInp_t ptr" ); } int status; char *bufp; authCheckInp_t authCheckInp; rodsServerHost_t *rodsServerHost; char digest[RESPONSE_LEN + 2]; char md5Buf[CHALLENGE_LEN + MAX_PASSWORD_LEN + 2]; char serverId[MAX_PASSWORD_LEN + 2]; MD5_CTX context; bufp = _rsAuthRequestGetChallenge(); // =-=-=-=-=-=-=- // need to do NoLogin because it could get into inf loop for cross // zone auth status = getAndConnRcatHostNoLogin( _ctx.comm(), MASTER_RCAT, _ctx.comm()->proxyUser.rodsZone, &rodsServerHost ); if ( status < 0 ) { return ERROR( status, "getAndConnRcatHostNoLogin failed" ); } memset( &authCheckInp, 0, sizeof( authCheckInp ) ); authCheckInp.challenge = bufp; authCheckInp.username = _resp->username; std::string resp_str = irods::AUTH_SCHEME_KEY + irods::kvp_association() + irods::AUTH_OSAUTH_SCHEME + irods::kvp_delimiter() + irods::AUTH_RESPONSE_KEY + irods::kvp_association() + _resp->response; authCheckInp.response = const_cast<char*>( resp_str.c_str() ); authCheckOut_t *authCheckOut = NULL; if ( rodsServerHost->localFlag == LOCAL_HOST ) { status = rsAuthCheck( _ctx.comm(), &authCheckInp, &authCheckOut ); } else { status = rcAuthCheck( rodsServerHost->conn, &authCheckInp, &authCheckOut ); /* not likely we need this connection again */ rcDisconnect( rodsServerHost->conn ); rodsServerHost->conn = NULL; } if ( status < 0 || authCheckOut == NULL ) { // JMC cppcheck if ( authCheckOut != NULL ) { free( authCheckOut->serverResponse ); } free( authCheckOut ); return ERROR( status, "rxAuthCheck failed" ); } if ( rodsServerHost->localFlag != LOCAL_HOST ) { if ( authCheckOut->serverResponse == NULL ) { rodsLog( LOG_NOTICE, "Warning, cannot authenticate remote server, no serverResponse field" ); if ( requireServerAuth ) { free( authCheckOut ); return ERROR( REMOTE_SERVER_AUTH_NOT_PROVIDED, "Authentication disallowed, no serverResponse field" ); } } else { char *cp; int OK, len, i; if ( *authCheckOut->serverResponse == '\0' ) { rodsLog( LOG_NOTICE, "Warning, cannot authenticate remote server, serverResponse field is empty" ); if ( requireServerAuth ) { free( authCheckOut->serverResponse ); free( authCheckOut ); return ERROR( REMOTE_SERVER_AUTH_EMPTY, "Authentication disallowed, empty serverResponse" ); } } else { char username2[NAME_LEN + 2]; char userZone[NAME_LEN + 2]; memset( md5Buf, 0, sizeof( md5Buf ) ); strncpy( md5Buf, authCheckInp.challenge, CHALLENGE_LEN ); parseUserName( _resp->username, username2, userZone ); getZoneServerId( userZone, serverId ); len = strlen( serverId ); if ( len <= 0 ) { rodsLog( LOG_NOTICE, "rsAuthResponse: Warning, cannot authenticate the remote server, no RemoteZoneSID defined in server_config.json", status ); if ( requireServerAuth ) { free( authCheckOut->serverResponse ); free( authCheckOut ); return ERROR( REMOTE_SERVER_SID_NOT_DEFINED, "Authentication disallowed, no RemoteZoneSID defined" ); } } else { strncpy( md5Buf + CHALLENGE_LEN, serverId, len ); MD5_Init( &context ); MD5_Update( &context, ( unsigned char* )md5Buf, CHALLENGE_LEN + MAX_PASSWORD_LEN ); MD5_Final( ( unsigned char* )digest, &context ); for ( i = 0; i < RESPONSE_LEN; i++ ) { if ( digest[i] == '\0' ) { digest[i]++; } /* make sure 'string' doesn't end early*/ } cp = authCheckOut->serverResponse; OK = 1; for ( i = 0; i < RESPONSE_LEN; i++ ) { if ( *cp++ != digest[i] ) { OK = 0; } } rodsLog( LOG_DEBUG, "serverResponse is OK/Not: %d", OK ); if ( OK == 0 ) { free( authCheckOut->serverResponse ); free( authCheckOut ); return ERROR( REMOTE_SERVER_AUTHENTICATION_FAILURE, "Server response incorrect, authentication disallowed" ); } } } } } /* Set the clientUser zone if it is null. */ if ( strlen( _ctx.comm()->clientUser.rodsZone ) == 0 ) { zoneInfo_t *tmpZoneInfo; status = getLocalZoneInfo( &tmpZoneInfo ); if ( status < 0 ) { free( authCheckOut->serverResponse ); free( authCheckOut ); return ERROR( status, "getLocalZoneInfo failed" ); } strncpy( _ctx.comm()->clientUser.rodsZone, tmpZoneInfo->zoneName, NAME_LEN ); } /* have to modify privLevel if the icat is a foreign icat because * a local user in a foreign zone is not a local user in this zone * and vice versa for a remote user */ if ( rodsServerHost->rcatEnabled == REMOTE_ICAT ) { /* proxy is easy because rodsServerHost is based on proxy user */ if ( authCheckOut->privLevel == LOCAL_PRIV_USER_AUTH ) { authCheckOut->privLevel = REMOTE_PRIV_USER_AUTH; } else if ( authCheckOut->privLevel == LOCAL_USER_AUTH ) { authCheckOut->privLevel = REMOTE_USER_AUTH; } /* adjust client user */ if ( strcmp( _ctx.comm()->proxyUser.userName, _ctx.comm()->clientUser.userName ) == 0 ) { authCheckOut->clientPrivLevel = authCheckOut->privLevel; } else { zoneInfo_t *tmpZoneInfo; status = getLocalZoneInfo( &tmpZoneInfo ); if ( status < 0 ) { free( authCheckOut->serverResponse ); free( authCheckOut ); return ERROR( status, "getLocalZoneInfo failed" ); } if ( strcmp( tmpZoneInfo->zoneName, _ctx.comm()->clientUser.rodsZone ) == 0 ) { /* client is from local zone */ if ( authCheckOut->clientPrivLevel == REMOTE_PRIV_USER_AUTH ) { authCheckOut->clientPrivLevel = LOCAL_PRIV_USER_AUTH; } else if ( authCheckOut->clientPrivLevel == REMOTE_USER_AUTH ) { authCheckOut->clientPrivLevel = LOCAL_USER_AUTH; } } else { /* client is from remote zone */ if ( authCheckOut->clientPrivLevel == LOCAL_PRIV_USER_AUTH ) { authCheckOut->clientPrivLevel = REMOTE_USER_AUTH; } else if ( authCheckOut->clientPrivLevel == LOCAL_USER_AUTH ) { authCheckOut->clientPrivLevel = REMOTE_USER_AUTH; } } } } else if ( strcmp( _ctx.comm()->proxyUser.userName, _ctx.comm()->clientUser.userName ) == 0 ) { authCheckOut->clientPrivLevel = authCheckOut->privLevel; } status = check_proxy_user_privileges( _ctx.comm(), authCheckOut->privLevel ); if ( status < 0 ) { free( authCheckOut->serverResponse ); free( authCheckOut ); return ERROR( status, "check_proxy_user_privileges failed" ); } rodsLog( LOG_DEBUG, "rsAuthResponse set proxy authFlag to %d, client authFlag to %d, user:%s proxy:%s client:%s", authCheckOut->privLevel, authCheckOut->clientPrivLevel, authCheckInp.username, _ctx.comm()->proxyUser.userName, _ctx.comm()->clientUser.userName ); if ( strcmp( _ctx.comm()->proxyUser.userName, _ctx.comm()->clientUser.userName ) != 0 ) { _ctx.comm()->proxyUser.authInfo.authFlag = authCheckOut->privLevel; _ctx.comm()->clientUser.authInfo.authFlag = authCheckOut->clientPrivLevel; } else { /* proxyUser and clientUser are the same */ _ctx.comm()->proxyUser.authInfo.authFlag = _ctx.comm()->clientUser.authInfo.authFlag = authCheckOut->privLevel; } free( authCheckOut->serverResponse ); free( authCheckOut ); return SUCCESS(); } // osauth_auth_agent_response