⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 spo_xml.c

📁 入侵检测源代码,参考snort结构编程. 可修改,编译连接.
💻 C
📖 第 1 页 / 共 4 页
字号:
           liberated from: spo_tcpdump.c */
        bzero(timebuf, 10);
        curr_time = time(NULL);
        loc_time = localtime(&curr_time);
        strftime(timebuf, 91, "%m%d@%H%M", loc_time);

        if(d->file[0] != '/')
        {
            bzero(filename, STD_BUF);
            if(chrootdir)
                strncpy(filename, chrootdir, STD_BUF);
            strncat(filename, pv.log_dir, STD_BUF - strlen(filename));
            strncat(filename, "/", 1);
            strncat(filename, d->file, STD_BUF - strlen(filename));
        }
        else
            strncpy(filename, d->file, STD_BUF - strlen(filename));

        strncat(filename, "-", STD_BUF - strlen(filename));      
        strncat(filename, timebuf, STD_BUF - strlen(filename));      

        /* Create unique filename to log to */
        d->fptr = fopen(filename, "w");

        /* Write XML header info */
        fprintf(d->fptr, "%s", SNORTML_DECLARATION);
        fprintf(d->fptr, "%s", SNORTML_DOCTYPE);
        fprintf(d->fptr, "\n%s", SNORTML_FILE_BEGIN);

        if(!d->fptr) FatalError(XMLMOD"logfile (%s) open error (%s)\n", d->file, strerror(errno));

        setvbuf(d->fptr,(char *)NULL, _IOLBF, (size_t)0);
    }
    else if(d->protocol != NULL)
    {
        if(d->host == NULL) FatalError(XMLMOD" can not use the protocol argument without a host argument\n");
    }
    else FatalError(XMLMOD"Invalid configuration options");

#ifdef ENABLE_SSL
    if(d->protocol != NULL)
    {
        if((!strcasecmp(d->protocol, "https")) && (d->client_cert_filename == NULL))
            FatalError(XMLMOD": must specify a certificate ([cert] parameter) when using https (SSL)\n");

        if(!strcasecmp(d->protocol, "https") && d->client_key_filename == NULL)
            FatalError(XMLMOD": must specify a private key ([key] parameter) when using https (SSL)\n");

        if(!strcasecmp(d->protocol, "https") && d->collector_name == NULL)
            FatalError(XMLMOD": must specify a server ([server] parameter) when using https (SSL)\n");

        if(!strcasecmp(d->protocol, "https") && d->issuer_cert == NULL)
            FatalError(XMLMOD": must specify a CA certificate ([ca] parameter) when using https (SSL)\n");

        if((!strcasecmp(d->protocol, "https") || !strcasecmp(d->protocol, "http"))
           && d->file == NULL)
            FatalError(XMLMOD": must specify a remote script ([file] parameter) with http or https\n");
    }
#endif

    return d;
}

/*
 * Function: LogXml(Packet *, char * msg, void * data)
 *
 * Purpose: Generate the XML for a given packet and msg 
 *
 * Arguments: p   => pointer to the current packet data struct 
 *            msg => pointer to the signature message
 *            data => passed in by snort
 *
 * Returns: void function
 *
 */
void LogXml(Packet *p, char *msg, void *arg)
{
    XmlData *d = (XmlData *)arg;

#ifdef ENABLE_SNORT_TIMING
    SNORT_TIME_MARK_START(packet_cnt);
#endif

    /* if (logging to a file) */
    if((d->host == NULL) && (!d->port) && (d->protocol == NULL))
        d->root = snml(d, p, msg);
    else
        addtag(d->root, snml(d, p, msg));

    d->count++;

    if(d->count >= MAX_QUEUE)
    {
        send_data(d);
        flush_data(d);
    }

#ifdef ENABLE_SNORT_TIMING
    /* #6 : Final Clean-up */
    SNORT_TIME_MARK();
    SNORT_TIME_MARK_END();
#endif
}

/*
 * Function: send_data(XmlData * data)
 *
 * Purpose: Write data to a file or over the network
 *
 * Arguments: data => pointer to an XmlData struct
 *
 * Returns: void function
 *
 */
void send_data(XmlData *d)
{
    char * output;
    char * ptr;
    int indent = 0;

    /* if d->root is empty there is nothing really to send */
    if(d->root == NULL)
        return;

    /* Turn the data into a string */
    output = (char *)malloc(MAX_ALERT_SIZE * (MAX_QUEUE + 2)); 
    ptr = output;

    /* Don't add the SNORTML header if logging to a file */
    if(!( (d->host == NULL) || (!d->port) || (d->protocol == NULL) ))
    {
        strncpy(ptr, SNORTML_DECLARATION, strlen(SNORTML_DECLARATION) + 1);
        strncat(ptr, SNORTML_DOCTYPE, strlen(SNORTML_DOCTYPE) + 1);

        ptr += strlen(SNORTML_DOCTYPE) + strlen(SNORTML_DECLARATION);
    }
    else
        indent = INDENT;

    ptr = tag2string(ptr, MAX_ALERT_SIZE * (MAX_QUEUE + 1), d->root, indent);
    strncat(ptr, "\n", 1);

    /* Write the XML to a file or send it over the network */
    if((d->host == NULL) || (!d->port) || (d->protocol == NULL))
    {
        fprintf(d->fptr, "%s", output);
        /*fflush(d->fptr);*/
    }
    else
    {
#ifdef ENABLE_SNORT_TIMING
        /* #1 : Client Alert Processing Time => Make XML */
        SNORT_TIME_MARK();
#endif
        /* send it over the network */
        send_data_network(d, output);
    }
    free(output); 
}

