📄 spo_xml.c
字号:
success_ssl_connect = 1;
#ifdef DEBUG
fprintf(stdout, " over SSL using [%s]\n", SSL_get_cipher(ssl)); fflush(0);
#endif
#ifdef ENABLE_SNORT_TIMING
/* #2 : SSL Connection Setup Time */
SNORT_TIME_MARK();
#endif
/* Server Authentication - Get the Server's certificate */
server_cert = SSL_get_peer_certificate (ssl);
CHK_NULL(server_cert, XMLMOD_SSL": Null Server certificate\n");
#ifdef DEBUG
ascii_cert_subject = X509_NAME_oneline (X509_get_subject_name (server_cert),0,0);
CHK_NULL(ascii_cert_subject, XMLMOD_SSL": Could not parse the server certificate:subject");
ascii_cert_issuer = X509_NAME_oneline (X509_get_issuer_name (server_cert),0,0);
CHK_NULL(ascii_cert_issuer, XMLMOD_SSL": Could not parse the server certificate:issuer");
printf ("Server certificate: \n");
printf (" [subject]: %s\n", ascii_cert_subject);
printf (" [issuer]: %s\n", ascii_cert_issuer);
free (ascii_cert_subject);
free (ascii_cert_issuer);
#endif
/* Validate the Server Certificate
By this point, SSLeay has given me a callback via CertVerifyCB()
on the following concerns:
- Issuer of the server certificate is the one specified
Now we must verify :
- the integrity certificate
- the expiration dates
- NO CRL is used
- we actually want to speak to _this_ particular server.
*/
if((err = VerifyServerCertificate(server_cert, d->collector_name, d->issuer_cert )) != X509_V_OK)
{
if(err == X509_V_ERR_APPLICATION_VERIFICATION)
ErrorMessage(XMLMOD": #%u : Authentication Error: "
"The CN in the server certificate does not match the valid server name\n",
packet_cnt);
else
ErrorMessage(XMLMOD": #%u : Authentication Error #%d : %s\n",
packet_cnt, err, X509_verify_cert_error_string(err));
goto end;
}
#ifdef DEBUG
else
printf(XMLMOD": Authentication OK - (%d)\n", err);
#endif
X509_free (server_cert);
}
#endif
#ifdef ENABLE_SNORT_TIMING
/* #3 : SSL Peer Server Authentication Time */
SNORT_TIME_MARK();
#endif
if(!strcasecmp(d->protocol, "http") || !strcasecmp(d->protocol, "https"))
{
script = (char *) malloc (strlen(d->file)+2);
if(d->file[0] != '/')
{
strcpy(script, "/");
strcat(script, d->file);
}
else
strcpy(script, d->file);
}
/* Create POST preamble/header information */
if(!strcasecmp(d->protocol, "http") || !strcasecmp(d->protocol, "https"))
{
sprintf(content_line, "Content-Length: %d\n", (int) strlen(output)+1);
snprintf(POST_header, POST_header_MAX, "%s%s%s%s%s\n",
POST_HDR, script, HTTP_VERSION, CONTENT_TYPE, content_line);
report = (char *) malloc(strlen(POST_header) + strlen(output) + 2);
sprintf(report, "%s%s\n", POST_header, output);
}
#ifdef DEBUG
printf("=======================\n%s\n=============================\n", output);
#endif
/* Write data on the wire */
if(!strcasecmp(d->protocol, "tcp"))
{
err = write(d->sk, output, strlen(output));
CHK_POS(err, XMLMOD": error sending Alert over TCP");
}
else if(!strcasecmp(d->protocol, "http"))
{
err = write(d->sk, report, strlen(report));
CHK_POS(err, XMLMOD": error sending Alert over HTTP");
}
#ifdef ENABLE_SSL
else if(!strcasecmp(d->protocol, "https"))
{
err = SSL_write (ssl, report, strlen(report));
CHK_SSL(err, XMLMOD_SSL": error sending Alert over HTTPS");
}
#endif
/* Get the server response to the POST.
* There is the underlying assumption that this response all fits in a 4K buffer.
*/
if(!strcasecmp(d->protocol, "http"))
err = read(d->sk, rbuf, 4096);
#ifdef ENABLE_SSL
else if(!strcasecmp(d->protocol, "https"))
err = SSL_read(ssl, rbuf, 4096);
#endif
/* Process the Server response to POST */
if(!strcasecmp(d->protocol, "http") || !strcasecmp(d->protocol, "https"))
{
rbuf[err] = '\0';
/* Verify that got some response from the server. No response
usually indicates that we were not communicating with an
HTTP server */
if(rbuf[0] == 0)
{
ErrorMessage(XMLMOD": #%u : no acknowledgement to the POSTed alert on '%s://%s:%d%s'.\n",
packet_cnt, d->protocol, d->host, d->port, script);
#ifdef ENABLE_SSL
LogSSLMessage(d->ssl_trace, "No Acknowledgement to POSTed alert",
output, "", packet_cnt, d->protocol, d->host, d->port, script);
#endif
goto end;
}
#ifdef DEBUG
printf("\n%s\n", rbuf);
#endif
/* Check that didn't get a HTTP related error */
if(!( !strncasecmp(rbuf, HTTP_1_0_OK, strlen(HTTP_1_0_OK)) ||
!strncasecmp(rbuf, HTTP_1_1_OK, strlen(HTTP_1_1_OK)) ))
{
ErrorMessage(XMLMOD": #%u : an HTTP server related error occured :\n"
"===========\n%s==========\n", packet_cnt, rbuf);
#ifdef ENABLE_SSL
LogSSLMessage(d->ssl_trace, "HTTP server related error occured",
output, rbuf, packet_cnt, d->protocol, d->host, d->port, script);
#endif
goto end;
}
#ifdef ENABLE_SSL
else if(!strcasecmp(d->protocol, "https"))
{
response = ProcessSSLServerResponse(rbuf);
if(!response->malformed)
{
printf("#%u - SERVER SENT: (%d alerts parsed)\n"
" o Auth=%s | Throttle=%s | Parser=%s\n",
packet_cnt, response->num_commit,
https_return_messages[response->auth],
https_return_messages[response->throttle],
https_return_messages[response->commit]);
}
else
{
printf("SERVER SENT\n [malformed response received from server]\n");
LogSSLMessage(d->ssl_trace, "Malformed response recieved from server",
output, rbuf, packet_cnt, d->protocol, d->host, d->port, script);
#ifdef DEBUG
printf("%s\n", rbuf);
#endif
}
++success_ssl_connect;
}
#endif
}
end:
#ifdef ENABLE_SNORT_TIMING
/* #4 : Get and Processes server response */
SNORT_TIME_MARK();
#endif
/* Close the connections */
#ifdef ENABLE_SSL
if(!strcasecmp(d->protocol, "https") && success_ssl_connect)
SSL_shutdown (ssl);
else
#endif
shutdown(d->sk, 2);
free(script);
free(report);
close(d->sk);
#ifdef ENABLE_SSL
free(response);
if(!strcasecmp(d->protocol, "https"))
{
SSL_free (ssl);
#ifndef ENABLE_SESSION_RESUME
SSL_CTX_free (d->ctx);
#else
/* Clear SSL cache if a successful SSL connection didn't occur.
* Should a network error occur between the sensor and collector,
* clearing the cache forces a full SSL key re-negotiation. This
* is neccessary to prevent an expired key from sitting in the
* cache and being used repeatedly by the client, despite the
* fact that it is no longer valid since the server may have
* dumped his cache (e.g. due to a restart).
*/
if(success_ssl_connect != 2)
d->session = NULL;
#endif
}
#endif
#ifdef DEBUG
fprintf(stdout, "Closed the session on %s:%d\n", d->host, d->port);
#endif
#ifdef ENABLE_SNORT_TIMING
/* #5 : Network Cleanup time */
SNORT_TIME_MARK();
#endif
}
#ifdef ENABLE_SSL
void LogSSLMessage(FILE *ssl_trace, char *msg, char *output, char *server, unsigned int packet_cnt,
char *protocol, char *host, unsigned int port, char *script)
{
char str_time[30];
time_t when;
if(ssl_trace > 0)
{
time(&when);
strftime (str_time, sizeof(str_time)-1, "%Y-%m-%d %H:%M:%S", localtime(&when));
fprintf(ssl_trace, "===============================================================\n"
"[%s] %s\n"
"#%u - '%s://%s:%d%s'\n\n"
"---------------------------------------------------------------\n"
"%s\n"
"---------------------------------------------------------------\n"
"%s\n",
str_time, msg, packet_cnt, protocol, host, port, script, output, server);
fflush(0);
}
}
SSLServerResponse * ProcessSSLServerResponse(char *rbuf)
{
SSLServerResponse *r;
char *t, *t2, *error_ptr = NULL;
int i;
r = (SSLServerResponse *) malloc ( sizeof(SSLServerResponse) );
if(!strstr(rbuf, "200 OK"))
r->malformed = 1;
else
{
r->malformed = 0;
/* Get Authentication Information */
r->auth = 0;
for(i = snort_return_msg_index(AUTH_CLIENT_OK);
i <= snort_return_msg_index(AUTH_CLIENT_IGNORED); i++)
{
if(strstr(rbuf, https_return_messages[i]))
{
r->auth = i;
break;
}
}
#ifdef DEBUG
printf("auth = %d ", r->auth);
#endif
/* If server has not authenticated us, no throttle or
* input is checked
*/
if(r->auth != snort_return_msg_index(AUTH_CLIENT_OK))
{
r->throttle = snort_return_msg_index(THROTTLE_IGNORED);
r->commit = snort_return_msg_index(INPUT_IGNORED);
r->num_commit = 0;
return r;
}
/* Get Throttle Information */
r->throttle = 0;
for(i = snort_return_msg_index(THROTTLE_OK);
i <= snort_return_msg_index(THROTTLE_IGNORED); i++)
if(strstr(rbuf, https_return_messages[i]))
{
r->throttle = i;
break;
}
#ifdef DEBUG
printf("throttle = %d ", r->throttle);
#endif
/* If server has quench our stream, it has ignored our input */
if(r->throttle == snort_return_msg_index(THROTTLE_QUENCH))
{
r->commit = snort_return_msg_index(INPUT_IGNORED);
r->num_commit = 0;
return r;
}
/* Get Parsing Information */
r->commit = 0;
for(i = snort_return_msg_index(INPUT_COMMIT_OK);
i <= snort_return_msg_index(INPUT_IGNORED); i++)
if(strstr(rbuf, https_return_messages[i]))
{
r->commit = i;
break;
}
t = strstr(rbuf, https_return_messages[snort_return_msg_index(INPUT_COMMIT_OK)]);
if(t)
{
/* break apart the string '### INPUT_COMMIT_OK (#)' */
t2 = (char *) malloc ( strlen(t) + 1);
strcpy(t2, t);
strtok(t2, "("); /* eats '### INPUT_COMMIT_OK (' */
r->num_commit = strtol(strtok(NULL, ")"), &error_ptr, 10);
/* If could not get the number commited return malformed */
if(*error_ptr)
r->malformed = 1;
free(t2);
}
else
r->num_commit = 0;
}
#ifdef DEBUG
printf("commit = %d\n", r->commit);
#endif
if(!r->throttle || !r->auth)
r->malformed = 1;
return r;
}
int snort_return_msg_index(int msg_code)
{
int index = 0;
if(msg_code >= 200 && msg_code < 300)
index += msg_code - 200;
if(msg_code >= 300 && msg_code < 400)
index += msg_code - 300 + SNORT_RETURN_MSG_200;
if(msg_code >= 400 && msg_code < 500)
index += msg_code - 400 + SNORT_RETURN_MSG_200 + SNORT_RETURN_MSG_300;
if(msg_code >= 500 && msg_code < 600)
index += msg_code - 500 + SNORT_RETURN_MSG_200
+ SNORT_RETURN_MSG_300 + SNORT_RETURN_MSG_400;
return index;
}
#endif
int srcSanitized(XmlData *d, Packet *p)
{
/*IPNode * tmp = d->sroot;*/
IpAddrSet *tmp = d->sroot;
while(tmp)
{
if(p)
{
if(CheckAddrPort(tmp, 0, 0, p, ANY_SRC_PORT, CHECK_SRC))
return 1;
}
tmp = tmp->next;
}
return 0;
}
int dstSanitized(XmlData *d, Packet *p)
{
/* IPNode * tmp = d->sroot;*/
IpAddrSet *tmp = d->sroot;
while(tmp)
{
if(p)
{
if(CheckAddrPort(tmp, 0, 0, p, ANY_DST_PORT, CHECK_DST))
return 1;
}
tmp = tmp->next;
}
return 0;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -