-/*
+/*
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;
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;
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);
/* 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];
/* 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;
}
+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];
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);
* 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;
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) {
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);
}
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);
* 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;
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);
}
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 */
}
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");
/* 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);
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);
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);
}
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);
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);
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);
}
return (0);
}
+void send_error_reply TAC_ARGS((int type, char *msg));
+
+void
send_error_reply(type, msg)
int type;
char *msg;