#ifdef ENABLE_SSL

void init_snort_ssl_ctx(XmlData *d)
/* Initializes an TLSv1 context */
{
    int err;

    SSLeay_add_ssl_algorithms();
    /* d->meth = SSLv2_client_method(); */
    /* d->meth = SSLv3_client_method(); */
    d->meth = TLSv1_client_method();
    SSL_load_error_strings();

    d->ctx = SSL_CTX_new (d->meth);
    CHK_NULL(d->ctx, XMLMOD_SSL": could not get a SSL context");

    SSL_CTX_set_verify(d->ctx, SSL_VERIFY_PEER, CertVerifyCB);
    SSL_CTX_set_default_verify_paths(d->ctx);

    if(! SSL_CTX_load_verify_locations(d->ctx, d->issuer_filename, NULL))
    {
        ErrorMessage(XMLMOD": Could not load the CA chain");
        return;
    }
    SSL_CTX_set_client_CA_list(d->ctx,SSL_load_client_CA_file(d->issuer_filename));

    /* inits Client Authentication parameters; sets the certificate and key */
    err = SSL_CTX_use_certificate_file (d->ctx, d->client_cert_filename, SSL_FILETYPE_PEM);
    CHK_NULL(err, XMLMOD_SSL": invalid client certificate specified in config");

    err = SSL_CTX_use_PrivateKey_file(d->ctx, d->client_key_filename, SSL_FILETYPE_PEM);
    CHK_NULL(err, XMLMOD_SSL": invalid client private key specified in config");

    SSL_CTX_set_session_cache_mode(d->ctx, SSL_SESS_CACHE_CLIENT);
    return;

    end:
    X509_free(d->issuer_cert);
    SSL_CTX_free (d->ctx);

    exit(-1);
}

int CertVerifyCB (int ok, X509_STORE_CTX *ctx)
{
    int errnum;

    errnum   = X509_STORE_CTX_get_error(ctx);
    if(errnum != X509_V_OK)
        ErrorMessage(XMLMOD": Authentication Error: CB : #%d : %s\n", errnum, X509_verify_cert_error_string(errnum));

    return 1;
}

EVP_PKEY * load_key(char *key_fname)
/* Loads a PEM encoded RSA Private key from disk into memory */
{
    BIO *in;
    EVP_PKEY *x=NULL;

    in=BIO_new(BIO_s_file_internal());

    if((in == NULL))
        goto error;

    if(!BIO_read_filename(in, key_fname))
        goto error;

    PEM_read_bio_PrivateKey(in,&x,NULL,NULL);

    error:
    BIO_free(in);

    return(x);
}

X509 * load_crt(char *ca_fname)
/* Loads a PEM encoded .CRT file from disk into memory */
{
    BIO *in;
    X509 *x=NULL;

    in=BIO_new(BIO_s_file_internal());

    if((in == NULL))
        goto error;

    if(!BIO_read_filename(in, ca_fname))
        goto error;

    PEM_read_bio_X509(in,&x,NULL,NULL);

    error:
    BIO_free(in);

    return(x);
}

int VerifyServerCertificate(X509 *current, char *valid_server, X509 *issuer)
/* Validates a certificate based on an issuer certificate. 
  
   By the time this routine is called SSLeay has ensure us that
   the 'current' certificate is signed by _our_ CA.  Therefore,
   we know that the server response at least came from inside our
   community of users.  The question now is whether:
   1. The integrity of the certificate is intact

   2. (TODO) The certificate has not expired or being used before 
      it is valid

   3. (TODO) Some notion of a CRL

   4. The server/user is a valid entity with which to communicate.
*/
{
    char *ascii_cert = NULL;
    int status = X509_V_OK;
    EVP_PKEY *issuer_pkey = NULL;

    /* Get the public key of the issuer (CA) */
    if((issuer_pkey = X509_get_pubkey(issuer)) == NULL)
        status = X509_V_ERR_UNABLE_TO_DECODE_ISSUER_PUBLIC_KEY;
    else
        /* Use the Issuer public key to validate the integrity 
           of the server's certificate */
        if(X509_verify(current, issuer_pkey) <= 0)
        status = X509_V_ERR_CERT_SIGNATURE_FAILURE;
    else
    {
        ascii_cert = X509_NAME_oneline (X509_get_subject_name (current),0,0);

        if(strcmp(ascii_cert, valid_server) != 0)
            status = X509_V_ERR_APPLICATION_VERIFICATION;
#ifdef DEBUG
        printf("Comparing to the expected server'%s' ?= to '%s'\n", 
               valid_server, ascii_cert);
#endif
    }

    EVP_PKEY_free(issuer_pkey);
    free(ascii_cert);

    return status;
}

