/*
  EHLO foo
  250-spamfirewall.domain.com
  250-PIPELINING
  250-SIZE 100000000
  250-VRFY
  250-ETRN
  250 8BITMIME
*/
int sayEHLO(int hSocket, _MODULE_DATA* _psSessionData)
{
  unsigned char bufSend[BUF_SIZE];
  unsigned char* bufReceive;
  int nReceiveBufferSize = 0;

  /* send helo string */
  memset(bufSend, 0, sizeof(bufSend));
  sprintf(bufSend, "EHLO %.250s\r\n", _psSessionData->szEHLO);

  if (medusaSend(hSocket, bufSend, strlen(bufSend), 0) < 0)
  {
    writeError(ERR_ERROR, "%s failed: medusaSend was not successful", MODULE_NAME);
  }

  nReceiveBufferSize = 0;
  bufReceive = medusaReceiveLineDelay(hSocket, &nReceiveBufferSize, RECEIVE_DELAY_1, RECEIVE_DELAY_2);
  if (bufReceive == NULL)
  {
    writeError(ERR_ERROR, "%s failed: medusaReceive returned no data.", MODULE_NAME);
    return FAILURE;
  }

  /* check if more data is waiting */
  if (medusaDataReadyTimed(hSocket, 0, 20000) > 0)
    bufReceive = medusaReceiveLineDelay(hSocket, &nReceiveBufferSize, RECEIVE_DELAY_1, RECEIVE_DELAY_2);
  
  writeError(ERR_DEBUG_MODULE, "[%s] Server responded to ELHO with: %s", MODULE_NAME, bufReceive);

  free(bufReceive);
  return SUCCESS;
}
/*
  VRFY [email protected]
  252 [email protected]
  
  VRFY [email protected]
  550 <*****@*****.**>: Recipient address rejected: No such user ([email protected])
  
  VRFY [email protected]
  554 <*****@*****.**>: Relay access denied
  
  421 Error: too many errors
*/
int tryLogin(int hSocket, sLogin** psLogin, _MODULE_DATA* _psSessionData, char* szDomain, char* szAccount)
{
  int iRet;
  unsigned char bufSend[BUF_SIZE];
  unsigned char* bufReceive;
  int nReceiveBufferSize = 0;

  /* send helo string */
  writeError(ERR_DEBUG_MODULE, "[%s] Sending: VRFY %.250s@%.250s\r\n", MODULE_NAME, szAccount, szDomain);
  memset(bufSend, 0, sizeof(bufSend));
  sprintf(bufSend, "VRFY %.250s@%.250s\r\n", szAccount, szDomain);

  if (medusaSend(hSocket, bufSend, strlen(bufSend), 0) < 0)
  {
    writeError(ERR_ERROR, "%s failed: medusaSend was not successful", MODULE_NAME);
  }

  nReceiveBufferSize = 0;
  bufReceive = medusaReceiveLineDelay(hSocket, &nReceiveBufferSize, RECEIVE_DELAY_1, RECEIVE_DELAY_2);
  if (bufReceive == NULL)
  {
    writeError(ERR_ERROR, "%s failed: medusaReceive returned no data.", MODULE_NAME);
    return FAILURE;
  }
  else if (strncmp(bufReceive, "252 ", 4) == 0) /* valid account */
  {
    writeError(ERR_DEBUG_MODULE, "[%s] Found valid account: %s", MODULE_NAME, szAccount);
    (*psLogin)->iResult = LOGIN_RESULT_SUCCESS;
    iRet = MSTATE_RUNNING;
  }
  else if (strncmp(bufReceive, "550 ", 4) == 0) /* non-existant account */
  {
    writeError(ERR_DEBUG_MODULE, "[%s] Non-existant account: %s", MODULE_NAME, szAccount);
    (*psLogin)->iResult = LOGIN_RESULT_FAIL;
    iRet = MSTATE_RUNNING;
  }
  else if (strncmp(bufReceive, "554 ", 4) == 0) /* invalid domain name */
  {
    writeError(ERR_ERROR, "[%s] Invalid domain name: %s", MODULE_NAME, szDomain);
    (*psLogin)->iResult = LOGIN_RESULT_ERROR;
    iRet = MSTATE_EXITING;
  }
  
  /* check if more data is waiting */
  if (medusaDataReadyTimed(hSocket, 0, 20000) > 0)
    bufReceive = medusaReceiveLineDelay(hSocket, &nReceiveBufferSize, RECEIVE_DELAY_1, RECEIVE_DELAY_2);
 
  if (strstr(bufReceive, "421 Error: too many errors"))
  {
    writeError(ERR_DEBUG_MODULE, "[%s] Too many errors. Restarting connection.", MODULE_NAME);
    iRet = MSTATE_NEW;
  }
  
  setPassResult((*psLogin), szDomain);
  return(iRet);
}
Exemple #3
0
int initModule(sLogin* _psLogin, _MODULE_DATA *_psSessionData)
{
  int hSocket = -1;
  enum MODULE_STATE nState = MSTATE_NEW;
  char* bufReceive;
  int nReceiveBufferSize = 0, nFoundPrompt = PROMPT_UNKNOWN;
  int i = 0;
  sCredentialSet *psCredSet = NULL;
  sConnectParams params;

  psCredSet = malloc( sizeof(sCredentialSet) );
  memset(psCredSet, 0, sizeof(sCredentialSet));

  if (getNextCredSet(_psLogin, psCredSet) == FAILURE)
  {
    writeError(ERR_ERROR, "[%s] Error retrieving next credential set to test.", MODULE_NAME);
    nState = MSTATE_COMPLETE;
  }
  else if (psCredSet->psUser)
  {
    writeError(ERR_DEBUG_MODULE, "[%s] module started for host: %s user: %s", MODULE_NAME, _psLogin->psServer->pHostIP, psCredSet->psUser->pUser);
  }
  else
  {
    writeError(ERR_DEBUG_MODULE, "[%s] module started for host: %s - no more available users to test.", MODULE_NAME);
    nState = MSTATE_COMPLETE;
  }

  memset(&params, 0, sizeof(sConnectParams));
  if (_psLogin->psServer->psAudit->iPortOverride > 0)
    params.nPort = _psLogin->psServer->psAudit->iPortOverride;
  else if (_psLogin->psServer->psHost->iUseSSL > 0)
    params.nPort = PORT_TELNETS;
  else
    params.nPort = PORT_TELNET;
  initConnectionParams(_psLogin, &params);

  while (nState != MSTATE_COMPLETE)
  {
    switch (nState)
    {
    case MSTATE_NEW:
      // Already have an open socket - close it
      if (hSocket > 0)
        medusaDisconnect(hSocket);

      if (_psLogin->psServer->psHost->iUseSSL > 0)
        hSocket = medusaConnectSSL(&params);
      else 
        hSocket = medusaConnect(&params);
      
      if (hSocket <= 0)
      {
        writeError(ERR_ERROR, "[%s] Failed to connect, port %d was not open on %s", MODULE_NAME, params.nPort, _psLogin->psServer->pHostIP);
        _psLogin->iResult = LOGIN_RESULT_UNKNOWN;
        setPassResult(_psLogin, psCredSet->pPass);
        return FAILURE;
      }

      writeError(ERR_DEBUG_MODULE, "Connected");

      // Examine the first line returned
      nReceiveBufferSize = 0;
      bufReceive = medusaReceiveLineDelay(hSocket, &nReceiveBufferSize, RECEIVE_DELAY_1, RECEIVE_DELAY_2);
      if (bufReceive == NULL)
        return FAILURE;

      bufReceive[nReceiveBufferSize] = 0;  // Make certain buffer is null-terminated

      if (bufReceive == NULL)
      {
        writeError(ERR_ERROR, "[%s] null response was unexpected from a telnet server (is one running?)", MODULE_NAME);
        _psLogin->iResult = LOGIN_RESULT_UNKNOWN;
        setPassResult(_psLogin, psCredSet->pPass);
        return FAILURE;
      }

      // Telnet protocol negotiation
      do
      {
        nFoundPrompt = PROMPT_UNKNOWN;
        processIAC(hSocket, _psSessionData, &bufReceive, &nReceiveBufferSize);

        if (bufReceive != NULL && bufReceive[0] != 0 && (unsigned char)bufReceive[0] != IAC)
          makeToLower(bufReceive);

        if (bufReceive != NULL)
        {
          writeError(ERR_DEBUG_MODULE, "Looking for login prompts");

          if (_psSessionData->nMode == MODE_AS400)
          {
            if (strcasestr(bufReceive, (char *)"Sign On") != '\0')
            {
              writeError(ERR_INFO, "[%s] Detected AS/400 Sign On Screen.", MODULE_NAME);
              nFoundPrompt = PROMPT_LOGIN_PASSWORD;
              
              FREE(bufReceive);
              if (medusaDataReadyTimed(hSocket, 0, 20000) > 0)
              {
                // More data waiting
                bufReceive = medusaReceiveLineDelay(hSocket, &nReceiveBufferSize, RECEIVE_DELAY_1, RECEIVE_DELAY_2);
                if (bufReceive != NULL)
                  bufReceive[nReceiveBufferSize] = 0;  // Make certain buffer is null-terminated
              }
 
              break;
            }

            /*
            Sign On
            System  . . . . . :   TSTDBS16
            Subsystem . . . . :   QINTER
            Display . . . . . :   QPADEV0001
            */
          }
          else
          {
            // Look for known login prompts
            for (i = 0; i < KNOWN_LOGIN_SIZE; i++)
            {
              if (strcasestr(bufReceive, KNOWN_LOGIN_PROMPTS[i]) != '\0')
              {
                // Do we have a prompt?
                writeError(ERR_DEBUG_MODULE, "Found login prompt...");
                nFoundPrompt = PROMPT_LOGIN_PASSWORD;
                break;
              }
            }
          
            /* Some systems do not provide a login prompt and go right to password */
            for (i = 0; i < KNOWN_PWD_SIZE; i++)
            {
              if (strcasestr(bufReceive, KNOWN_PWD_PROMPTS[i]) != '\0')
              {
                // Do we have a prompt?
                writeError(ERR_DEBUG_MODULE, "Found a password prompt already...");
                nFoundPrompt = PROMPT_PASSWORD;
                
                if (_psLogin->psServer->iLoginsDone < 1 && _psLogin->iId == 0)
                  writeVerbose(VB_NONE_FILE, "Password Prompt Only: %s\n", _psLogin->psServer->pHostIP);
                
                break;
              }
            }
          
            if (nFoundPrompt == PROMPT_UNKNOWN)
            {
              FREE(bufReceive);
              if (medusaDataReadyTimed(hSocket, 0, 20000) > 0)
              {
                // More data waiting
                bufReceive = medusaReceiveLineDelay(hSocket, &nReceiveBufferSize, RECEIVE_DELAY_1, RECEIVE_DELAY_2);
                if (bufReceive != NULL)
                  bufReceive[nReceiveBufferSize] = 0;  // Make certain buffer is null-terminated
              } 
            }
          }
        }
      }
      while (bufReceive != NULL && (unsigned char)bufReceive[0] == IAC && nFoundPrompt == PROMPT_UNKNOWN);

      FREE(bufReceive);

      if (nFoundPrompt == PROMPT_UNKNOWN)
      {
        writeError(ERR_ERROR, "[%s] Failed to identify logon prompt.", MODULE_NAME); 
        _psLogin->iResult = LOGIN_RESULT_UNKNOWN;
        setPassResult(_psLogin, psCredSet->pPass);
        return FAILURE;
      }
      else
        nState = MSTATE_RUNNING;
      
      break;

    case MSTATE_RUNNING:
      if (_psSessionData->nMode == MODE_AS400)
        nState = tryLoginAS400(hSocket, &_psLogin, _psSessionData, psCredSet->psUser->pUser, psCredSet->pPass);
      else
        nState = tryLogin(hSocket, &_psLogin, _psSessionData, psCredSet->psUser->pUser, psCredSet->pPass, nFoundPrompt);
      
      if (nState != MSTATE_EXITING)
      {
        if (processIAClogout(hSocket, _psSessionData) == FAILURE)
        {
          writeError(ERR_ERROR, "[%s] Failed to close existing Telnet session.", MODULE_NAME);
        }
        medusaDisconnect(hSocket);
        hSocket = -1;
        
        /*
          Cisco devices appear to keep sessions open for a brief time after we terminate 
          the connection. They also seem to ignore "IAC DO LOGOUT" commands. Adding a 
          sleep() hack here, to give them some time to clean-up. 
        */
        sleep(1);

        if (getNextCredSet(_psLogin, psCredSet) == FAILURE)
        {
          writeError(ERR_ERROR, "[%s] Error retrieving next credential set to test.", MODULE_NAME);
          nState = MSTATE_EXITING;
        }
        else
        {
          if (psCredSet->iStatus == CREDENTIAL_DONE)
          {
            writeError(ERR_DEBUG_MODULE, "[%s] No more available credential sets to test.", MODULE_NAME);
            nState = MSTATE_EXITING;
          }
          else if (psCredSet->iStatus == CREDENTIAL_NEW_USER)
          {
            writeError(ERR_DEBUG_MODULE, "[%s] Starting testing for new user: %s.", MODULE_NAME, psCredSet->psUser->pUser);
            nState = MSTATE_NEW;
          }
          else
            writeError(ERR_DEBUG_MODULE, "[%s] Next credential set - user: %s password: %s", MODULE_NAME, psCredSet->psUser->pUser, psCredSet->pPass);
        }
      }
      break;
    case MSTATE_EXITING:
      if (hSocket > 0)
        medusaDisconnect(hSocket);
      hSocket = -1;
      nState = MSTATE_COMPLETE;
      break;
    default:
      writeError(ERR_CRITICAL, "Unknown %s module (%d) state %d host: %s", MODULE_NAME, _psLogin->iId, nState, _psLogin->psServer->pHostIP);
      _psLogin->iResult = LOGIN_RESULT_UNKNOWN;
    }
  }

  FREE(psCredSet);
  return SUCCESS;
}