Initial "gts1" commit.
[tac_plus.git] / packet.c
index f3f7023..30f5a2c 100644 (file)
--- a/packet.c
+++ b/packet.c
@@ -1,4 +1,4 @@
-/* 
+/*
    Copyright (c) 1995-1998 by Cisco systems, Inc.
 
    Permission to use, copy, modify, and distribute this software for
    FITNESS FOR A PARTICULAR PURPOSE.
 */
 
+
 #include "tac_plus.h"
 
+#include <stdlib.h>
+#include <netinet/in.h>                /* for ntohl() */
+#include <errno.h>
+#include <time.h>
+#ifdef HAVE_SYS_TIME_H
+#include <sys/time.h>
+#endif
+#include <sys/types.h>
+#ifdef HAVE_UNISTD_H
+#include <unistd.h>
+#endif
+
+#include "packet.h"
+#include "utils.h"
+#include "report.h"
+#include "dump.h"
+#include "cfgfile.h"
+#include "encrypt.h"
+#include "main.h"
+#include "do_author.h"
+
+
+static int write_packet TAC_ARGS((u_char *pak));
+
+
+/* Configurable:
+ */
+
+#define TAC_PLUS_READ_TIMEOUT          180     /* seconds */
+#define TAC_PLUS_WRITE_TIMEOUT         180     /* seconds */
+
+
 /* Everything to do with reading and writing packets */
 
+void send_acct_reply TAC_ARGS((unsigned status, const char *msg, const char *data));
+
 /* send an accounting response packet */
+void
 send_acct_reply(status, msg, data)
-    u_char status;
-    char *msg, *data;
+unsigned status;                       /* promoted "u_char" type */
+const char *msg;
+const char *data;
 {
     u_char *pak, *p;
     HDR *hdr;
@@ -73,13 +110,16 @@ send_acct_reply(status, msg, data)
     free(pak);
 }
 
+void send_author_reply TAC_ARGS((unsigned status, const char *msg, const char *data, int arg_cnt, /* const */ char **args));
+
 /* send an authorization reply packet */
+void
 send_author_reply(status, msg, data, arg_cnt, args)
-u_char status;
-char *msg;
-char *data;
+unsigned status;                       /* promoted "u_char" type */
+const char *msg;
+const char *data;
 int arg_cnt;