#endif

void BrokenNetConnection(int signal)
{
    ErrorMessage(XMLMOD" : Remote connection terminated during logging. Alert dropped!\n");
}

void send_data_network(XmlData *d, char *output)
/* Sends the XML-formatted Snort output onto the wire: TCP socket, 
   HTTP, HTTPS
 */
{
#define POST_header_MAX 500

    /* socket data structures */
    struct sockaddr_in remote;
    int err;

    char POST_header[POST_header_MAX],
    *report = NULL;

#ifdef ENABLE_SSL
    /* int sent; */
    /* SSL connection data structures */
    SSL        *ssl = NULL;             /* particular ssl connection */
    X509       *server_cert;            /* X.509 certificate of server */

    /* SSL temporary */
#ifdef DEBUG
    char *ascii_cert_subject, 
    *ascii_cert_issuer;            /* ASCII text of X.509 certificate */
#endif
    SSLServerResponse *response = NULL; /* response codes of the mod_snort server */
    int  success_ssl_connect = 0;

#endif

    /* POST temporary variables */
    char rbuf[4096];                    /* raw HTTP server response */
    char content_line[25];              /* HTTP hdr: Content-Length: */
    char *script = NULL;                /* remote script to be executed */

    /* Catch all the empty alerts triggered by abnormal Snort termination */
    if(strstr(output, EMPTY_ALERT))
        return;

    ++packet_cnt;
    /* Open an socket connection */
    d->sk = socket(AF_INET,SOCK_STREAM,0);
    if(d->sk < 0)
    {
        ErrorMessage(XMLMOD" #%u : could not open connection to %s:%d."
                     "(socket - error #%d)\n",
                     packet_cnt, d->host, d->port, errno);
#ifdef ENABLE_SSL
        LogSSLMessage(d->ssl_trace, "Could not open connection (socket() fail)",
                      "<not stored>", "<not stored>", packet_cnt, d->protocol, d->host, d->port, script);
#endif

        return;
    }

    remote.sin_family=AF_INET;
    bcopy( d->host_ipaddr->h_addr,(char*)&remote.sin_addr, d->host_ipaddr->h_length);
    remote.sin_port= htons((unsigned short)d->port); 
    err = connect(d->sk,(struct sockaddr *)&remote,sizeof(remote));

    if(err != 0)
    {
        if(errno == 111)
            ErrorMessage(XMLMOD" #%u: Connection refused. No server found at %s:%d\n",
                         packet_cnt, d->host, d->port);
        else
            ErrorMessage(XMLMOD" #%u : could not open connection to %s:%d."
                         "(connect - error #%d)\n", 
                         packet_cnt, d->host, d->port, errno);
#ifdef ENABLE_SSL
        if(errno == 111)
            LogSSLMessage(d->ssl_trace, "Connection refused (connect() fail)",
                          "<not stored>", "<not stored>", packet_cnt, d->protocol, d->host, d->port, script);
        else
            LogSSLMessage(d->ssl_trace, "Could not open connection (connect() fail)",
                          "<not stored>", "<not stored>", packet_cnt, d->protocol, d->host, d->port, script);
#endif

        close(d->sk);
        return;
    }

#ifdef ENABLE_SSL
    /* Configure the socket to do SSL if neccessary */
    if(!strcasecmp(d->protocol, "https"))
    {     
        /* Allocate a new SSL connection */
        ssl = SSL_new (d->ctx);
        CHK_NULL(ssl, XMLMOD_SSL": Could not alloc an SSL structure\n");              
        SSL_set_fd (ssl, d->sk);           /* associate a file-desc with SSL */

#ifdef ENABLE_SESSION_RESUME
        /* Re-use (if had one) the previous session whereby preventing _very_ expensive 
         * crypto operations */
        if(d->session)
            if(!SSL_set_session(ssl, d->session))
            {
                /* had an error, most likely the cache has expired. So lets flag
                 * the d->session as NULL so that the newly negotiated session
                 * is saved 
                 */
                printf("Session Dropped from cache already\n");
                d->session = NULL;
            }
#endif

        err = SSL_connect (ssl);           /* connect() */
        CHK_SSL(err, XMLMOD_SSL": Could not open SSL connection (SSL_connect())");

#ifdef ENABLE_SESSION_RESUME
        /* If this is the first SSL_connect()/session, save the session */
        if(!d->session)
            d->session = SSL_get_session(ssl);
#endif

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -