SaslStreamElements.java

  1. /**
  2.  *
  3.  * Copyright 2014 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 org.jivesoftware.smack.packet.AbstractError;
  20. import org.jivesoftware.smack.packet.PlainStreamElement;
  21. import org.jivesoftware.smack.sasl.SASLError;
  22. import org.jivesoftware.smack.util.Objects;
  23. import org.jivesoftware.smack.util.StringUtils;
  24. import org.jivesoftware.smack.util.XmlStringBuilder;

  25. public class SaslStreamElements {
  26.     public static final String NAMESPACE = "urn:ietf:params:xml:ns:xmpp-sasl";

  27.     /**
  28.      * Initiating SASL authentication by select a mechanism.
  29.      */
  30.     public static class AuthMechanism implements PlainStreamElement {
  31.         public static final String ELEMENT = "auth";

  32.         private final String mechanism;
  33.         private final String authenticationText;

  34.         public AuthMechanism(String mechanism, String authenticationText) {
  35.             this.mechanism = Objects.requireNonNull(mechanism, "SASL mechanism shouldn't be null.");
  36.             this.authenticationText = StringUtils.requireNotNullOrEmpty(authenticationText,
  37.                             "SASL authenticationText must not be null or empty (RFC6120 6.4.2)");
  38.         }

  39.         @Override
  40.         public XmlStringBuilder toXML() {
  41.             XmlStringBuilder xml = new XmlStringBuilder();
  42.             xml.halfOpenElement(ELEMENT).xmlnsAttribute(NAMESPACE).attribute("mechanism", mechanism).rightAngleBracket();
  43.             xml.optAppend(authenticationText);
  44.             xml.closeElement(ELEMENT);
  45.             return xml;
  46.         }

  47.         public String getMechanism() {
  48.             return mechanism;
  49.         }

  50.         public String getAuthenticationText() {
  51.             return authenticationText;
  52.         }
  53.     }

  54.     /**
  55.      * A SASL challenge stream element.
  56.      */
  57.     public static class Challenge implements PlainStreamElement {
  58.         public static final String ELEMENT = "challenge";

  59.         private final String data;

  60.         public Challenge(String data) {
  61.             this.data = StringUtils.returnIfNotEmptyTrimmed(data);
  62.         }

  63.         @Override
  64.         public XmlStringBuilder toXML() {
  65.             XmlStringBuilder xml = new XmlStringBuilder().halfOpenElement(ELEMENT).xmlnsAttribute(
  66.                             NAMESPACE).rightAngleBracket();
  67.             xml.optAppend(data);
  68.             xml.closeElement(ELEMENT);
  69.             return xml;
  70.         }
  71.     }

  72.     /**
  73.      * A SASL response stream element.
  74.      */
  75.     public static class Response implements PlainStreamElement {
  76.         public static final String ELEMENT = "response";

  77.         private final String authenticationText;

  78.         public Response() {
  79.             authenticationText = null;
  80.         }

  81.         public Response(String authenticationText) {
  82.             this.authenticationText = StringUtils.returnIfNotEmptyTrimmed(authenticationText);
  83.         }

  84.         @Override
  85.         public XmlStringBuilder toXML() {
  86.             XmlStringBuilder xml = new XmlStringBuilder();
  87.             xml.halfOpenElement(ELEMENT).xmlnsAttribute(NAMESPACE).rightAngleBracket();
  88.             xml.optAppend(authenticationText);
  89.             xml.closeElement(ELEMENT);
  90.             return xml;
  91.         }

  92.         public String getAuthenticationText() {
  93.             return authenticationText;
  94.         }
  95.     }

  96.     /**
  97.      * A SASL success stream element.
  98.      */
  99.     public static class Success implements PlainStreamElement {
  100.         public static final String ELEMENT = "success";

  101.         final private String data;

  102.         /**
  103.          * Construct a new SASL success stream element with optional additional data for the SASL layer
  104.          * (RFC6120 6.3.10)
  105.          *
  106.          * @param data additional data for the SASL layer or <code>null</code>
  107.          */
  108.         public Success(String data) {
  109.             this.data = StringUtils.returnIfNotEmptyTrimmed(data);
  110.         }

  111.         /**
  112.          * Returns additional data for the SASL layer or <code>null</code>.
  113.          *
  114.          * @return additional data or <code>null</code>
  115.          */
  116.         public String getData() {
  117.             return data;
  118.         }

  119.         @Override
  120.         public XmlStringBuilder toXML() {
  121.             XmlStringBuilder xml = new XmlStringBuilder();
  122.             xml.halfOpenElement(ELEMENT).xmlnsAttribute(NAMESPACE).rightAngleBracket();
  123.             xml.optAppend(data);
  124.             xml.closeElement(ELEMENT);
  125.             return xml;
  126.         }
  127.     }

  128.     /**
  129.      * A SASL failure stream element, also called "SASL Error"
  130.      * @see <a href="http://xmpp.org/rfcs/rfc6120.html#sasl-errors">RFC 6120 6.5 SASL Errors</a>
  131.      */
  132.     public static class SASLFailure extends AbstractError implements PlainStreamElement {
  133.         public static final String ELEMENT = "failure";

  134.         private final SASLError saslError;
  135.         private final String saslErrorString;

  136.         public SASLFailure(String saslError) {
  137.             this(saslError, null);
  138.         }

  139.         public SASLFailure(String saslError, Map<String, String> descriptiveTexts) {
  140.             super(descriptiveTexts);
  141.             SASLError error = SASLError.fromString(saslError);
  142.             if (error == null) {
  143.                 // RFC6120 6.5 states that unknown condition must be treat as generic authentication
  144.                 // failure.
  145.                 this.saslError = SASLError.not_authorized;
  146.             }
  147.             else {
  148.                 this.saslError = error;
  149.             }
  150.             this.saslErrorString = saslError;
  151.         }

  152.         /**
  153.          * Get the SASL related error condition.
  154.          *
  155.          * @return the SASL related error condition.
  156.          */
  157.         public SASLError getSASLError() {
  158.             return saslError;
  159.         }

  160.         /**
  161.          * @return the SASL error as String
  162.          */
  163.         public String getSASLErrorString() {
  164.             return saslErrorString;
  165.         }

  166.         @Override
  167.         public XmlStringBuilder toXML() {
  168.             XmlStringBuilder xml = new XmlStringBuilder();
  169.             xml.halfOpenElement(ELEMENT).xmlnsAttribute(NAMESPACE).rightAngleBracket();
  170.             xml.emptyElement(saslErrorString);
  171.             addDescriptiveTextsAndExtensions(xml);
  172.             xml.closeElement(ELEMENT);
  173.             return xml;
  174.         }

  175.         @Override
  176.         public String toString() {
  177.             return toXML().toString();
  178.         }
  179.     }
  180. }