static gint tacplus_decrypted_tvb_setup( tvbuff_t *tvb, tvbuff_t **dst_tvb, packet_info *pinfo, guint32 len, guint8 version, const char *key ) { guint8 *buff; guint8 session_id[4]; /* TODO Check the possibility to use pinfo->decrypted_data */ /* session_id is in NETWORK Byte Order, and is used as byte array in the md5_xor */ tvb_memcpy(tvb, session_id, 4,4); buff = tvb_memdup(tvb, TAC_PLUS_HDR_SIZE, len); md5_xor( buff, key, len, session_id,version, tvb_get_guint8(tvb,2) ); /* Allocate a new tvbuff, referring to the decrypted data. */ *dst_tvb = tvb_new_child_real_data(tvb, buff, len, len ); /* Arrange that the allocated packet data copy be freed when the tvbuff is freed. */ tvb_set_free_cb( *dst_tvb, g_free ); /* Add the decrypted data to the data source list. */ add_new_data_source(pinfo, *dst_tvb, "TACACS+ Decrypted"); return 0; }
/* write a packet to the wire, encrypting it */ static int write_packet(u_char *pak) { HDR *hdr = (HDR *)pak; u_char *data; int len; char *tkey; len = TAC_PLUS_HDR_SIZE + ntohl(hdr->datalength); /* the data start here */ data = pak + TAC_PLUS_HDR_SIZE; /* encrypt the data portion */ tkey = cfg_get_host_key(session.peerip); if (tkey == NULL && !STREQ(session.peer, session.peerip)) { tkey = cfg_get_host_prompt(session.peer); } if (tkey == NULL) tkey = session.key; if (md5_xor((HDR *)pak, data, tkey)) { report(LOG_ERR, "%s: write_packet: error encrypting data", session.peer); return(-1); } if (sockwrite(session.sock, pak, len, cfg_get_writetimeout()) != len) { return(-1); } session.last_exch = time(NULL); return(0); }
/* * read a packet from the wire, and decrypt it. Increment the global * seq_no return NULL on failure */ u_char * read_packet(void) { 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, cfg_get_readtimeout()); if (len != TAC_PLUS_HDR_SIZE) { report(LOG_DEBUG, "Read %d bytes from %s %s, expecting %d", len, session.peer, session.port, TAC_PLUS_HDR_SIZE); return(NULL); } session.peerflags = hdr.flags; if ((hdr.version & TAC_PLUS_MAJOR_VER_MASK) != TAC_PLUS_MAJOR_VER) { report(LOG_ERR, "%s: Illegal major version specified: found %d wanted " "%d\n", session.peer, hdr.version, TAC_PLUS_MAJOR_VER); return(NULL); } /* get memory for the packet */ len = TAC_PLUS_HDR_SIZE + ntohl(hdr.datalength); if ((ntohl(hdr.datalength) & ~0xffffUL) || (len < TAC_PLUS_HDR_SIZE) || (len > 0x10000)) { report(LOG_ERR, "%s: Illegal data size: %lu\n", session.peer, ntohl(hdr.datalength)); return(NULL); } pkt = (u_char *)tac_malloc(len); /* initialise the packet */ memcpy(pkt, &hdr, TAC_PLUS_HDR_SIZE); /* the data start here */ data = pkt + TAC_PLUS_HDR_SIZE; /* read the rest of the packet data */ if (sockread(session.sock, data, ntohl(hdr.datalength), cfg_get_readtimeout()) != ntohl(hdr.datalength)) { report(LOG_ERR, "%s: start_session: bad socket read", session.peer); free(pkt); return(NULL); } session.seq_no++; /* should now equal that of incoming packet */ session.last_exch = time(NULL); if (session.seq_no != hdr.seq_no) { report(LOG_ERR, "%s: Illegal session seq # %d != packet seq # %d", session.peer, session.seq_no, hdr.seq_no); free(pkt); return(NULL); } /* decrypt the data portion */ tkey = cfg_get_host_key(session.peerip); if (tkey == NULL && !STREQ(session.peer, session.peerip)) { tkey = cfg_get_host_prompt(session.peer); } if (tkey == NULL) tkey = session.key; if (md5_xor((HDR *)pkt, data, tkey)) { report(LOG_ERR, "%s: start_session error decrypting data", session.peer); free(pkt); return(NULL); } if (debug & DEBUG_PACKET_FLAG) report(LOG_DEBUG, "Read %s size=%d", summarise_incoming_packet_type(pkt), len); session.version = hdr.version; return(pkt); }