int initAuthSSL(int hSocket, _MODULE_DATA* _psSessionData) { unsigned char bufSend[BUF_SIZE]; unsigned char* bufReceive = NULL; int nReceiveBufferSize; writeError(ERR_NOTICE, "[%s] Establishing Explicit FTPS (FTP/SSL) session.", MODULE_NAME); memset(bufSend, 0, BUF_SIZE); sprintf((char*)bufSend, "AUTH TLS\r\n"); if (medusaSend(hSocket, bufSend, strlen((char*)bufSend), 0) < 0) { writeError(ERR_ERROR, "[%s] failed: medusaSend was not successful", MODULE_NAME); return FAILURE; } nReceiveBufferSize = 0; if ((medusaReceiveRegex(hSocket, &bufReceive, &nReceiveBufferSize, "^[0-9]{3,3}-.*\r\n[0-9]{3,3} .*\r\n|^[0-9]{3,3} .*\r\n") == FAILURE) || (bufReceive == NULL)) { writeError(ERR_DEBUG_MODULE, "[%s] failed: Server sent unknown or no response. Exiting...", MODULE_NAME); FREE(bufReceive); return FAILURE; } /* 234 Proceed with negotiation. */ if (strncmp((char*)bufReceive, "234 ", 4) == 0) { FREE(bufReceive); if (medusaConnectSocketSSL(_psSessionData->params, hSocket) < 0) { writeError(ERR_ERROR, "[%s] Failed to establish SSL connection.", MODULE_NAME); return FAILURE; } } else { writeError(ERR_ERROR, "[%s] Failed to establish SSL connection. Server sent response: %c%c%c", MODULE_NAME, bufReceive[0], bufReceive[1], bufReceive[2]); return FAILURE; } return SUCCESS; }
/* Module Specific Functions */ int initConnection(_MODULE_DATA *_psSessionData, int hSocket, sConnectParams *params) { unsigned char *bufSend = NULL; unsigned char *bufReceive = NULL; int nReceiveBufferSize = 0; int nSendBufferSize = 0; /* Retrieve IMAP server banner */ if ((medusaReceiveRegex(hSocket, &bufReceive, &nReceiveBufferSize, "\\* OK .*\r\n") == FAILURE) || (bufReceive == NULL)) { writeError(ERR_ERROR, "[%s] Failed to retrieve IMAP server banner. Exiting...", MODULE_NAME); return FAILURE; } else if ((strstr(bufReceive,"* OK ") != NULL)) { writeError(ERR_DEBUG_MODULE, "[%s] Received IMAP server banner: %s", MODULE_NAME, bufReceive); FREE(bufReceive); } else if ((strstr(bufReceive,"* BYE Connection refused") != NULL)) { writeError(ERR_ERROR, "[%s] IMAP server refused connection. Is SSL required?", MODULE_NAME); FREE(bufReceive); return FAILURE; } else { writeError(ERR_ERROR, "[%s] Failed to retrieve IMAP server banner.", MODULE_NAME); FREE(bufReceive); return FAILURE; } /* Request IMAP server capabilities */ writeError(ERR_DEBUG_MODULE, "[%s] Sending IMAP CAPABILITIES request.", MODULE_NAME); nSendBufferSize = strlen(_psSessionData->szTag) + 13; bufSend = malloc(nSendBufferSize + 1); memset(bufSend, 0, nSendBufferSize + 1); sprintf(bufSend, "%s CAPABILITY\r\n", _psSessionData->szTag); if (medusaSend(hSocket, bufSend, strlen(bufSend), 0) < 0) { writeError(ERR_ERROR, "[%s] Failed: medusaSend was not successful", MODULE_NAME); FREE(bufSend); return FAILURE; } FREE(bufSend); nReceiveBufferSize = 0; if ((medusaReceiveRegex(hSocket, &bufReceive, &nReceiveBufferSize, "OK CAPABILITY .*\r\n") == FAILURE) || (bufReceive == NULL)) { writeError(ERR_ERROR, "[%s] Failed: No OK message received for CAPABILITY request.", MODULE_NAME); return FAILURE; } /* If server supports STARTTLS and we are not already within a SSL connection, let's use it. */ if ((params->nUseSSL == 0) && (strstr(bufReceive, "STARTTLS") != NULL)) { FREE(bufReceive); writeError(ERR_DEBUG_MODULE, "[%s] Initiating STARTTLS session.", MODULE_NAME); bufSend = malloc(strlen(_psSessionData->szTag) + 11 + 1); memset(bufSend, 0, strlen(_psSessionData->szTag) + 11 + 1); sprintf(bufSend, "%s STARTTLS\r\n", _psSessionData->szTag); if (medusaSend(hSocket, bufSend, strlen(bufSend), 0) < 0) { writeError(ERR_ERROR, "[%s] failed: medusaSend was not successful", MODULE_NAME); FREE(bufSend); return FAILURE; } FREE(bufSend); nReceiveBufferSize = 0; if ((medusaReceiveRegex(hSocket, &bufReceive, &nReceiveBufferSize, " OK .*\r\n") == FAILURE) || (bufReceive == NULL)) { writeError(ERR_ERROR, "[%s] Failed: No OK message received for STARTTLS request.", MODULE_NAME); return FAILURE; } /* OK Begin TLS negotiation now. */ else { FREE(bufReceive); params->nSSLVersion = 3.1; /* Force the use of TLSv1 */ if (medusaConnectSocketSSL(params, hSocket) < 0) { writeError(ERR_ERROR, "[%s] Failed to establish TLSv1 connection.", MODULE_NAME); return FAILURE; } /* Resend CAPABILITY request as the AUTH types may have changed. */ writeError(ERR_DEBUG_MODULE, "[%s] Sending IMAP CAPABILITIES request.", MODULE_NAME); nSendBufferSize = strlen(_psSessionData->szTag) + 13; bufSend = malloc(nSendBufferSize + 1); memset(bufSend, 0, nSendBufferSize + 1); sprintf(bufSend, "%s CAPABILITY\r\n", _psSessionData->szTag); if (medusaSend(hSocket, bufSend, strlen(bufSend), 0) < 0) { writeError(ERR_ERROR, "[%s] Failed: medusaSend was not successful", MODULE_NAME); FREE(bufSend); return FAILURE; } FREE(bufSend); nReceiveBufferSize = 0; if ((medusaReceiveRegex(hSocket, &bufReceive, &nReceiveBufferSize, "OK CAPABILITY .*\r\n") == FAILURE) || (bufReceive == NULL)) { writeError(ERR_ERROR, "[%s] Failed: No OK message received for CAPABILITY request.", MODULE_NAME); return FAILURE; } } } /* Process IMAP supported authentication types */ if (_psSessionData->nAuthType != AUTH_UNKNOWN) { writeError(ERR_DEBUG_MODULE, "[%s] Ignoring server requested AUTH type and using user-specified value.", MODULE_NAME); } else if ((strstr(bufReceive,"AUTH=LOGIN") != NULL)) { writeError(ERR_DEBUG_MODULE, "Server requested authentication type: LOGIN"); _psSessionData->nAuthType = AUTH_LOGIN; } else if ((strstr(bufReceive,"AUTH=PLAIN") != NULL)) { writeError(ERR_DEBUG_MODULE, "Server requested authentication type: PLAIN"); _psSessionData->nAuthType = AUTH_PLAIN; } else if ((strstr(bufReceive,"AUTH=NTLM") != NULL)) { writeError(ERR_DEBUG_MODULE, "Server requested authentication type: NTLM"); _psSessionData->nAuthType = AUTH_NTLM; } else { writeError(ERR_ERROR, "[%s] Failed: Server did not respond that it supported any of the authentication types we handle (PLAIN, LOGIN, NTLM). Use the AUTH module option to force the use of an authentication type.", MODULE_NAME); return FAILURE; } FREE(bufReceive); return SUCCESS; }
int initModule(sLogin* psLogin, _MODULE_DATA *_psSessionData) { int hSocket = -1; enum MODULE_STATE nState = MSTATE_NEW; unsigned char bufSend[BUF_SIZE]; unsigned char* bufReceive; int nReceiveBufferSize = 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(¶ms, 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_POP3S; else params.nPort = PORT_POP3; initConnectionParams(psLogin, ¶ms); 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(¶ms); else hSocket = medusaConnect(¶ms); if (hSocket < 0) { writeError(ERR_NOTICE, "%s: failed to connect, port %d was not open on %s", MODULE_NAME, params.nPort, psLogin->psServer->pHostIP); psLogin->iResult = LOGIN_RESULT_UNKNOWN; return FAILURE; } /* establish initial connection */ nReceiveBufferSize = 0; if ((medusaReceiveRegex(hSocket, &bufReceive, &nReceiveBufferSize, "\\+OK.*\r\n") == FAILURE) || (bufReceive == NULL)) { writeError(ERR_DEBUG_MODULE, "%s failed: Server did not respond with '+OK'. Exiting...", MODULE_NAME); psLogin->iResult = LOGIN_RESULT_UNKNOWN; nState = MSTATE_EXITING; } else { writeError(ERR_DEBUG_MODULE, "Connected"); nState = MSTATE_RUNNING; } /* POP3 STARTTLS Extension http://www.faqs.org/rfcs/rfc2595.html */ /* The capability name "STLS" indicates this command is present and permitted in the current state. "CAPA" can be used to test for its presence. Are there cases where "STLS" may not be implemented? */ /* Initiate STLS only if we don't already have a SSL connection */ if (psLogin->psServer->psHost->iUseSSL == 0) { memset(bufSend, 0, BUF_SIZE); sprintf(bufSend, "STLS\r\n"); if (medusaSend(hSocket, bufSend, strlen(bufSend), 0) < 0) { writeError(ERR_ERROR, "[%s] failed: medusaSend was not successful", MODULE_NAME); return FAILURE; } nReceiveBufferSize = 0; if (medusaReceiveRegex(hSocket, &bufReceive, &nReceiveBufferSize, "\\+OK.*\r\n|-ERR.*\r\n") == FAILURE) { writeError(ERR_ERROR, "[%s] Failed: Unexpected or no data received: %s", MODULE_NAME, bufReceive); return FAILURE; } /* [SUPPORTED] +OK Begin TLS negotiation / +OK Ready to start TLS [NOT SUPPORTED] +OK STLS completed [ERROR] -ERR Command not permitted when TLS active */ else if (strstr(bufReceive, "+OK") != NULL) { FREE(bufReceive); writeError(ERR_DEBUG_MODULE, "[%s] Starting TLS negotiation.", MODULE_NAME); params.nSSLVersion = 3.1; /* Force the use of TLSv1 */ if (medusaConnectSocketSSL(¶ms, hSocket) < 0) { writeError(ERR_ERROR, "[%s] Failed to establish SSLv3 connection.", MODULE_NAME); return FAILURE; } } else { writeError(ERR_DEBUG_MODULE, "[%s] TLS negotiation not available.", MODULE_NAME); FREE(bufReceive); } } /* Query service for accepted authentication methods */ if (_psSessionData->nAuthType == AUTH_UNKNOWN) { getAuthType(hSocket, _psSessionData); if (_psSessionData->nAuthType == AUTH_UNKNOWN) { psLogin->iResult = LOGIN_RESULT_UNKNOWN; return FAILURE; } } break; case MSTATE_RUNNING: /* The POP3 service may be configured to drop connections after an arbitrary number of failed logon attempts. We will reuse the established connection to send authentication attempts until that disconnect happens. At that point the connection should be reestablished. */ if ( medusaCheckSocket(hSocket) ) { nState = tryLogin(hSocket, &psLogin, _psSessionData, psCredSet->psUser->pUser, psCredSet->pPass); if (psLogin->iResult != LOGIN_RESULT_UNKNOWN) { 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); } } } else { writeError(ERR_NOTICE, "[%s] Socket is no longer valid. Server likely dropped connection. Establishing new session.", MODULE_NAME); nState = MSTATE_NEW; if (hSocket > 0) medusaDisconnect(hSocket); hSocket = -1; } break; case MSTATE_EXITING: if (hSocket > 0) medusaDisconnect(hSocket); hSocket = -1; nState = MSTATE_COMPLETE; break; default: writeError(ERR_CRITICAL, "Unknown %s module state %d", MODULE_NAME, nState); if (hSocket > 0) medusaDisconnect(hSocket); hSocket = -1; psLogin->iResult = LOGIN_RESULT_UNKNOWN; return FAILURE; } } FREE(psCredSet); return SUCCESS; }
int initConnection(_MODULE_DATA *_psSessionData, int hSocket, sConnectParams *params) { unsigned char *bufSend = NULL; unsigned char *bufReceive = NULL; int nReceiveBufferSize = 0; int nSendBufferSize = 0; /* Retrieve SMTP banner */ writeError(ERR_DEBUG_MODULE, "[%s] Retrieving SMTP banner.", MODULE_NAME); nReceiveBufferSize = 0; if ((medusaReceiveRegex(hSocket, &bufReceive, &nReceiveBufferSize, "^220 .*\r\n") == FAILURE) || (bufReceive == NULL)) { writeError(ERR_DEBUG_MODULE, "[%s] failed: Server did not respond with '220'. Exiting...", MODULE_NAME); FREE(bufReceive); return FAILURE; } /* Send greeting to SMTP server */ writeError(ERR_DEBUG_MODULE, "[%s] Sending SMTP EHLO greeting.", MODULE_NAME); nSendBufferSize = 5 + strlen(_psSessionData->szEHLO) + 2; bufSend = malloc(nSendBufferSize + 1); memset(bufSend, 0, nSendBufferSize + 1); sprintf((char *)bufSend, "EHLO %s\r\n", _psSessionData->szEHLO); if (medusaSend(hSocket, bufSend, strlen((char *)bufSend), 0) < 0) { writeError(ERR_ERROR, "[%s] Failed: medusaSend was not successful", MODULE_NAME); FREE(bufSend); return FAILURE; } FREE(bufSend); nReceiveBufferSize = 0; if ((medusaReceiveRegex(hSocket, &bufReceive, &nReceiveBufferSize, "250 .*\r\n") == FAILURE) || (bufReceive == NULL)) { writeError(ERR_ERROR, "[%s] failed: Server did not respond with '250'. Exiting...", MODULE_NAME); FREE(bufReceive); return FAILURE; } /* If server supports STARTTLS and we are not already within a SSL connection, let's use it. */ if ((params->nUseSSL == 0) && (strstr((char *)bufReceive, "STARTTLS") != NULL)) { FREE(bufReceive); writeError(ERR_DEBUG_MODULE, "[%s] Initiating STARTTLS session.", MODULE_NAME); bufSend = malloc(10 + 1); memset(bufSend, 0, 10 + 1); sprintf((char *)bufSend, "STARTTLS\r\n"); if (medusaSend(hSocket, bufSend, strlen((char *)bufSend), 0) < 0) { writeError(ERR_ERROR, "[%s] failed: medusaSend was not successful", MODULE_NAME); FREE(bufSend); return FAILURE; } FREE(bufSend); nReceiveBufferSize = 0; if ((medusaReceiveRegex(hSocket, &bufReceive, &nReceiveBufferSize, "^220 .*\r\n") == FAILURE) || (bufReceive == NULL)) { writeError(ERR_ERROR, "[%s] failed: Server did not respond with '220'. Exiting...", MODULE_NAME); FREE(bufReceive); return FAILURE; } else { FREE(bufReceive); params->nSSLVersion = 3.1; /* Force the use of TLSv1 */ if (medusaConnectSocketSSL(params, hSocket) < 0) { writeError(ERR_ERROR, "[%s] Failed to establish SSLv3 connection.", MODULE_NAME); return FAILURE; } /* Resend EHLO greeting as the AUTH types may have changed. */ writeError(ERR_DEBUG_MODULE, "[%s] Sending SMTP EHLO greeting.", MODULE_NAME); nSendBufferSize = 5 + strlen(_psSessionData->szEHLO) + 2; bufSend = malloc(nSendBufferSize + 1); memset(bufSend, 0, nSendBufferSize + 1); sprintf((char *)bufSend, "EHLO %s\r\n", _psSessionData->szEHLO); if (medusaSend(hSocket, bufSend, strlen((char *)bufSend), 0) < 0) { writeError(ERR_ERROR, "[%s] Failed: medusaSend was not successful", MODULE_NAME); FREE(bufSend); return FAILURE; } FREE(bufSend); nReceiveBufferSize = 0; if ((medusaReceiveRegex(hSocket, &bufReceive, &nReceiveBufferSize, "250 .*\r\n") == FAILURE) || (bufReceive == NULL)) { writeError(ERR_ERROR, "[%s] failed: Server did not respond with '250'. Exiting...", MODULE_NAME); FREE(bufReceive); return FAILURE; } } } /* Process SMTP supported authentication types */ if (_psSessionData->nAuthType != AUTH_UNKNOWN) { writeError(ERR_DEBUG_MODULE, "[%s] Ignoring server requested AUTH type and using user-specified value.", MODULE_NAME); } else if ((strstr((char *)bufReceive, "AUTH=LOGIN") != NULL)) { writeError(ERR_DEBUG_MODULE, "Detected authentication type: LOGIN"); _psSessionData->nAuthType = AUTH_LOGIN; } else if ((strstr((char *)bufReceive, "AUTH=PLAIN") != NULL)) { writeError(ERR_DEBUG_MODULE, "Detected authentication type: PLAIN"); _psSessionData->nAuthType = AUTH_PLAIN; } else if ((strstr((char *)bufReceive, "AUTH ") != NULL)) { if ((strstr((char *)bufReceive, "LOGIN") != NULL)) { writeError(ERR_DEBUG_MODULE, "Detected authentication type: LOGIN"); _psSessionData->nAuthType = AUTH_LOGIN; } else if ((strstr((char *)bufReceive, "PLAIN") != NULL)) { writeError(ERR_DEBUG_MODULE, "Detected authentication type: PLAIN"); _psSessionData->nAuthType = AUTH_PLAIN; } else if ((strstr((char *)bufReceive, "NTLM") != NULL)) { writeError(ERR_DEBUG_MODULE, "Detected authentication type: NTLM"); _psSessionData->nAuthType = AUTH_NTLM; } } else { writeError(ERR_ERROR, "%s failed: Server did not respond that it supported LOGIN, PLAIN or NTLM as an authentication type. Use the AUTH module option to force the use of an authentication type.", MODULE_NAME); return FAILURE; } FREE(bufReceive); return SUCCESS; }