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 }
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]; bufp = _rsAuthRequestGetChallenge(); /* need to do NoLogin because it could get into inf loop for cross * zone auth */ status = getAndConnRcatHostNoLogin (rsComm, MASTER_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) { char username2[NAME_LEN+2]; char userZone[NAME_LEN+2]; int 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 (requireSIDs) { rodsLog(LOG_NOTICE, "Authentication disallowed, no RemoteZoneSID defined"); return(REMOTE_SERVER_SID_NOT_DEFINED); } } else { 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 { 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 { int OK, i; char *cp; memset(md5Buf, 0, sizeof(md5Buf)); strncpy(md5Buf, authCheckInp.challenge, CHALLENGE_LEN); 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*/ } 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); } } } } } #ifdef STORAGE_ADMIN_ROLE /* if the user is a storage admin, this will be indicated with a bit in authCheckOut->privLevel. If it's set, set the userType in rsComm->proxyUser to 'storageadmin' and clear the bit so it doesn't affect subsequent checks */ if (authCheckOut->privLevel & STORAGE_ADMIN_USER) { strncpy(rsComm->proxyUser.userType, STORAGE_ADMIN_USER_TYPE, NAME_LEN); authCheckOut->privLevel &= ~STORAGE_ADMIN_USER; } #endif /* 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_USER_AUTH) authCheckOut->privLevel = REMOTE_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); }