package org.freertr.auth; import java.util.ArrayList; import java.util.List; import org.freertr.addr.addrEui; import org.freertr.addr.addrIPv4; import org.freertr.addr.addrIPv6; import org.freertr.cfg.cfgAll; import org.freertr.cry.cryHashSha1; import org.freertr.cry.cryKeyGeneric; import org.freertr.enc.encBase32; import org.freertr.enc.encBase64; import org.freertr.enc.encUrl; import org.freertr.util.bits; import org.freertr.util.cmds; /** * one user record * * @author matecsaba */ public class authLocalEntry implements Comparable { /** * create instance */ public authLocalEntry() { } /** * times matched */ protected int matches; /** * last matched */ protected long lastMatch; /** * name of user */ protected String username = ""; /** * description of user */ protected String description = null; /** * remark of user */ protected String remark = null; /** * group of user */ protected String group = null; /** * password of user */ protected String password = null; /** * secret of user */ protected byte[] secret; /** * hidden data */ protected byte[] hidata; /** * one time password */ protected byte[] otpseed; /** * ssh public key */ protected byte[] pubkey; /** * accept any password */ protected boolean anyPass; /** * accept any public key */ protected boolean anyKey; /** * accept refused authentication */ protected boolean nothing; /** * command to use on login */ protected String autoCommand = ""; /** * terminate session after command */ protected boolean autoHangup = false; /** * privilege of user */ protected int privilege = 15; /** * filter id of user */ protected String filterid; /** * usage counter */ protected int countdown = -1; /** * ipv4 address */ protected addrIPv4 ipv4addr; /** * ipv4 routes */ protected String ipv4route; /** * ipv6 address */ protected addrIPv6 ipv6addr; /** * ipv6 interface id */ protected addrEui ipv6ifid; /** * ipv6 routes */ protected String ipv6route; /** * get running configuration * * @param beg beginning string * @param lst list to append * @param filter default filter */ public void getShRun(String beg, List lst, int filter) { beg += "username " + username; lst.add(beg); beg += " "; if (description != null) { lst.add(beg + "description " + description); } if (remark != null) { lst.add(beg + "remark " + remark); } if (group != null) { lst.add(beg + "group " + group); } if (password != null) { lst.add(beg + "password " + authLocal.passwdEncode(password, (filter & 2) != 0)); } if (secret != null) { lst.add(beg + "secret " + authLocal.secretEncode(secret, (filter & 2) != 0)); } if (otpseed != null) { lst.add(beg + "otpseed " + authLocal.passwdEncode(encBase64.encodeBytes(otpseed), (filter & 2) != 0)); } if (hidata != null) { lst.add(beg + "hidata " + authLocal.passwdEncode(encBase64.encodeBytes(hidata), (filter & 2) != 0)); } if (pubkey != null) { lst.add(beg + "pubkey " + encBase64.encodeBytes(pubkey)); } if (autoHangup) { lst.add(beg + "autohangup"); } if (countdown >= 0) { lst.add(beg + "countdown " + countdown); } if (filterid != null) { lst.add(beg + "filter " + filterid); } if (anyPass) { lst.add(beg + "anypass"); } if (anyKey) { lst.add(beg + "anykey"); } if (nothing) { lst.add(beg + "anything"); } if (ipv4addr != null) { lst.add(beg + "ipv4addr " + ipv4addr); } if (ipv4route != null) { lst.add(beg + "ipv4route " + ipv4route); } if (ipv6addr != null) { lst.add(beg + "ipv6addr " + ipv6addr); } if (ipv6ifid != null) { lst.add(beg + "ipv6ifid " + ipv6ifid); } if (ipv6route != null) { lst.add(beg + "ipv6route " + ipv6route); } lst.add(beg + "autocommand " + autoCommand); lst.add(beg + "privilege " + privilege); } /** * parse commands * * @param neg negated * @param cmd commands * @return true if error happened */ public boolean fromString(boolean neg, cmds cmd) { String s = cmd.word(); if (s.length() < 1) { return false; } if (s.equals("description")) { description = cmd.getRemaining(); if (neg) { description = null; } return false; } if (s.equals("group")) { group = cmd.getRemaining(); if (neg) { group = null; } return false; } if (s.equals("remark")) { remark = cmd.getRemaining(); if (neg) { remark = null; } return false; } if (s.equals("password")) { if (neg) { password = null; return false; } password = authLocal.passwdDecode(cmd.getRemaining()); return false; } if (s.equals("secret")) { if (neg) { secret = null; return false; } secret = authLocal.secretDecode(cmd.getRemaining()); return false; } if (s.equals("pubkey")) { if (neg) { pubkey = null; return false; } pubkey = encBase64.decodeBytes(cmd.getRemaining()); return false; } if (s.equals("otpseed")) { if (neg) { otpseed = null; return false; } s = cmd.getRemaining(); s = authLocal.passwdDecode(s); if (s == null) { return false; } otpseed = encBase64.decodeBytes(s); return false; } if (s.equals("hidata")) { if (neg) { hidata = null; return false; } s = cmd.getRemaining(); s = authLocal.passwdDecode(s); if (s == null) { return false; } hidata = encBase64.decodeBytes(s); return false; } if (s.equals("anypass")) { anyPass = !neg; return false; } if (s.equals("anykey")) { anyKey = !neg; return false; } if (s.equals("anything")) { nothing = !neg; return false; } if (s.equals("countdown")) { if (neg) { countdown = -1; return false; } countdown = bits.str2num(cmd.word()); return false; } if (s.equals("otppass")) { byte[] buf1 = new byte[2]; buf1[0] = (byte) bits.str2num(cmd.word()); buf1[1] = (byte) bits.str2num(cmd.word()); otpseed = bits.byteConcat(buf1, cmd.getRemaining().getBytes()); return false; } if (s.equals("otpurl")) { return setOtpUrl(cmd.getRemaining()); } if (s.equals("autocommand")) { if (neg) { autoCommand = ""; return false; } autoCommand = cmd.getRemaining(); return false; } if (s.equals("autohangup")) { autoHangup = !neg; return false; } if (s.equals("filter")) { if (neg) { filterid = null; return false; } filterid = cmd.getRemaining(); return false; } if (s.equals("ipv4addr")) { if (neg) { ipv4addr = null; return false; } ipv4addr = new addrIPv4(); ipv4addr.fromString(cmd.word()); return false; } if (s.equals("ipv4route")) { if (neg) { ipv4route = null; return false; } ipv4route = cmd.getRemaining(); return false; } if (s.equals("ipv6addr")) { if (neg) { ipv6addr = null; return false; } ipv6addr = new addrIPv6(); ipv6addr.fromString(cmd.word()); return false; } if (s.equals("ipv6ifid")) { if (neg) { ipv6ifid = null; return false; } ipv6ifid = new addrEui(); ipv6ifid.fromString(cmd.word()); return false; } if (s.equals("ipv6route")) { if (neg) { ipv6route = null; return false; } ipv6route = cmd.getRemaining(); return false; } if (s.equals("privilege")) { privilege = bits.str2num(cmd.word()) & 0xf; return false; } return true; } public int compareTo(authLocalEntry o) { return username.toLowerCase().compareTo(o.username.toLowerCase()); } /** * get otp list * * @param pwd include password * @return list of passwords */ public String getOtpPass(boolean pwd) { if (otpseed == null) { return null; } byte[] seed = new byte[otpseed.length - 2]; bits.byteCopy(otpseed, 2, seed, 0, seed.length); long tim = (bits.getTime() + cfgAll.timeServerOffset) / 1000; final int digits = otpseed[0]; final int period = otpseed[1]; String a = autherOtp.calcTotp(seed, tim, period, digits, new cryHashSha1()); if (password == null) { return a; } if (!pwd) { return a; } return password + a; } /** * get otp url * * @return url string */ public String getOtpUrl() { if (otpseed == null) { return null; } return "otpauth://totp/?secret=" + encBase32.encodeBytes(otpseed, 2, otpseed.length - 2) + "&digits=" + otpseed[0] + "&period=" + otpseed[1]; } /** * set otp url * * @param s string * @return false on success, true on error */ public boolean setOtpUrl(String s) { encUrl url = encUrl.parseOne(s); byte[] buf1 = new byte[2]; s = url.getParam("digits"); if (s == null) { return true; } buf1[0] = (byte) bits.str2num(s); s = url.getParam("period"); if (s == null) { return true; } buf1[1] = (byte) bits.str2num(s); s = url.getParam("secret"); if (s == null) { return true; } byte[] buf2 = encBase32.decodeBytes(s); if (buf2 == null) { return true; } otpseed = bits.byteConcat(buf1, buf2); return false; } /** * check public key * * @param key key to compare * @return false if equals, true if not */ public boolean checkPkey(cryKeyGeneric key) { if (pubkey == null) { return true; } byte[] buf = key.sshWriter(); if (buf.length != pubkey.length) { return true; } if (bits.byteComp(pubkey, 0, buf, 0, buf.length) != 0) { return true; } return false; } /** * get menu data * * @param otp value * @return list of stings */ public List toMenu(boolean otp) { List res = new ArrayList(); res.add("nam " + description); res.add("usr " + remark); res.add("grp " + group); res.add("pwd " + password); res.add("otp " + (otp ? getOtpPass(false) : getOtpUrl())); res.add("---"); if (hidata == null) { return res; } String a = ""; for (int i = 0; i < hidata.length; i++) { int o = hidata[i] & 0xff; switch (o) { case 10: res.add(a); a = ""; break; default: a += (char) o; break; } } return res; } /** * set menu data * * @param lst list to read */ public void fromMenu(List lst) { if (lst == null) { return; } description = ""; remark = ""; group = ""; password = ""; otpseed = null; int i = 0; for (; i < lst.size(); i++) { String a = lst.get(i); cmds cmd = new cmds("menu", a); a = cmd.word(); if (a.length() < 1) { break; } if (a.equals("---")) { break; } if (a.equals("nam")) { description = cmd.getRemaining(); continue; } if (a.equals("usr")) { remark = cmd.getRemaining(); continue; } if (a.equals("grp")) { group = cmd.getRemaining(); continue; } if (a.equals("pwd")) { password = cmd.getRemaining(); continue; } if (a.equals("otp")) { setOtpUrl(cmd.getRemaining()); continue; } } i++; hidata = new byte[0]; for (; i < lst.size(); i++) { byte[] buf = lst.get(i).getBytes(); buf = bits.byteConcat(buf, new byte[]{10}); hidata = bits.byteConcat(hidata, buf); } if (hidata.length < 1) { hidata = null; } } }