1package eu.siacs.conversations.crypto.sasl;
2
3import com.google.common.base.Strings;
4
5import java.security.SecureRandom;
6
7import eu.siacs.conversations.entities.Account;
8import eu.siacs.conversations.xml.Element;
9import eu.siacs.conversations.xml.Namespace;
10import eu.siacs.conversations.xml.TagWriter;
11
12public abstract class SaslMechanism {
13
14 final protected TagWriter tagWriter;
15 final protected Account account;
16 final protected SecureRandom rng;
17
18 protected enum State {
19 INITIAL,
20 AUTH_TEXT_SENT,
21 RESPONSE_SENT,
22 VALID_SERVER_RESPONSE,
23 }
24
25 public static class AuthenticationException extends Exception {
26 public AuthenticationException(final String message) {
27 super(message);
28 }
29
30 public AuthenticationException(final Exception inner) {
31 super(inner);
32 }
33
34 public AuthenticationException(final String message, final Exception exception) {
35 super(message, exception);
36 }
37 }
38
39 public static class InvalidStateException extends AuthenticationException {
40 public InvalidStateException(final String message) {
41 super(message);
42 }
43
44 public InvalidStateException(final State state) {
45 this("Invalid state: " + state.toString());
46 }
47 }
48
49 public SaslMechanism(final TagWriter tagWriter, final Account account, final SecureRandom rng) {
50 this.tagWriter = tagWriter;
51 this.account = account;
52 this.rng = rng;
53 }
54
55 /**
56 * The priority is used to pin the authentication mechanism. If authentication fails, it MAY be retried with another
57 * mechanism of the same priority, but MUST NOT be tried with a mechanism of lower priority (to prevent downgrade
58 * attacks).
59 *
60 * @return An arbitrary int representing the priority
61 */
62 public abstract int getPriority();
63
64 public abstract String getMechanism();
65
66 public String getClientFirstMessage() {
67 return "";
68 }
69
70 public String getResponse(final String challenge) throws AuthenticationException {
71 return "";
72 }
73
74 public enum Version {
75 SASL, SASL_2;
76
77 public static Version of(final Element element) {
78 switch ( Strings.nullToEmpty(element.getNamespace())) {
79 case Namespace.SASL:
80 return SASL;
81 case Namespace.SASL_2:
82 return SASL_2;
83 default:
84 throw new IllegalArgumentException("Unrecognized SASL namespace");
85 }
86 }
87 }
88}