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); }
// =-=-=-=-=-=-=- // 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