Rainer Gerhards wrote:
> Hi Tomas,
>
> it's probably the simplest if you post your code so that I can give you the
> relevant hints.
>
> Rainer
>
>   
>> -----Original Message-----
>> From: [email protected] [mailto:rsyslog-
>> [email protected]] On Behalf Of Tomas Kubina
>> Sent: Wednesday, January 13, 2010 12:16 PM
>> To: rsyslog-users
>> Subject: [rsyslog] How to add new configuration option
>>
>> Hi,
>>
>> I would appreciate any help with adding support for a new configuration
>> directive. I have done some
>> code and I need now something like:
>> $AddClientCN [on/off].
>> I have read the sources to find out how rsyslog processes conf file.
>> There is some linked list with
>> known commands. I think that it is enough to add new item to this list
>> but I don't know how.
>> Is this my idea right?
>>
>> Thanks for any help.
>>
>> Regards,
>>
>> Tomas
>>     
>   
Hi Rainer,

the modified files are attached. The alternative code is marked by #if
statement. I had to try to do this modification because the project,
I am interested in, needs to verify client's authentication. I realize 
that the patch is something  like a hack, because the rsyslog's 
architecture doesn't provide this feature (adding client CN to
syslog message) and it is not proper solution, but for our needs it is
enough.
BTW I use this templete:
template ILS_template,"%timegenerated% %fromhost-ip% %HOSTNAME%
%syslogtag%%msg%\n";

I have done a similar code for adding client principal for imgssapi.

Thanks for help.

Regards,

Tomas

FILES:

nsd_gtls.c

