diff --git a/upassword b/upassword index b6e9df7..0639467 100755 --- a/upassword +++ b/upassword @@ -4766,6 +4766,10 @@ public class upassword { HASH_PASSWORD, GEN_AESKEY, SHOW_AESKEY, AES_ENCRYPT, AES_DECRYPT; } + private static enum EHashAction { + AUTO, CHECK_MATCH, SAME_OR_NEW, NEW; + } + private static final void checkExisting(String aeskeyfile) { if (aeskeyfile == null) die("Vous devez spécifier l'option -f", null); if (!new File(aeskeyfile).exists()) die(aeskeyfile + ": Fichier introuvable", null); @@ -4873,6 +4877,16 @@ public class upassword { + "\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 -m, --salt-check-match-hash" + + "\n -n, --salt-same-or-new-hash" + + "\n Spécifier le comportement à adopter si les salts qui sont spécifiés sont" + + "\n des hashes normalisés." + + "\n Avec l'option -m (par défaut), pour chacun des hashes, le salt est" + + "\n extrait et le mot de passe en clair est hashé avec ce salt et le scheme" + + "\n spécifiés. Si le hash résultant est le même, afficher 'match: true'" + + "\n Avec l'option -n, si l'un des hashes correspond au mot de passe en" + + "\n clair, alors afficher ce hash. Sinon, faire comme si le mot de passe en" + + "\n clair avait été spécifié sans salt et choisir un nouveau salt 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" @@ -4921,6 +4935,7 @@ public class upassword { } EAction action = EAction.HASH_PASSWORD; + EHashAction hashAction = EHashAction.AUTO; boolean codEtu = false, crypted = false, shell = false; String codEtuKey = null; String aeskeyfile = null; @@ -4946,6 +4961,12 @@ public class upassword { } else if (arg.equals("-k") || args.equals("--clear-is-crypted")) { crypted = true; i++; + } else if (arg.equals("-m") || args.equals("--salt-check-match-hash")) { + hashAction = EHashAction.CHECK_MATCH; + i++; + } else if (arg.equals("-n") || args.equals("--salt-same-or-new-hash")) { + hashAction = EHashAction.SAME_OR_NEW; + i++; } else if (arg.equals("-G") || arg.equals("--aes-genkey")) { action = EAction.GEN_AESKEY; i++; @@ -5014,7 +5035,58 @@ public class upassword { clear = pg.generate(); } + String newCryptSalt = null; + byte[] newBinarySalt = null; if (args.length <= 1) { + hashAction = EHashAction.NEW; + } else if (hashAction == EHashAction.AUTO) { + hashAction = EHashAction.CHECK_MATCH; + } else if (hashAction == EHashAction.SAME_OR_NEW) { + i = 1; + max = args.length; + while (i < max) { + String salt = args[i++]; + if (Password.isNormalizedFormat(salt)) { + if (Password.isCryptScheme(salt)) { + String cryptSalt = Salt.getCryptSalt(salt); + String crypt = getPasswordCryptSalt(clear, Password.CRYPT, cryptSalt) + .getNormalized(); + if (salt.equals(crypt)) newCryptSalt = cryptSalt; + } else if (Password.isSshaScheme(salt)) { + byte[] sshaSalt = Salt.getSshaSalt(salt); + String ssha = getPasswordBinarySalt(clear, Password.SSHA, sshaSalt) + .getNormalized(); + if (salt.equals(ssha)) newBinarySalt = sshaSalt; + } else if (Password.isSmd5Scheme(salt)) { + byte[] smd5Salt = Salt.getSmd5Salt(salt); + String smd5 = getPasswordBinarySalt(clear, Password.SMD5, smd5Salt) + .getNormalized(); + if (salt.equals(smd5)) newBinarySalt = smd5Salt; + } + } else if (isHex(salt)) { + byte[] binarySalt = fromHex(salt); + String ssha = getPasswordBinarySalt(clear, Password.SSHA, binarySalt) + .getNormalized(); + String smd5 = getPasswordBinarySalt(clear, Password.SMD5, binarySalt) + .getNormalized(); + if (salt.length() >= 2) { + String cryptSalt = Salt.getCryptSalt(salt); + String crypt = getPasswordCryptSalt(clear, Password.CRYPT, cryptSalt) + .getNormalized(); + if (salt.equals(crypt)) newCryptSalt = cryptSalt; + } + if (salt.equals(ssha) || salt.equals(smd5)) newBinarySalt = binarySalt; + } else { + String cryptSalt = Salt.getCryptSalt(salt); + String crypt = getPasswordCryptSalt(clear, Password.CRYPT, cryptSalt) + .getNormalized(); + if (salt.equals(crypt)) newCryptSalt = cryptSalt; + } + } + hashAction = EHashAction.NEW; + } + + if (hashAction == EHashAction.NEW) { // Pas de salt, afficher simplement les versions cryptées des mots // de passe pour tous les schemes. Le salt est choisi au hasard pour // chaque mot de passe. Il est donc différent à chaque fois. @@ -5026,12 +5098,15 @@ public class upassword { ntlm = p.getNtlmHash(); } catch (Password.NotAvailableException e) { } - String crypt = getPasswordAnySalt(clear, Password.CRYPT, null).getNormalized(); + String crypt = getPasswordCryptSalt(clear, Password.CRYPT, newCryptSalt) + .getNormalized(); String sha = getPasswordAnySalt(clear, Password.SHA, null).getNormalized(); String xsha = getPasswordAnySalt(clear, Password.XSHA, null).getNormalized(); - String ssha = getPasswordAnySalt(clear, Password.SSHA, null).getNormalized(); + String ssha = getPasswordBinarySalt(clear, Password.SSHA, newBinarySalt) + .getNormalized(); String md5 = getPasswordAnySalt(clear, Password.MD5, null).getNormalized(); - String smd5 = getPasswordAnySalt(clear, Password.SMD5, null).getNormalized(); + String smd5 = getPasswordBinarySalt(clear, Password.SMD5, newBinarySalt) + .getNormalized(); String aes = null; if (aeskey != null) { try { @@ -5051,7 +5126,7 @@ public class upassword { printvar("md5", md5, shell); printvar("smd5", smd5, shell); if (aes != null) printvar("aes", aes, shell); - } else { + } else if (hashAction == EHashAction.CHECK_MATCH) { // 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. @@ -5113,6 +5188,8 @@ public class upassword { if (salt.equals(crypt)) printvar("match", "true", shell); } } + } else { + throw new Error("bug: hashAction==" + hashAction); } break; }