diff options
Diffstat (limited to 'tcpsyslog.c')
-rw-r--r-- | tcpsyslog.c | 187 |
1 files changed, 180 insertions, 7 deletions
diff --git a/tcpsyslog.c b/tcpsyslog.c index d2a4b724..c2591663 100644 --- a/tcpsyslog.c +++ b/tcpsyslog.c @@ -42,10 +42,15 @@ #if HAVE_FCNTL_H #include <fcntl.h> #endif - +#if defined(SYSLOG_INET) && defined(USE_GSSAPI) +#include <gssapi.h> +#endif #include "syslogd.h" #include "syslogd-types.h" #include "net.h" +#if defined(SYSLOG_INET) && defined(USE_GSSAPI) +#include "gss-misc.h" +#endif #include "tcpsyslog.h" /******************************************************************** * ### SYSLOG/TCP CODE ### @@ -71,7 +76,10 @@ int bEnableTCP = 0; /* read-only after startup */ int *sockTCPLstn = NULL; /* read-only after startup, modified by restart */ struct TCPSession *pTCPSessions; /* The thread-safeness of the sesion table is doubtful */ - +#ifdef USE_GSSAPI +static gss_cred_id_t gss_server_creds; +char *gss_listen_service_name = NULL; +#endif /* configure TCP listener settings. This is called during command * line parsing. The argument following -t is supplied as an argument. @@ -155,6 +163,10 @@ static int TCPSessInit(void) pTCPSessions[i].iMsg = 0; /* just make sure... */ pTCPSessions[i].bAtStrtOfFram = 1; /* indicate frame header expected */ pTCPSessions[i].eFraming = TCP_FRAMING_OCTET_STUFFING; /* just make sure... */ +#ifdef USE_GSSAPI + pTCPSessions[i].gss_flags = 0; + pTCPSessions[i].gss_context = GSS_C_NO_CONTEXT; +#endif } return(0); } @@ -215,6 +227,15 @@ void deinit_tcp_listener(void) fd = pTCPSessions[iTCPSess].sock; dbgprintf("Closing TCP Session %d\n", fd); close(fd); + free(pTCPSessions[iTCPSess].fromHost); +#ifdef USE_GSSAPI + if(bEnableTCP == 2) { + OM_uint32 maj_stat, min_stat; + maj_stat = gss_delete_sec_context(&min_stat, &pTCPSessions[iTCPSess].gss_context, GSS_C_NO_BUFFER); + if (maj_stat != GSS_S_COMPLETE) + display_status("deleting context", maj_stat, min_stat); + } +#endif /* now get next... */ iTCPSess = TCPSessGetNxtSess(iTCPSess); } @@ -389,7 +410,7 @@ int *create_tcp_socket(void) * is no more space left in the connection table, the new TCP * connection is immediately dropped. */ -void TCPSessAccept(int fd) +int TCPSessAccept(int fd) { int newConn; int iSess; @@ -403,7 +424,7 @@ void TCPSessAccept(int fd) newConn = accept(fd, (struct sockaddr*) &addr, &addrlen); if (newConn < 0) { logerror("tcp accept, ignoring error and connection request"); - return; + return -1; } /* Add to session list */ @@ -412,7 +433,7 @@ void TCPSessAccept(int fd) errno = 0; logerror("too many tcp sessions - dropping incoming request"); close(newConn); - return; + return -1; } /* OK, we have a "good" index... */ @@ -423,7 +444,7 @@ void TCPSessAccept(int fd) * Error message has been generated by cvthname. */ close (newConn); - return; + return -1; } /* Here we check if a host is permitted to send us @@ -439,7 +460,7 @@ void TCPSessAccept(int fd) (char*)fromHost); } close(newConn); - return; + return -1; } /* OK, we have an allowed sender, so let's continue */ @@ -454,6 +475,7 @@ void TCPSessAccept(int fd) pTCPSessions[iSess].sock = newConn; pTCPSessions[iSess].iMsg = 0; /* init msg buffer! */ + return iSess; } @@ -678,6 +700,157 @@ int TCPSessDataRcvd(int iTCPSess, char *pData, int iLen) } +#ifdef USE_GSSAPI +int TCPSessGSSInit(void) +{ + gss_buffer_desc name_buf; + gss_name_t server_name; + OM_uint32 maj_stat, min_stat; + + name_buf.value = (gss_listen_service_name == NULL) ? "host" : gss_listen_service_name; + name_buf.length = strlen(name_buf.value) + 1; + maj_stat = gss_import_name(&min_stat, &name_buf, GSS_C_NT_HOSTBASED_SERVICE, &server_name); + if (maj_stat != GSS_S_COMPLETE) { + display_status("importing name", maj_stat, min_stat); + return -1; + } + + maj_stat = gss_acquire_cred(&min_stat, server_name, 0, + GSS_C_NULL_OID_SET, GSS_C_ACCEPT, + &gss_server_creds, NULL, NULL); + if (maj_stat != GSS_S_COMPLETE) { + display_status("acquiring credentials", maj_stat, min_stat); + return -1; + } + + gss_release_name(&min_stat, &server_name); + dbgprintf("GSS-API initialized\n"); + return 0; +} + + +int TCPSessGSSAccept(int fd) +{ + gss_buffer_desc send_tok, recv_tok; + gss_name_t client; + gss_OID doid; + OM_uint32 maj_stat, min_stat, acc_sec_min_stat; + int iSess; + gss_ctx_id_t *context; + OM_uint32 *sess_flags; + int fdSess; + + if ((iSess = TCPSessAccept(fd)) == -1) + return -1; + + context = &pTCPSessions[iSess].gss_context; + *context = GSS_C_NO_CONTEXT; + sess_flags = &pTCPSessions[iSess].gss_flags; + fdSess = pTCPSessions[iSess].sock; + + do { + if (recv_token(fdSess, &recv_tok) <= 0) + return -1; + + maj_stat = gss_accept_sec_context(&acc_sec_min_stat, context, gss_server_creds, + &recv_tok, GSS_C_NO_CHANNEL_BINDINGS, &client, + NULL, &send_tok, sess_flags, NULL, NULL); + if (recv_tok.value) { + free(recv_tok.value); + recv_tok.value = NULL; + } + if (send_tok.length != 0) { + if (send_token(fdSess, &send_tok) < 0) { + return -1; + } + + gss_release_buffer(&min_stat, &send_tok); + } + if (maj_stat != GSS_S_COMPLETE + && maj_stat != GSS_S_CONTINUE_NEEDED) { + display_status("accepting context", maj_stat, + acc_sec_min_stat); + if (*context != GSS_C_NO_CONTEXT) + gss_delete_sec_context(&min_stat, context, + GSS_C_NO_BUFFER); + return -1; + } + } while (maj_stat == GSS_S_CONTINUE_NEEDED); + + maj_stat = gss_display_name(&min_stat, client, &recv_tok, NULL); + if (maj_stat != GSS_S_COMPLETE) + display_status("displaying name", maj_stat, min_stat); + gss_release_name(&min_stat, &client); + + dbgprintf("GSS-API Accepted connection from: %s\n", recv_tok.value); + gss_release_buffer(&min_stat, &recv_tok); + + dbgprintf("GSS-API Provided context flags:\n"); + display_ctx_flags(*sess_flags); + + return 0; +} + + +int TCPSessGSSRecv(int iSess, void *buf, size_t buf_len) +{ + gss_buffer_desc xmit_buf, msg_buf; + gss_ctx_id_t *context; + OM_uint32 maj_stat, min_stat; + int fdSess; + int conf_state; + int state, len; + + fdSess = pTCPSessions[iSess].sock; + if ((state = recv_token(fdSess, &xmit_buf)) <= 0) + return state; + + context = &pTCPSessions[iSess].gss_context; + maj_stat = gss_unwrap(&min_stat, *context, &xmit_buf, &msg_buf, + &conf_state, (gss_qop_t *) NULL); + if (maj_stat != GSS_S_COMPLETE) { + display_status("unsealing message", maj_stat, min_stat); + if (xmit_buf.value) { + free(xmit_buf.value); + xmit_buf.value = 0; + } + return (-1); + } + if (xmit_buf.value) { + free(xmit_buf.value); + xmit_buf.value = 0; + } + + len = msg_buf.length < buf_len ? msg_buf.length : buf_len; + memcpy(buf, msg_buf.value, len); + gss_release_buffer(&min_stat, &msg_buf); + + return len; +} + + +void TCPSessGSSClose(int iSess) { + OM_uint32 maj_stat, min_stat; + gss_ctx_id_t *context; + + if(iSess < 0 || iSess > iTCPSessMax) { + errno = 0; + logerror("internal error, trying to close an invalid TCP session!"); + return; + } + + context = &pTCPSessions[iSess].gss_context; + maj_stat = gss_delete_sec_context(&min_stat, context, GSS_C_NO_BUFFER); + if (maj_stat != GSS_S_COMPLETE) + display_status("deleting context", maj_stat, min_stat); + *context = GSS_C_NO_CONTEXT; + pTCPSessions[iSess].gss_flags = 0; + + TCPSessClose(iSess); +} +#endif /* #ifdef USE_GSSAPI */ + + #endif /******************************************************************** * ### END OF SYSLOG/TCP CODE ### |