static rsRetVal
AcceptConnReq(nsd_t *pNsd, nsd_t **ppNew)
{
        DEFiRet;
        int gnuRet;
        nsd_gtls_t *pNew = NULL;
        nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;

         ISOBJ_TYPE_assert((pThis), nsd_gtls);
        CHKiRet(nsd_gtlsConstruct(&pNew)); // TODO: prevent construct/destruct!
        CHKiRet(nsd_ptcp.Destruct(&pNew->pTcp));
        CHKiRet(nsd_ptcp.AcceptConnReq(pThis->pTcp, &pNew->pTcp));
        
        if(pThis->iMode == 0) {
                /* we are in non-TLS mode, so we are done */
                *ppNew = (nsd_t*) pNew;
                FINALIZE;
        }

        /* if we reach this point, we are in TLS mode */
        CHKiRet(gtlsInitSession(pNew));
        gtlsSetTransportPtr(pNew, ((nsd_ptcp_t*) (pNew->pTcp))->sock);
        pNew->authMode = pThis->authMode;
        pNew->pPermPeers = pThis->pPermPeers;

        /* we now do the handshake. This is a bit complicated, because we are
         * on non-blocking sockets. Usually, the handshake will not complete
         * immediately, so that we need to retry it some time later.
         */
        gnuRet = gnutls_handshake(pNew->sess);
        if(gnuRet == GNUTLS_E_AGAIN || gnuRet == GNUTLS_E_INTERRUPTED) {
                pNew->rtryCall = gtlsRtry_handshake;
                dbgprintf("GnuTLS handshake does not complete immediately - 
setting to 
retry (this is OK and normal)\n");
        } else if(gnuRet == 0) {
                /* we got a handshake, now check authorization */
                CHKiRet(gtlsChkPeerAuth(pNew));
        } else {
                ABORT_FINALIZE(RS_RET_TLS_HANDSHAKE_ERR);
        }

        pNew->iMode = 1; /* this session is now in TLS mode! */
#if 1
         pNew->clientCNValid = 0;
#endif
        *ppNew = (nsd_t*) pNew;

finalize_it:
        if(iRet != RS_RET_OK) {
                if(pNew != NULL)
                        nsd_gtlsDestruct(&pNew);
        }
        RETiRet;
}

static rsRetVal
Rcv(nsd_t *pNsd, uchar *pBuf, ssize_t *pLenBuf)
{
        DEFiRet;
        ssize_t iBytesCopy; /* how many bytes are to be copied to the client 
buffer? */
        nsd_gtls_t *pThis = (nsd_gtls_t*) pNsd;
        ISOBJ_TYPE_assert(pThis, nsd_gtls);
#if 1
         cstr_t *pstrCN = NULL;
         const gnutls_datum *cert_list;
        unsigned int cert_list_size = 0;
         gnutls_x509_crt cert;
         int len = 0;
         char *buf_temp;
#endif
        if(pThis->bAbortConn)
                ABORT_FINALIZE(RS_RET_CONNECTION_ABORTREQ);

        if(pThis->iMode == 0) {
                CHKiRet(nsd_ptcp.Rcv(pThis->pTcp, pBuf, pLenBuf));
                FINALIZE;
        }

        /* --- in TLS mode now --- */

        /* Buffer logic applies only if we are in TLS mode. Here we
         * assume that we will switch from plain to TLS, but never back. This
         * assumption may be unsafe, but it is the model for the time being and 
I
         * do not see any valid reason why we should switch back to plain TCP 
after
         * we were in TLS mode. However, in that case we may lose something that
         * is already in the receive buffer ... risk accepted. -- rgerhards, 
2008-06-23
         */

        if(pThis->pszRcvBuf == NULL) {
                /* we have no buffer, so we need to malloc one */
                CHKmalloc(pThis->pszRcvBuf = MALLOC(NSD_GTLS_MAX_RCVBUF));
                pThis->lenRcvBuf = -1;
        }

        /* now check if we have something in our buffer. If so, we satisfy
         * the request from buffer contents.
         */
        if(pThis->lenRcvBuf == -1) { /* no data present, must read */
                CHKiRet(gtlsRecordRecv(pThis));
        }

        if(pThis->lenRcvBuf == 0) { /* EOS */
                *pLenBuf = 0;
                /* in this case, we also need to free the receive buffer, if we
                 * allocated one. -- rgerhards, 2008-12-03
                 */
                if(pThis->pszRcvBuf != NULL) {
                        free(pThis->pszRcvBuf);
                        pThis->pszRcvBuf = NULL;
                }
                ABORT_FINALIZE(RS_RET_CLOSED);
        }

        /* if we reach this point, data is present in the buffer and must be 
copied */
        iBytesCopy = pThis->lenRcvBuf - pThis->ptrRcvBuf;
        if(iBytesCopy > *pLenBuf) {
                iBytesCopy = *pLenBuf;
        } else {
                pThis->lenRcvBuf = -1; /* buffer will be emptied below */
        }
#if 1
         if (pThis->clientCNValid != 1)
         {
           cert_list = gnutls_certificate_get_peers(pThis->sess, 
&cert_list_size);

          if(cert_list_size > 0)
           {
            // we only print information about the first certificate
            gnutls_x509_crt_init(&cert);
            gnutls_x509_crt_import(cert, &cert_list[0], GNUTLS_X509_FMT_DER);

             CHKiRet(gtlsGetCN(pThis, &cert, &pstrCN));

             len = snprintf(NULL, 0, "CN:%s ", (char*)cstrGetSzStr(pstrCN));
             if ( !(pThis->clientCN = malloc((len + 1)*sizeof(char))) )
               return -1;

             snprintf(pThis->clientCN, len + 1, "CN:%s ", 
(char*)cstrGetSzStr(pstrCN));
             pThis->clientCN[len] = '\0';
             pThis->clientCNLen = len + 1;

             pThis->clientCNValid = 1;
           }
         }

         iBytesCopy = iBytesCopy + pThis->clientCNLen - 1 < *pLenBuf ? 
iBytesCopy + pThis->clientCNLen - 1 : *pLenBuf;

         buf_temp = (char*)malloc(iBytesCopy);

         if (buf_temp)
         {
           memset(buf_temp, 0, iBytesCopy);
           strncpy(buf_temp, pThis->clientCN, pThis->clientCNLen);
           strncat(buf_temp, pThis->pszRcvBuf, pThis->lenRcvBuf);
           buf_temp[iBytesCopy] ='\0';
         }

         memset(pBuf, 0, *pLenBuf);
        memcpy(pBuf, buf_temp, iBytesCopy);

         if (buf_temp)
           free(buf_temp);
#else
         memcpy(pBuf, pThis->pszRcvBuf + pThis->ptrRcvBuf, iBytesCopy);
#endif  
         pThis->ptrRcvBuf += iBytesCopy;
        *pLenBuf = iBytesCopy;

finalize_it:
        dbgprintf("gtlsRcv return. nsd %p, iRet %d, lenRcvBuf %d, ptrRcvBuf 
%d\n", pThis, iRet, pThis->lenRcvBuf, pThis->ptrRcvBuf);
        RETiRet;
}

tcps_sess.c

static rsRetVal
Close(tcps_sess_t *pThis)
{
        DEFiRet;

        ISOBJ_TYPE_assert(pThis, tcps_sess);
        netstrm.Destruct(&pThis->pStrm);
        if(pThis->fromHost != NULL) {
                prop.Destruct(&pThis->fromHost);
        }
        if(pThis->fromHostIP != NULL)
                prop.Destruct(&pThis->fromHostIP);
#if 1
        if(pThis->clientPrincipal != NULL)
                free(pThis->clientPrincipal);
#endif
        RETiRet;
}

tcps_sess.h

/* the tcps_sess object */
struct tcps_sess_s {
        BEGINobjInstance;       /* Data to implement generic object - MUST be 
the 
first data element! */
        tcpsrv_t *pSrv; /* pointer back to my server (e.g. for callbacks) */
        tcpLstnPortList_t *pLstnInfo;   /* pointer back to listener info */
        netstrm_t *pStrm;
        int iMsg;                /* index of next char to store in msg */
        int bAtStrtOfFram;      /* are we at the very beginning of a new frame? 
*/
        enum {
                eAtStrtFram,
                eInOctetCnt,
                eInMsg
        } inputState;           /* our current state */
        int iOctetsRemain;      /* Number of Octets remaining in message */
        TCPFRAMINGMODE eFraming;
        uchar *pMsg;            /* message (fragment) received */
        prop_t *fromHost;       /* host name we received messages from */
        prop_t *fromHostIP;
        void *pUsr;             /* a user-pointer */
#if 1
         char *clientPrincipal;    /* client principal */
         int clientPrincipalLen;
#endif
        rsRetVal (*DoSubmitMessage)(tcps_sess_t*, uchar*, int); /* submit 
message callback */
};


_______________________________________________
rsyslog mailing list
http://lists.adiscon.net/mailman/listinfo/rsyslog
http://www.rsyslog.com

Reply via email to