Exemplo n.º 1
0
int igsiServersideAuth() {
    int status;
#if defined(GSI_AUTH)
    char clientName[500];
    genQueryInp_t genQueryInp;
    genQueryOut_t *genQueryOut;
    char condition1[MAX_NAME_LEN];
    char condition2[MAX_NAME_LEN];
    char *tResult;
    int privLevel;
    int clientPrivLevel;
    int noNameMode;
    int statusRule;
#ifdef GSI_DEBUG
    char *getVar;
    getVar = getenv( "X509_CERT_DIR" );
    if ( getVar != NULL ) {
        printf( "X509_CERT_DIR:%s\n", getVar );
    }
#endif

    gsiAuthReqStatus = 1;

    status = igsiEstablishContextServerside( rsComm, clientName, 500 );
#ifdef GSI_DEBUG
    if ( status == 0 ) {
        printf( "clientName:%s\n", clientName );
    }
#endif

    memset( &genQueryInp, 0, sizeof( genQueryInp_t ) );

    noNameMode = 0;
    if ( strlen( rsComm->clientUser.userName ) > 0 ) {
        /* regular mode */

        snprintf( condition1, MAX_NAME_LEN, "='%s'", clientName );
        addInxVal( &genQueryInp.sqlCondInp, COL_USER_DN, condition1 );

        snprintf( condition2, MAX_NAME_LEN, "='%s'",
                  rsComm->clientUser.userName );
        addInxVal( &genQueryInp.sqlCondInp, COL_USER_NAME, condition2 );

        addInxIval( &genQueryInp.selectInp, COL_USER_ID, 1 );
        addInxIval( &genQueryInp.selectInp, COL_USER_TYPE, 1 );
        addInxIval( &genQueryInp.selectInp, COL_USER_ZONE, 1 );

        genQueryInp.maxRows = 2;

        status = rsGenQuery( rsComm, &genQueryInp, &genQueryOut );
    }
    else {
        /*
        The client isn't providing the rodsUserName so query on just
               the DN.  If it returns just one row, set the clientUser to
               the returned irods user name.
            */
        noNameMode = 1;
        memset( &genQueryInp, 0, sizeof( genQueryInp_t ) );

        snprintf( condition1, MAX_NAME_LEN, "='%s'", clientName );
        addInxVal( &genQueryInp.sqlCondInp, COL_USER_DN, condition1 );

        addInxIval( &genQueryInp.selectInp, COL_USER_ID, 1 );
        addInxIval( &genQueryInp.selectInp, COL_USER_TYPE, 1 );
        addInxIval( &genQueryInp.selectInp, COL_USER_NAME, 1 );
        addInxIval( &genQueryInp.selectInp, COL_USER_ZONE, 1 );

        genQueryInp.maxRows = 2;

        status = rsGenQuery( rsComm, &genQueryInp, &genQueryOut );

        if ( status == CAT_NO_ROWS_FOUND ) { /* not found */
            /* execute the rule acGetUserByDN.  By default this
                   is a no-op but at some sites can be configured to
                   run a process to determine a user by DN (for VO support)
                   or possibly create the user.
               The stdout of the process is the irodsUserName to use.

               The corresponding rule would be something like this:
               acGetUserByDN(*arg,*OUT)||msiExecCmd(t,"*arg",null,null,null,*OUT)|nop
            */
            ruleExecInfo_t rei;
            char *args[2];
            msParamArray_t *myMsParamArray;
            msParamArray_t myInOutParamArray;

            memset( ( char* )&rei, 0, sizeof( rei ) );
            rei.rsComm = rsComm;
            rei.uoic = &rsComm->clientUser;
            rei.uoip = &rsComm->proxyUser;
            args[0] = clientName;
            char out[200] = "*cmdOutput";
            args[1] = out;

            rei.inOutMsParamArray = myInOutParamArray;

            myMsParamArray = ( msParamArray_t * ) malloc( sizeof( msParamArray_t ) );
            memset( myMsParamArray, 0, sizeof( msParamArray_t ) );

            statusRule = applyRuleArgPA( "acGetUserByDN", args, 2,
                                         myMsParamArray, &rei, NO_SAVE_REI );

#ifdef GSI_DEBUG
            printf( "acGetUserByDN status=%d\n", statusRule );

            int i;
            for ( i = 0; i < myMsParamArray->len; i++ ) {
                char *r;
                msParam_t *myP;
                myP = myMsParamArray->msParam[i];
                r = myP->label;
                printf( "l1=%s\n", r );
            }
#endif
            /* Try the query again, whether or not the rule succeeded, to see
                   if the user has been added. */
            memset( &genQueryInp, 0, sizeof( genQueryInp_t ) );

            snprintf( condition1, MAX_NAME_LEN, "='%s'", clientName );
            addInxVal( &genQueryInp.sqlCondInp, COL_USER_DN, condition1 );

            addInxIval( &genQueryInp.selectInp, COL_USER_ID, 1 );
            addInxIval( &genQueryInp.selectInp, COL_USER_TYPE, 1 );
            addInxIval( &genQueryInp.selectInp, COL_USER_NAME, 1 );
            addInxIval( &genQueryInp.selectInp, COL_USER_ZONE, 1 );

            genQueryInp.maxRows = 2;

            status = rsGenQuery( rsComm, &genQueryInp, &genQueryOut );
        }
        if ( status == 0 ) {
            char *myBuf;
            strncpy( rsComm->clientUser.userName, genQueryOut->sqlResult[2].value,
                     NAME_LEN );
            strncpy( rsComm->proxyUser.userName, genQueryOut->sqlResult[2].value,
                     NAME_LEN );
            strncpy( rsComm->clientUser.rodsZone, genQueryOut->sqlResult[3].value,
                     NAME_LEN );
            strncpy( rsComm->proxyUser.rodsZone, genQueryOut->sqlResult[3].value,
                     NAME_LEN );
            myBuf = ( char * )malloc( NAME_LEN * 2 );
            snprintf( myBuf, NAME_LEN * 2, "%s=%s", SP_CLIENT_USER,
                      rsComm->clientUser.userName );
            putenv( myBuf );
            free( myBuf ); // JMC cppcheck - leak
        }
    }
    if ( status == CAT_NO_ROWS_FOUND || genQueryOut == NULL ) {
        status = GSI_DN_DOES_NOT_MATCH_USER;
        rodsLog( LOG_NOTICE,
                 "igsiServersideAuth: DN mismatch, user=%s, Certificate DN=%s, status=%d",
                 rsComm->clientUser.userName,
                 clientName,
                 status );
        snprintf( gsiAuthReqErrorMsg, sizeof gsiAuthReqErrorMsg,
                  "igsiServersideAuth: DN mismatch, user=%s, Certificate DN=%s, status=%d",
                  rsComm->clientUser.userName,
                  clientName,
                  status );
        gsiAuthReqError = status;
        return status;
    }

    if ( status < 0 ) {
        rodsLog( LOG_NOTICE,
                 "igsiServersideAuth: rsGenQuery failed, status = %d", status );
        snprintf( gsiAuthReqErrorMsg, sizeof gsiAuthReqErrorMsg,
                  "igsiServersideAuth: rsGenQuery failed, status = %d", status );
        gsiAuthReqError = status;
        return status;
    }

    if ( noNameMode == 0 ) {
        if ( genQueryOut == NULL || genQueryOut->rowCnt < 1 ) {
            gsiAuthReqError = GSI_NO_MATCHING_DN_FOUND;
            return GSI_NO_MATCHING_DN_FOUND;
        }
        if ( genQueryOut->rowCnt > 1 ) {
            gsiAuthReqError = GSI_MULTIPLE_MATCHING_DN_FOUND;
            return GSI_MULTIPLE_MATCHING_DN_FOUND;
        }
        if ( genQueryOut->attriCnt != 3 ) {
            gsiAuthReqError = GSI_QUERY_INTERNAL_ERROR;
            return GSI_QUERY_INTERNAL_ERROR;
        }
    }
    else {
        if ( genQueryOut == NULL || genQueryOut->rowCnt < 1 ) {
            gsiAuthReqError = GSI_NO_MATCHING_DN_FOUND;
            return GSI_NO_MATCHING_DN_FOUND;
        }
        if ( genQueryOut->rowCnt > 1 ) {
            gsiAuthReqError = GSI_MULTIPLE_MATCHING_DN_FOUND;
            return GSI_MULTIPLE_MATCHING_DN_FOUND;
        }
        if ( genQueryOut->attriCnt != 4 ) {
            gsiAuthReqError = GSI_QUERY_INTERNAL_ERROR;
            return GSI_QUERY_INTERNAL_ERROR;
        }
    }

#ifdef GSI_DEBUG
    printf( "Results=%d\n", genQueryOut->rowCnt );
#endif

    tResult = genQueryOut->sqlResult[0].value;
#ifdef GSI_DEBUG
    printf( "0:%s\n", tResult );
#endif
    tResult = genQueryOut->sqlResult[1].value;
#ifdef GSI_DEBUG
    printf( "1:%s\n", tResult );
#endif
    privLevel = LOCAL_USER_AUTH;
    clientPrivLevel = LOCAL_USER_AUTH;

    if ( strcmp( tResult, "rodsadmin" ) == 0 ) {
        privLevel = LOCAL_PRIV_USER_AUTH;
        clientPrivLevel = LOCAL_PRIV_USER_AUTH;
    }

    status = chkProxyUserPriv( rsComm, privLevel );

    if ( status < 0 ) {
        return status;
    }

    rsComm->proxyUser.authInfo.authFlag = privLevel;
    rsComm->clientUser.authInfo.authFlag = clientPrivLevel;

    if ( noNameMode ) { /* We didn't before, but now have an irodsUserName */
        int status2, status3;
        rodsServerHost_t *rodsServerHost = NULL;
        status2 = getAndConnRcatHost( rsComm, MASTER_RCAT,
                                      rsComm->myEnv.rodsZone, &rodsServerHost );
        if ( status2 >= 0 &&
                rodsServerHost->localFlag == REMOTE_HOST &&
                rodsServerHost->conn != NULL ) {  /* If the IES is remote */

            status3 = rcDisconnect( rodsServerHost->conn ); /* disconnect*/

            /* And clear out the connection information so
               getAndConnRcatHost will reconnect.  This may leak some
               memory but only happens at most once in an agent:  */
            rodsServerHost->conn = NULL;

            /* And reconnect (with irodsUserName here and in the IES): */
            status3 = getAndConnRcatHost( rsComm, MASTER_RCAT,
                                          rsComm->myEnv.rodsZone,
                                          &rodsServerHost );
            if ( status3 ) {
                rodsLog( LOG_ERROR,
                         "igsiServersideAuth failed in getAndConnRcatHost, status = %d",
                         status3 );
                return status3;
            }
        }
    }
    return status;
#else
    status = GSI_NOT_BUILT_INTO_SERVER;
    rodsLog( LOG_ERROR,
             "igsiServersideAuth failed GSI_NOT_BUILT_INTO_SERVER, status = %d",
             status );
    return status;
#endif
}
Exemplo n.º 2
0
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);
}