package org.freertr.pack; import org.freertr.cry.cryHashMd5; import org.freertr.pipe.pipeSide; import org.freertr.util.bits; /** * terminal access controller access control system (rfc1492) packet * * @author matecsaba */ public class packTacacs { /** * port number */ public final static int port = 49; /** * header size */ public final static int size = 12; /** * cleartext transmission */ public final static int flgClr = 0x1; /** * multiple session */ public final static int flgMul = 0x4; /** * not echo */ public final static int flgNech = 0x1; /** * abort */ public final static int flgAbrt = 0x1; /** * authentication */ public final static int typAuthen = 1; /** * authorization */ public final static int typAuthor = 2; /** * accounting */ public final static int typAccount = 3; /** * passed */ public final static int sttPass = 1; /** * failed */ public final static int sttFail = 2; /** * get data */ public final static int sttGetDat = 3; /** * get username */ public final static int sttGetUsr = 4; /** * get password */ public final static int sttGetPwd = 5; /** * restart */ public final static int sttGetRst = 6; /** * error */ public final static int sttGetErr = 7; /** * follow */ public final static int sttGetFlw = 33; /** * login */ public final static int actLogin = 1; /** * change password */ public final static int actChPwd = 2; /** * send password */ public final static int actTxPwd = 3; /** * send authentication */ public final static int actTxAut = 4; /** * not set */ public final static int autyNotset = 0; /** * ascii login */ public final static int autyAscii = 1; /** * password authentication protocol */ public final static int autyPap = 2; /** * channenge-handshake authentication protocol */ public final static int autyChap = 3; /** * arap */ public final static int autyArap = 4; /** * ms-chap */ public final static int autyMSchap = 5; /** * login */ public final static int srvLogin = 1; /** * enable */ public final static int srvEnable = 2; /** * ppp */ public final static int srvPpp = 3; /** * arap */ public final static int srvArap = 4; /** * pt */ public final static int srvPt = 5; /** * rcmd */ public final static int srvRcmd = 6; /** * x25 */ public final static int srvX25 = 7; /** * nasi */ public final static int srvNasi = 8; /** * fwd proxy */ public final static int srvPrxy = 9; /** * not set */ public final static int metNotset = 0; /** * none */ public final static int metNone = 1; /** * kerberos5 */ public final static int metKrb5 = 2; /** * line */ public final static int metLine = 3; /** * enable */ public final static int metEna = 4; /** * local */ public final static int metLoc = 5; /** * tacacs */ public final static int metTac = 6; /** * guest */ public final static int metGuest = 8; /** * radius */ public final static int metRad = 16; /** * kerberos4 */ public final static int metKrb4 = 17; /** * rcmd */ public final static int metRcmd = 32; /** * passed add */ public final static int staPassAdd = 0; /** * passed reply */ public final static int staPassRep = 1; /** * failed */ public final static int staFail = 16; /** * error */ public final static int staError = 17; /** * follow */ public final static int staFolow = 33; /** * current packet */ public packHolder pack; /** * lower pipe */ public pipeSide pipe; /** * shared secret */ public String secret; /** * version */ public int ver; /** * message type */ public int typ; /** * sequence number */ public int seq; /** * flags */ public int flg; /** * session id */ public int ses; /** * action */ public int act; /** * privilege level */ public int priv; /** * authentication type */ public int auty; /** * service */ public int srv; /** * username */ public String usr; /** * nas port */ public String prt; /** * remote address */ public String adr; /** * additional data */ public String dat; /** * arguments */ public String[] arg; /** * create packet holder */ public packTacacs() { pack = new packHolder(true, true); } private boolean packCrypt() { if (secret == null) { return (flg & flgClr) == 0; } if ((flg & flgClr) != 0) { return true; } byte[] prv = new byte[0]; for (int p = 0; p < pack.dataSize(); p += prv.length) { cryHashMd5 m = new cryHashMd5(); m.init(); byte[] buf = new byte[4]; bits.msbPutD(buf, 0, ses); m.update(buf, 0, buf.length); buf = secret.getBytes(); m.update(buf, 0, buf.length); buf[0] = (byte) ver; m.update(buf, 0, 1); buf[0] = (byte) seq; m.update(buf, 0, 1); m.update(prv, 0, prv.length); prv = m.finish(); for (int o = 0; o < prv.length; o++) { pack.putByte(p + o, pack.getByte(p + o) ^ prv[o]); } } int i = pack.dataSize(); pack.getSkip(i); pack.putSkip(i); pack.merge2beg(); return false; } /** * parse one header * * @return false on success, true on error */ public boolean packRecv() { typ = -1; pack.clear(); if (pack.pipeRecv(pipe, 0, size, 144) != size) { pipe.setClose(); return true; } ver = pack.getByte(0); // version if ((ver & 0xf0) != 0xc0) { return true; } typ = pack.getByte(1); // type of packet seq = pack.getByte(2); // sequence number flg = pack.getByte(3); // flags ses = pack.msbGetD(4); int len = pack.msbGetD(8); if (pack.pipeRecv(pipe, size, len, 144) != len) { pipe.setClose(); typ = -1; return true; } pack.getSkip(size); if (packCrypt()) { pipe.setClose(); typ = -1; return true; } return false; } /** * create one header */ public void packSend() { pack.merge2beg(); seq++; ver = 0xc0; flg = 0; if (secret == null) { flg |= flgClr; } packCrypt(); pack.putByte(0, ver); pack.putByte(1, typ); pack.putByte(2, seq); pack.putByte(3, flg); pack.msbPutD(4, ses); pack.msbPutD(8, pack.dataSize()); pack.putSkip(size); pack.merge2beg(); pack.pipeSend(pipe, 0, pack.dataSize(), 3); } /** * dump this packet * * @return string */ public String dump() { String a = ""; if (arg != null) { for (int i = 0; i < arg.length; i++) { a += " arg" + i + "=" + arg[i]; } } return "typ=" + typ + " seq=" + seq + " ses=" + ses + " act=" + act + " priv=" + priv + " autyp=" + auty + " srv=" + srv + " usr=" + usr + " prt=" + prt + " adr=" + adr + " dat=" + dat + a; } /** * parse authentication start * * @return false on success, true on error */ public boolean parseAuthenStrt() { if (typ != typAuthen) { return true; } act = pack.getByte(0); priv = pack.getByte(1); auty = pack.getByte(2); srv = pack.getByte(3); int usrL = pack.getByte(4); int prtL = pack.getByte(5); int adrL = pack.getByte(6); int datL = pack.getByte(7); pack.getSkip(8); usr = pack.getAsciiZ(0, usrL, -1); pack.getSkip(usrL); prt = pack.getAsciiZ(0, prtL, -1); pack.getSkip(prtL); adr = pack.getAsciiZ(0, adrL, -1); pack.getSkip(adrL); dat = pack.getAsciiZ(0, datL, -1); pack.getSkip(datL); return false; } /** * create authentication start */ public void createAuthenStrt() { pack.clear(); typ = typAuthen; pack.putByte(0, act); pack.putByte(1, priv); pack.putByte(2, auty); pack.putByte(3, srv); int usrL = usr.length(); int prtL = prt.length(); int adrL = adr.length(); int datL = dat.length(); pack.putByte(4, usrL); pack.putByte(5, prtL); pack.putByte(6, adrL); pack.putByte(7, datL); pack.putSkip(8); pack.putAsciiZ(0, usrL, usr, 0); pack.putSkip(usrL); pack.putAsciiZ(0, prtL, prt, 0); pack.putSkip(prtL); pack.putAsciiZ(0, adrL, adr, 0); pack.putSkip(adrL); pack.putAsciiZ(0, datL, dat, 0); pack.putSkip(datL); } /** * parse authentication reply * * @return false on success, true on error */ public boolean parseAuthenRply() { if (typ != typAuthen) { return true; } act = pack.getByte(0); priv = pack.getByte(1); int usrL = pack.msbGetW(2); int datL = pack.msbGetW(4); pack.getSkip(6); usr = pack.getAsciiZ(0, usrL, -1); pack.getSkip(usrL); dat = pack.getAsciiZ(0, datL, -1); pack.getSkip(datL); return false; } /** * create authentication reply */ public void createAuthenRply() { pack.clear(); typ = typAuthen; pack.putByte(0, act); pack.putByte(1, priv); int usrL = usr.length(); int datL = dat.length(); pack.msbPutW(2, usrL); pack.msbPutW(4, datL); pack.putSkip(6); pack.putAsciiZ(0, usrL, usr, 0); pack.putSkip(usrL); pack.putAsciiZ(0, datL, dat, 0); pack.putSkip(datL); } /** * parse authentication continue * * @return false on success, true on error */ public boolean parseAuthenCont() { if (typ != typAuthen) { return true; } int usrL = pack.msbGetW(0); int datL = pack.msbGetW(2); act = pack.getByte(4); pack.getSkip(5); usr = pack.getAsciiZ(0, usrL, -1); pack.getSkip(usrL); dat = pack.getAsciiZ(0, datL, -1); pack.getSkip(datL); return false; } /** * parse authentication continue */ public void createAuthenCont() { pack.clear(); typ = typAuthen; int usrL = usr.length(); int datL = dat.length(); pack.msbPutW(0, usrL); pack.msbPutW(2, datL); pack.putByte(4, act); pack.putSkip(5); pack.putAsciiZ(0, usrL, usr, 0); pack.putSkip(usrL); pack.putAsciiZ(0, datL, dat, 0); pack.putSkip(datL); } /** * parse authorization request * * @return false on success, true on error */ public boolean parseAuthorReq() { if (typ != typAuthor) { return true; } act = pack.getByte(0); priv = pack.getByte(1); auty = pack.getByte(2); srv = pack.getByte(3); int usrL = pack.getByte(4); int prtL = pack.getByte(5); int adrL = pack.getByte(6); int args = pack.getByte(7); int ofs = 8 + args; usr = pack.getAsciiZ(ofs, usrL, -1); ofs += usrL; prt = pack.getAsciiZ(ofs, prtL, -1); ofs += prtL; adr = pack.getAsciiZ(ofs, adrL, -1); ofs += adrL; arg = new String[args]; for (int i = 0; i < args; i++) { int o = pack.getByte(8 + i); arg[i] = pack.getAsciiZ(ofs, o, -1); ofs += o; } return false; } /** * parse authorization request */ public void createAuthorReq() { pack.clear(); typ = typAuthor; pack.putByte(0, act); pack.putByte(1, priv); pack.putByte(2, auty); pack.putByte(3, srv); int usrL = usr.length(); int prtL = prt.length(); int adrL = adr.length(); pack.putByte(4, usrL); pack.putByte(5, prtL); pack.putByte(6, adrL); pack.putByte(7, arg.length); pack.putSkip(8); for (int i = 0; i < arg.length; i++) { pack.putByte(i, arg[i].length()); } pack.putSkip(arg.length); pack.putAsciiZ(0, usrL, usr, 0); pack.putSkip(usrL); pack.putAsciiZ(0, prtL, prt, 0); pack.putSkip(prtL); pack.putAsciiZ(0, adrL, adr, 0); pack.putSkip(adrL); for (int i = 0; i < arg.length; i++) { pack.putAsciiZ(0, arg[i].length(), arg[i], 0); pack.putSkip(arg[i].length()); } } /** * parse authorization reply * * @return false on success, true on error */ public boolean parseAuthorRep() { if (typ != typAuthor) { return true; } srv = pack.getByte(0); int args = pack.getByte(1); int usrL = pack.msbGetW(2); int adrL = pack.msbGetW(4); int ofs = 6 + args; usr = pack.getAsciiZ(ofs, usrL, -1); ofs += usrL; adr = pack.getAsciiZ(ofs, adrL, -1); ofs += adrL; arg = new String[args]; for (int i = 0; i < args; i++) { int o = pack.getByte(6 + i); arg[i] = pack.getAsciiZ(ofs, o, -1); ofs += o; } return false; } /** * parse authorization reply */ public void createAuthorRep() { pack.clear(); typ = typAuthor; pack.putByte(0, srv); pack.putByte(1, arg.length); int usrL = usr.length(); int adrL = adr.length(); pack.msbPutW(2, usrL); pack.msbPutW(4, adrL); pack.putSkip(6); for (int i = 0; i < arg.length; i++) { pack.putByte(i, arg[i].length()); } pack.putSkip(arg.length); pack.putAsciiZ(0, usrL, usr, 0); pack.putSkip(usrL); pack.putAsciiZ(0, adrL, adr, 0); pack.putSkip(adrL); for (int i = 0; i < arg.length; i++) { pack.putAsciiZ(0, arg[i].length(), arg[i], 0); pack.putSkip(arg[i].length()); } } }