-char **args;
+/* const */ char **args;
 {
     u_char *pak, *p;
     HDR *hdr;
@@ -145,9 +185,9 @@ char **args;
     if (debug & DEBUG_PACKET_FLAG) {
        report(LOG_DEBUG, "Writing %s size=%d",
               summarise_outgoing_packet_type(pak), len);
-       dump_tacacs_pak(pak); 
+       dump_tacacs_pak(pak);
     }
-    
+
     reply->msg_len  = htons(reply->msg_len);
     reply->data_len = htons(reply->data_len);
 
@@ -159,8 +199,11 @@ char **args;
 /* Send an authentication reply packet indicating an error has
    occurred. msg is a null terminated character string */
 
+void send_authen_error TAC_ARGS((const char *msg));
+
+void
 send_authen_error(msg)
-char *msg;
+const char *msg;
 {
     char buf[255];
 
@@ -176,13 +219,16 @@ char *msg;
 
 /* create and send an authentication reply packet from tacacs+ to a NAS */
 
+void send_authen_reply TAC_ARGS((int status, const char *msg, unsigned msg_len, const unsigned char *data, unsigned data_len, unsigned flags));
+
+void
 send_authen_reply(status, msg, msg_len, data, data_len, flags)
 int status;
-char *msg;
-u_short msg_len;
-char *data;
-u_short data_len;
-u_char flags;
+const char *msg;
+unsigned msg_len;                      /* promoted "u_short" type */
+const unsigned char *data;
+unsigned data_len;                     /* promoted "u_short" type */
+unsigned flags;                                /* promoted "u_char" type */
 {
     u_char *pak, *p;
     HDR *hdr;
@@ -228,12 +274,14 @@ u_char flags;
 }
 
 
+u_char *get_authen_continue TAC_ARGS((void));
+
 /* read an authentication GETDATA packet from a NAS. Return 0 on failure */
 u_char *
 get_authen_continue()
 {
     HDR *hdr;
-    u_char *pak, *read_packet();
+    u_char *pak;
     struct authen_cont *cont;
     char msg[255];
 
@@ -255,10 +303,10 @@ get_authen_continue()
     cont->user_msg_len  = ntohs(cont->user_msg_len);
     cont->user_data_len = ntohs(cont->user_data_len);
 
-    if (TAC_AUTHEN_CONT_FIXED_FIELDS_SIZE + 
-       cont->user_msg_len + 
-       cont->user_data_len !=
-       ntohl(hdr->datalength)) {
+    if ((unsigned long)(TAC_AUTHEN_CONT_FIXED_FIELDS_SIZE +
+       cont->user_msg_len +
+       cont->user_data_len) !=
+       (unsigned long) ntohl(hdr->datalength)) {
        char *m = "Illegally sized authentication cont packet";
        report(LOG_ERR, "%s: %s", session.peer, m);
        send_authen_error(m);
@@ -278,7 +326,9 @@ get_authen_continue()
  * Return -1 on error, eof or timeout. Otherwise return number of
  * bytes read. */
 
-int
+static int sockread TAC_ARGS((int fd, u_char *ptr, int nbytes, int timeout));
+
+static int
 sockread(fd, ptr, nbytes, timeout)
 int fd;
 u_char *ptr;
@@ -301,7 +351,7 @@ int timeout;
     nleft = nbytes;
 
     while (nleft > 0) {
-       int status = select(fd + 1, &readfds, (fd_set *) NULL, 
+       int status = select(fd + 1, &readfds, (fd_set *) NULL,
                            &exceptfds, &tout);
 
        if (status == 0) {
@@ -311,7 +361,7 @@ int timeout;
        if (status < 0) {
            if (errno == EINTR)
                continue;
-           report(LOG_DEBUG, "%s: error in select %s fd %d", 
+           report(LOG_DEBUG, "%s: error in select %s fd %d",
                   session.peer, sys_errlist[errno], fd);
            return (-1);
        }
@@ -331,17 +381,17 @@ int timeout;
        if (nread < 0) {
            if (errno == EINTR)
                goto again;
-           report(LOG_DEBUG, "%s %s: error reading fd %d nread=%d %s", 
+           report(LOG_DEBUG, "%s %s: error reading fd %d nread=%d %s",
                   session.peer, session.port, fd, nread, sys_errlist[errno]);
            return (-1);        /* error */
 
        } else if (nread == 0) {
-           report(LOG_DEBUG, "%s %s: fd %d eof (connection closed)", 
+           report(LOG_DEBUG, "%s %s: fd %d eof (connection closed)",
                   session.peer, session.port, fd);
            return (-1);        /* eof */
        }
        nleft -= nread;
-       if (nleft) 
+       if (nleft)
            ptr += nread;
     }
     return (nbytes - nleft);
@@ -354,7 +404,9 @@ int timeout;
  * Return -1 on error, eof or timeout. Otherwise return number of
  * bytes written. */
 
-int
+static int sockwrite TAC_ARGS((int fd, u_char *ptr, int bytes, int timeout));
+
+static int
 sockwrite(fd, ptr, bytes, timeout)
 int fd;
 u_char *ptr;
@@ -379,16 +431,16 @@ int timeout;
     remaining = bytes;
 
     while (remaining > 0) {
-       int status = select(fd + 1, (fd_set *) NULL, 
+       int status = select(fd + 1, (fd_set *) NULL,
                            &writefds, &exceptfds, &tout);
 
        if (status == 0) {
-           report(LOG_DEBUG, "%s: timeout writing to fd %d", 
+           report(LOG_DEBUG, "%s: timeout writing to fd %d",
                   session.peer, fd);
            return (-1);
        }
        if (status < 0) {
-           report(LOG_DEBUG, "%s: error in select fd %d", 
+           report(LOG_DEBUG, "%s: error in select fd %d",
                   session.peer, fd);
            return (-1);
        }
@@ -406,7 +458,7 @@ int timeout;
        sent = write(fd, ptr, remaining);
 
        if (sent <= 0) {
-           report(LOG_DEBUG, "%s: error writing fd %d sent=%d", 
+           report(LOG_DEBUG, "%s: error writing fd %d sent=%d",
                   session.peer, fd, sent);
            return (sent);      /* error */
        }
@@ -416,16 +468,32 @@ int timeout;
     return (bytes - remaining);
 }
 
+static const char *get_session_key TAC_ARGS((void));
+
+static const char *
+get_session_key()
+{
+    const char *retval = NULL;
+
+    if ((retval = cfg_get_host_key(session.peer_addr)))
+       return (retval);
+    if (session.peer_addr != session.peer
+     && (retval = cfg_get_host_key(session.peer     )))
+       return (retval);
+    return (session.key);
+}
+
 /* read a packet from the wire, and decrypt it. Increment the global
  seq_no return NULL on failure */
 
+u_char *read_packet TAC_ARGS((void));
+
 u_char *
 read_packet()
 {
     HDR hdr;
     u_char *pkt, *data;
     int len;
-    char *tkey;
 
     if (debug & DEBUG_PACKET_FLAG)
        report(LOG_DEBUG, "Waiting for packet");
@@ -433,13 +501,13 @@ read_packet()
     /* read a packet header */
     len = sockread(session.sock, (u_char *) & hdr, TAC_PLUS_HDR_SIZE, TAC_PLUS_READ_TIMEOUT);
     if (len != TAC_PLUS_HDR_SIZE) {
-       report(LOG_DEBUG, "Read %d bytes from %s %s, expecting %d", 
+       report(LOG_DEBUG, "Read %d bytes from %s %s, expecting %d",
               len, session.peer, session.port, TAC_PLUS_HDR_SIZE);
        return(NULL);
     }
 
     if ((hdr.version & TAC_PLUS_MAJOR_VER_MASK) != TAC_PLUS_MAJOR_VER) {
-       report(LOG_ERR, 
+       report(LOG_ERR,
               "%s: Illegal major version specified: found %d wanted %d\n",
               session.peer, hdr.version, TAC_PLUS_MAJOR_VER);
        return(NULL);
@@ -451,7 +519,7 @@ read_packet()
        len < TAC_PLUS_HDR_SIZE || len > 0x10000) {
        report(LOG_ERR,
               "%s: Illegal data size: %lu\n",
-              session.peer, ntohl(hdr.datalength));
+              session.peer, (unsigned long) ntohl(hdr.datalength));
        return(NULL);
     }
     pkt = (u_char *) tac_malloc(len);
@@ -463,9 +531,9 @@ read_packet()
     data = pkt + TAC_PLUS_HDR_SIZE;
 
     /* read the rest of the packet data */
-    if (sockread(session.sock, data, ntohl(hdr.datalength), 
+    if ((unsigned long)sockread(session.sock, data, ntohl(hdr.datalength),
                 TAC_PLUS_READ_TIMEOUT) !=
-       ntohl(hdr.datalength)) {
+       (unsigned long) ntohl(hdr.datalength)) {
        report(LOG_ERR, "%s: start_session: bad socket read", session.peer);
        return (NULL);
     }
@@ -479,11 +547,11 @@ read_packet()
        return (NULL);
     }
 
-    /* decrypt the data portion */
-    if ( !(tkey=(char *)cfg_get_host_key(session.peer)) )
-               tkey = session.key;     
+    /* Now we are starting our new 'request' cycle */
+    cfg_request_scan_begin();
 
-    if (md5_xor((HDR *)pkt, data, tkey)) {
+    /* decrypt the data portion */
+    if (md5_xor((HDR *)pkt, data, get_session_key())) {
        report(LOG_ERR, "%s: start_session error decrypting data",
               session.peer);
        return (NULL);
@@ -498,14 +566,16 @@ read_packet()
     return (pkt);
 }
 
+static int write_packet TAC_ARGS((u_char *pak));
+
 /* write a packet to the wire, encrypting it */
+static int
 write_packet(pak)
 u_char *pak;
 {
     HDR *hdr = (HDR *) pak;
     u_char *data;
     int len;
-    char *tkey;
 
     len = TAC_PLUS_HDR_SIZE + ntohl(hdr->datalength);
 
@@ -513,10 +583,7 @@ u_char *pak;
     data = pak + TAC_PLUS_HDR_SIZE;
 
     /* encrypt the data portion */
-   if ( !(tkey=(char *)cfg_get_host_key(session.peer)) )
-                tkey = session.key;
-
-   if (md5_xor((HDR *)pak, data, tkey)) {
+    if (md5_xor((HDR *)pak, data, get_session_key())) {
        report(LOG_ERR, "%s: write_packet: error encrypting data", session.peer);
        return (-1);
     }
@@ -528,6 +595,9 @@ u_char *pak;
     return (0);
 }
 
+void send_error_reply TAC_ARGS((int type, char *msg));
+
+void
 send_error_reply(type, msg)
 int type;
 char *msg;