diff --git a/upassword b/upassword index 6dd5004..5105cb2 100755 --- a/upassword +++ b/upassword @@ -4736,10 +4736,63 @@ public class upassword { } } + private static final void printvar(String name, String value, boolean shell) { + StringBuilder sb = new StringBuilder(); + if (shell) { + sb.append(name); + sb.append("='"); + sb.append(value.replaceAll("'", "'\\\\''")); + sb.append("'"); + } else { + sb.append(name); + sb.append(":"); + while (sb.length() < 8) + sb.append(" "); + sb.append(value); + } + println(sb.toString()); + } + + private static final boolean isCodEtu(String codEtu) { + if (codEtu == null) return false; + return Pattern.matches("\\d{8}", codEtu); + } + + private static final String[] ETU_PASSWORD_GROUPS = new String[] { + // + "jiPV/09lHKI1uz+a9vUpX0yMUIy9YAeIwfHPXoA81ik=", + "Vgrlv+kkWzlYVIUnnL7zUw==", + "QFL4JbN2+rsQn1zMVkS//8MLGz1dxxgI2jHKM3iIrwg=", + "KMCTgO8AerczlcQubrbsQg==", + "iLOWOlwRn6YpEj/ZSJFdUVWzjvESRSv45UXDStJCanM=", + "ktokGgUx93gjSsimKn4BBQ==", + "jiPV/09lHKI1uz+a9vUpX3CXBrQfBiW/OgGD/CIjZBE=", + "yYjWpZXP2EMWp7VZR+0xPA=="}; + + private static final void unlockEtuPasswordGroups(String skey) throws Exception { + byte[] key = AESEnc.getKey(skey); + for (int i = 0; i < ETU_PASSWORD_GROUPS.length; i++) { + ETU_PASSWORD_GROUPS[i] = AESEnc.sdecrypt(ETU_PASSWORD_GROUPS[i], key); + } + } + + private static final String getEtuPassword(String codEtu) { + StringBuilder sb = new StringBuilder(); + int crc = Integer.valueOf(codEtu); + for (int i = 0; i < ETU_PASSWORD_GROUPS.length; i++) { + String group = ETU_PASSWORD_GROUPS[i]; + int grouplen = group.length(); + sb.append(group.charAt(crc % grouplen)); + } + return sb.toString(); + } + private void run(String[] args) { if (args.length == 1 && strEquals(args[0], "--help")) { println("USAGE:" // + "\n upassword -p [-f aeskeyfile] [clear [salts...]]" + + "\n upassword -p [-f aeskeyfile] -j JKEY codetu [salts...]" + + "\n upassword -p -f aeskeyfile -k crypted [salts...]" + "\n upassword -f aeskeyfile -G [password [salt]]" + "\n upassword -f aeskeyfile -s" + "\n upassword -f aeskeyfile -e clear" @@ -4747,7 +4800,13 @@ public class upassword { + "\n\nOPTIONS" + "\n -p, --hash-password" + "\n Crypter un mot de passe (option par défaut). Si le mot de passe en clair" - + "\n et/ou le salt ne sont pas spécifiés, ils sont choisis au hasard. " + + "\n et/ou le salt ne sont pas spécifiés, ils sont choisis au hasard." + + "\n -j, --clear-is-codetu JKEY" + + "\n Indiquer que l'argument clear est un numéro d'étudiant, à partir duquel" + + "\n il faut générer le mot de passe. Cette option n'est valide qu'avec -p" + + "\n -k, --clear-is-crypted" + + "\n Indiquer que l'argument clear doit d'abord être décrypté avec la clé AES" + + "\n spécifiée avant utilisation. Cette option n'est valide qu'avec -p" + "\n -G, --aes-genkey" + "\n Générer une clé AES pour utilisation avec les options -s, -e, -d" + "\n -s, --aes-showkey" @@ -4758,11 +4817,15 @@ public class upassword { + "\n Décrypter un mot de passe avec la clé AES spécifiée" + "\n -f, --aes-keyfile" + "\n Spécifier le fichier contenant la clé AES. Cette option est obligatoire" - + "\n avec les options -G, -s, -e et -d"); + + "\n avec les options -G, -s, -e et -d" + + "\n --shell" + + "\n Afficher les valeurs pour évaluation par le shell"); System.exit(0); } EAction action = EAction.HASH_PASSWORD; + boolean codEtu = false, crypted = false, shell = false; + String codEtuKey = null; String aeskeyfile = null; int i = 0, max = args.length; while (i < args.length) { @@ -4770,6 +4833,21 @@ public class upassword { if (arg.equals("-p") || arg.equals("--hash-password")) { action = EAction.HASH_PASSWORD; i++; + } else if (arg.substring(0, 2).equals("-j") || arg.equals("--clear-is-codetu")) { + int shift = 1; + if (arg.equals("-j") || arg.equals("--clear-is-codetu")) { + if (args.length > i + 1) { + codEtuKey = args[i + 1]; + shift = 2; + } + } else { + codEtuKey = arg.substring(2); + } + i += shift; + codEtu = true; + } else if (arg.equals("-k") || args.equals("--clear-is-crypted")) { + crypted = true; + i++; } else if (arg.equals("-G") || arg.equals("--aes-genkey")) { action = EAction.GEN_AESKEY; i++; @@ -4793,22 +4871,45 @@ public class upassword { aeskeyfile = arg.substring(2); } i += shift; + } else if (arg.equals("--shell")) { + shell = true; + i++; } else { if (arg.equals("--")) i++; - String[] newargs = new String[args.length - i]; - System.arraycopy(args, i, newargs, 0, newargs.length); - args = newargs; break; } } + String[] newargs = new String[args.length - i]; + System.arraycopy(args, i, newargs, 0, newargs.length); + args = newargs; switch (action) { case HASH_PASSWORD: { - byte[] aeskey = readAeskeyfile(aeskeyfile); - String clear = null; if (args.length > 0) clear = args[0]; + byte[] aeskey; + if (crypted && clear != null) { + checkExisting(aeskeyfile); + aeskey = readAeskeyfile(aeskeyfile); + try { + clear = AESEnc.sdecrypt(clear, aeskey); + } catch (Exception e) { + die(null, e); + } + } else { + aeskey = readAeskeyfile(aeskeyfile); + } + + if (codEtu && isCodEtu(clear)) { + try { + unlockEtuPasswordGroups(codEtuKey); + } catch (Exception e) { + die(null, e); + } + clear = getEtuPassword(clear); + } + if (clear == null) { PasswordGenerator pg = new PasswordGenerator(); clear = pg.generate(); @@ -4840,20 +4941,20 @@ public class upassword { } } - println("clear: " + clear); - println("lm: " + lm); - println("ntlm: " + ntlm); - println("crypt: " + crypt); - println("sha: " + sha); - println("ssha: " + ssha); - println("md5: " + md5); - println("smd5: " + smd5); - if (aes != null) println("aes: " + aes); + printvar("clear", clear, shell); + printvar("lm", lm, shell); + printvar("ntlm", ntlm, shell); + printvar("crypt", crypt, shell); + printvar("sha", sha, shell); + printvar("ssha", ssha, shell); + printvar("md5", md5, shell); + printvar("smd5", smd5, shell); + if (aes != null) printvar("aes", aes, shell); } else { // Afficher uniquement les versions cryptées des mots de passe avec // les schemes correspondant aux salts spécifiés, pour chacun des // salts spécifiés. - println("clear: " + clear); + printvar("clear", clear, shell); i = 1; max = args.length; while (i < max) { @@ -4863,25 +4964,25 @@ public class upassword { String cryptSalt = Salt.getCryptSalt(salt); String crypt = getPasswordCryptSalt(clear, Password.CRYPT, cryptSalt) .getNormalized(); - println("salt: " + cryptSalt); - println("crypt: " + crypt); - if (salt.equals(crypt)) println("match: true"); + printvar("salt", cryptSalt, shell); + printvar("crypt", crypt, shell); + if (salt.equals(crypt)) printvar("match", "true", shell); } else if (Password.isSshaScheme(salt)) { byte[] sshaSalt = Salt.getSshaSalt(salt); String ssha = getPasswordBinarySalt(clear, Password.SSHA, sshaSalt) .getNormalized(); - println("salt: " + toHex(sshaSalt)); - println("ssha: " + ssha); - if (salt.equals(ssha)) println("match: true"); + printvar("salt", toHex(sshaSalt), shell); + printvar("ssha", ssha, shell); + if (salt.equals(ssha)) printvar("match", "true", shell); } else if (Password.isSmd5Scheme(salt)) { byte[] smd5Salt = Salt.getSmd5Salt(salt); String smd5 = getPasswordBinarySalt(clear, Password.SMD5, smd5Salt) .getNormalized(); - println("salt: " + toHex(smd5Salt)); - println("smd5: " + smd5); - if (salt.equals(smd5)) println("match: true"); + printvar("salt", toHex(smd5Salt), shell); + printvar("smd5", smd5, shell); + if (salt.equals(smd5)) printvar("match", "true", shell); } else { - println("salt: " + salt + " !not supported"); + printvar("salt", salt + " !not supported", shell); } } else if (isHex(salt)) { byte[] binarySalt = fromHex(salt); @@ -4889,26 +4990,26 @@ public class upassword { .getNormalized(); String smd5 = getPasswordBinarySalt(clear, Password.SMD5, binarySalt) .getNormalized(); - println("salt: " + toHex(binarySalt)); - println("ssha: " + ssha); - println("smd5: " + smd5); + printvar("salt", toHex(binarySalt), shell); + printvar("ssha", ssha, shell); + printvar("smd5", smd5, shell); if (salt.length() >= 2) { String cryptSalt = Salt.getCryptSalt(salt); String crypt = getPasswordCryptSalt(clear, Password.CRYPT, cryptSalt) .getNormalized(); - if (!salt.equals(cryptSalt)) println("salt: " + cryptSalt); - println("crypt: " + crypt); - if (salt.equals(crypt)) println("match: true"); + if (!salt.equals(cryptSalt)) printvar("salt", cryptSalt, shell); + printvar("crypt", crypt, shell); + if (salt.equals(crypt)) printvar("match", "true", shell); } - if (salt.equals(ssha)) println("match: true"); - if (salt.equals(smd5)) println("match: true"); + if (salt.equals(ssha)) printvar("match", "true", shell); + if (salt.equals(smd5)) printvar("match", "true", shell); } else { String cryptSalt = Salt.getCryptSalt(salt); String crypt = getPasswordCryptSalt(clear, Password.CRYPT, cryptSalt) .getNormalized(); - println("salt: " + cryptSalt); - println("crypt: " + crypt); - if (salt.equals(crypt)) println("match: true"); + printvar("salt", cryptSalt, shell); + printvar("crypt", crypt, shell); + if (salt.equals(crypt)) printvar("match", "true", shell); } } } @@ -4921,23 +5022,22 @@ public class upassword { die(aeskeyfile + ": Refus d'écraser un fichier existant", null); } + String password = null; + if (args.length > 0) password = args[0]; + String salt = null; + if (args.length > 1) salt = args[1]; + byte[] key = null; try { - String password = null; - if (args.length > 0) password = args[0]; - byte[] salt = null; - if (args.length > 1) salt = args[1].getBytes(UTF_8); - if (password != null && salt != null) { key = AESEnc.genkey(); } else { - key = AESEnc.genkey(password, salt, -1); + key = AESEnc.genkey(password, salt.getBytes(UTF_8), -1); } } catch (Exception e) { die(null, e); } writeAeskeyfile(aeskeyfile, key); - println(AESEnc.getSkey(key)); break; }