Thanks for the code. Unfortunately, adding the config switch to it is not
quite easy in that case (good I asked for the actual code). I'd say that you
best do it similar to the other config directives, like the authentication
mode. They actual directives are in the upper level code (imtcp/omfwd).
There, they are shuffled over to the instance data, which goes along with
each of the configured listeners/sender. Then, when a new network stream is
created, the params are passed down to the generic stream interface and there
passed down to the selected stream driver, which finally stores and acts on
them. It's clumpsy and quite some work, but that is what is needed for the
old config system. You probably need to add around 50 to 100 lines of code
altogether to the various files. It's not complex, but easy to forget
something. Best start by a directive (like $..AuthMode), see how it is
handled (and passed down) in imtcp and work your way down the stack ;)

Rainer 

> -----Original Message-----
> From: [email protected] 
> [mailto:[email protected]] On Behalf Of Tomas Kubina
> Sent: Wednesday, January 13, 2010 2:49 PM
> To: rsyslog-users
> Subject: Re: [rsyslog] How to add new configuration option
> 
> 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
> 
_______________________________________________
rsyslog mailing list
http://lists.adiscon.net/mailman/listinfo/rsyslog
http://www.rsyslog.com

Reply via email to