SaslNonza.java

  1. /**
  2.  *
  3.  * Copyright 2014-2019 Florian Schmaus
  4.  *
  5.  * Licensed under the Apache License, Version 2.0 (the "License");
  6.  * you may not use this file except in compliance with the License.
  7.  * You may obtain a copy of the License at
  8.  *
  9.  *     http://www.apache.org/licenses/LICENSE-2.0
  10.  *
  11.  * Unless required by applicable law or agreed to in writing, software
  12.  * distributed under the License is distributed on an "AS IS" BASIS,
  13.  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
  14.  * See the License for the specific language governing permissions and
  15.  * limitations under the License.
  16.  */
  17. package org.jivesoftware.smack.sasl.packet;

  18. import java.util.Map;

  19. import javax.xml.namespace.QName;

  20. import org.jivesoftware.smack.packet.AbstractError;
  21. import org.jivesoftware.smack.packet.Nonza;
  22. import org.jivesoftware.smack.packet.XmlEnvironment;
  23. import org.jivesoftware.smack.sasl.SASLError;
  24. import org.jivesoftware.smack.util.Objects;
  25. import org.jivesoftware.smack.util.StringUtils;
  26. import org.jivesoftware.smack.util.XmlStringBuilder;

  27. public interface SaslNonza extends Nonza {
  28.     String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-sasl";

  29.     @Override
  30.     default String getNamespace() {
  31.         return NAMESPACE;
  32.     }

  33.     /**
  34.      * Initiating SASL authentication by select a mechanism.
  35.      */
  36.     class AuthMechanism implements SaslNonza {
  37.         public static final String ELEMENT = "auth";
  38.         public static final QName QNAME = new QName(NAMESPACE, ELEMENT);

  39.         private final String mechanism;
  40.         private final String authenticationText;

  41.         public AuthMechanism(String mechanism, String authenticationText) {
  42.             this.mechanism = Objects.requireNonNull(mechanism, "SASL mechanism shouldn't be null.");
  43.             this.authenticationText = StringUtils.requireNotNullNorEmpty(authenticationText,
  44.                             "SASL authenticationText must not be null nor empty (RFC6120 6.4.2)");
  45.         }

  46.         @Override
  47.         public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) {
  48.             XmlStringBuilder xml = new XmlStringBuilder(this, xmlEnvironment);
  49.             xml.attribute("mechanism", mechanism).rightAngleBracket();
  50.             xml.escape(authenticationText);
  51.             xml.closeElement(this);
  52.             return xml;
  53.         }

  54.         public String getMechanism() {
  55.             return mechanism;
  56.         }

  57.         public String getAuthenticationText() {
  58.             return authenticationText;
  59.         }

  60.         @Override
  61.         public String getElementName() {
  62.             return ELEMENT;
  63.         }
  64.     }

  65.     /**
  66.      * A SASL challenge stream element.
  67.      */
  68.     class Challenge implements SaslNonza {
  69.         public static final String ELEMENT = "challenge";
  70.         public static final QName QNAME = new QName(NAMESPACE, ELEMENT);

  71.         private final String data;

  72.         public Challenge(String data) {
  73.             this.data = StringUtils.returnIfNotEmptyTrimmed(data);
  74.         }

  75.         public String getData() {
  76.             return data;
  77.         }

  78.         @Override
  79.         public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) {
  80.             XmlStringBuilder xml = new XmlStringBuilder(this, xmlEnvironment);
  81.             xml.optTextChild(data, this);
  82.             return xml;
  83.         }

  84.         @Override
  85.         public String getElementName() {
  86.             return ELEMENT;
  87.         }
  88.     }

  89.     /**
  90.      * A SASL response stream element.
  91.      */
  92.     class Response implements SaslNonza {
  93.         public static final String ELEMENT = "response";
  94.         public static final QName QNAME = new QName(NAMESPACE, ELEMENT);

  95.         private final String authenticationText;

  96.         public Response() {
  97.             authenticationText = null;
  98.         }

  99.         public Response(String authenticationText) {
  100.             this.authenticationText = StringUtils.returnIfNotEmptyTrimmed(authenticationText);
  101.         }

  102.         @Override
  103.         public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) {
  104.             XmlStringBuilder xml = new XmlStringBuilder(this, xmlEnvironment);
  105.             xml.optTextChild(authenticationText, this);
  106.             return xml;
  107.         }

  108.         public String getAuthenticationText() {
  109.             return authenticationText;
  110.         }

  111.         @Override
  112.         public String getElementName() {
  113.             return ELEMENT;
  114.         }
  115.     }

  116.     /**
  117.      * A SASL success stream element.
  118.      */
  119.     class Success implements SaslNonza {
  120.         public static final String ELEMENT = "success";
  121.         public static final QName QNAME = new QName(NAMESPACE, ELEMENT);

  122.         private final String data;

  123.         /**
  124.          * Construct a new SASL success stream element with optional additional data for the SASL layer.
  125.          * (RFC6120 6.3.10)
  126.          *
  127.          * @param data additional data for the SASL layer or <code>null</code>
  128.          */
  129.         public Success(String data) {
  130.             this.data = StringUtils.returnIfNotEmptyTrimmed(data);
  131.         }

  132.         /**
  133.          * Returns additional data for the SASL layer or <code>null</code>.
  134.          *
  135.          * @return additional data or <code>null</code>
  136.          */
  137.         public String getData() {
  138.             return data;
  139.         }

  140.         @Override
  141.         public XmlStringBuilder toXML(XmlEnvironment xmlEnvironment) {
  142.             XmlStringBuilder xml = new XmlStringBuilder(this, xmlEnvironment);
  143.             xml.optTextChild(data, this);
  144.             return xml;
  145.         }

  146.         @Override
  147.         public String getElementName() {
  148.             return ELEMENT;
  149.         }
  150.     }

  151.     /**
  152.      * A SASL failure stream element, also called "SASL Error".
  153.      * @see <a href="http://xmpp.org/rfcs/rfc6120.html#sasl-errors">RFC 6120 6.5 SASL Errors</a>
  154.      */
  155.     class SASLFailure extends AbstractError implements SaslNonza {
  156.         public static final String ELEMENT = "failure";
  157.         public static final QName QNAME = new QName(NAMESPACE, ELEMENT);

  158.         private final SASLError saslError;
  159.         private final String saslErrorString;

  160.         public SASLFailure(String saslError) {
  161.             this(saslError, null);
  162.         }

  163.         public SASLFailure(String saslError, Map<String, String> descriptiveTexts) {
  164.             super(descriptiveTexts);
  165.             SASLError error = SASLError.fromString(saslError);
  166.             if (error == null) {
  167.                 // RFC6120 6.5 states that unknown condition must be treat as generic authentication
  168.                 // failure.
  169.                 this.saslError = SASLError.not_authorized;
  170.             }
  171.             else {
  172.                 this.saslError = error;
  173.             }
  174.             this.saslErrorString = saslError;
  175.         }

  176.         /**
  177.          * Get the SASL related error condition.
  178.          *
  179.          * @return the SASL related error condition.
  180.          */
  181.         public SASLError getSASLError() {
  182.             return saslError;
  183.         }

  184.         /**
  185.          * Get the SASL error as String.
  186.          * @return the SASL error as String
  187.          */
  188.         public String getSASLErrorString() {
  189.             return saslErrorString;
  190.         }

  191.         @Override
  192.         public XmlStringBuilder toXML(org.jivesoftware.smack.packet.XmlEnvironment enclosingNamespace) {
  193.             XmlStringBuilder xml = new XmlStringBuilder();
  194.             xml.halfOpenElement(ELEMENT).xmlnsAttribute(NAMESPACE).rightAngleBracket();
  195.             xml.emptyElement(saslErrorString);
  196.             addDescriptiveTextsAndExtensions(xml);
  197.             xml.closeElement(ELEMENT);
  198.             return xml;
  199.         }

  200.         @Override
  201.         public String toString() {
  202.             return toXML().toString();
  203.         }

  204.         @Override
  205.         public String getElementName() {
  206.             return ELEMENT;
  207.         }
  208.     }
  209. }