001/** 002 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS HEADER. 003 * 004 * Copyright (c) 2006 Sun Microsystems Inc. All Rights Reserved 005 * 006 * The contents of this file are subject to the terms 007 * of the Common Development and Distribution License 008 * (the License). You may not use this file except in 009 * compliance with the License. 010 * 011 * You can obtain a copy of the License at 012 * https://opensso.dev.java.net/public/CDDLv1.0.html or 013 * opensso/legal/CDDLv1.0.txt 014 * See the License for the specific language governing 015 * permission and limitations under the License. 016 * 017 * When distributing Covered Code, include this CDDL 018 * Header Notice in each file and include the License file 019 * at opensso/legal/CDDLv1.0.txt. 020 * If applicable, add the following below the CDDL Header, 021 * with the fields enclosed by brackets [] replaced by 022 * your own identifying information: 023 * "Portions Copyrighted [year] [name of copyright owner]" 024 * 025 * $Id: SASLResponse.java,v 1.2 2008/06/25 05:47:08 qcheng Exp $ 026 * 027 */ 028 029 030package com.sun.identity.liberty.ws.authnsvc.protocol; 031 032import java.util.ArrayList; 033import java.util.Iterator; 034import java.util.List; 035 036import org.w3c.dom.Document; 037import org.w3c.dom.Element; 038import org.w3c.dom.Node; 039import org.w3c.dom.NodeList; 040 041import javax.xml.namespace.QName; 042 043import com.sun.identity.shared.xml.XMLUtils; 044import com.sun.identity.shared.encode.Base64; 045import com.sun.identity.liberty.ws.authnsvc.AuthnSvcConstants; 046import com.sun.identity.liberty.ws.authnsvc.AuthnSvcException; 047import com.sun.identity.liberty.ws.authnsvc.AuthnSvcUtils; 048import com.sun.identity.liberty.ws.disco.common.DiscoConstants; 049import com.sun.identity.liberty.ws.disco.ResourceOffering; 050import com.sun.identity.liberty.ws.soapbinding.Utils; 051 052/** 053 * The <code>SASLResponse</code> class represents <code>SASLResponse</code> 054 * element defined in Authentication Service schema. 055 * 056 * @supported.all.api 057 */ 058public class SASLResponse { 059 060 /** 061 * Continue status where the server expects the client to send another 062 * <code>SASLRequest</code> 063 */ 064 public static final String CONTINUE = "continue"; 065 066 /** 067 * Abort status where the server is aborting the authentication exchange. 068 */ 069 public static final String ABORT = "abort"; 070 071 /** 072 * OK status where the server considers the authentication exchange to have 073 * successfully completed. 074 */ 075 public static final String OK = "OK"; 076 077 private String statusCode = null; 078 private PasswordTransforms passwordTransforms = null; 079 private byte[] data = null; 080 private ResourceOffering resourceOffering = null; 081 private List credentials = null; 082 private String serverMechanism = null; 083 private String id = null; 084 private String messageID = null; 085 private String refToMessageID = null; 086 087 /** 088 * Constructs a <code>SASLResponse</code> instance. 089 * 090 * @param statusCode Status Code. 091 */ 092 public SASLResponse(String statusCode) { 093 this.statusCode = statusCode; 094 } 095 096 /** 097 * Constructs a <code>SASLResponse</code> with a 098 * <code>org.w3c.dom.Element</code>. 099 * @param element a <code>SASLResponse</code> element 100 * @exception AuthnSvcException if an error occurs while parsing the 101 * <code>SASLResponse</code> element 102 */ 103 public SASLResponse(Element element) throws AuthnSvcException { 104 Element statusE = null; 105 Element ptE = null; 106 Element dataE = null; 107 Element roE = null; 108 Element credentialsE = null; 109 110 NodeList nl = element.getChildNodes(); 111 int length = nl.getLength(); 112 113 int i; 114 for(i = 0; i < length; i++) { 115 Node child = nl.item(i); 116 if (child.getNodeType() == Node.ELEMENT_NODE) { 117 Element childElement = (Element)child; 118 String localName = childElement.getLocalName(); 119 String namespaceURI = childElement.getNamespaceURI(); 120 121 if (AuthnSvcConstants.NS_AUTHN_SVC.equals(namespaceURI) && 122 AuthnSvcConstants.TAG_STATUS.equals(localName)){ 123 statusE = childElement; 124 break; 125 } else { 126 throw new AuthnSvcException("missingStatus"); 127 } 128 } 129 } 130 131 String statusCodeStr = XMLUtils.getNodeAttributeValue( 132 statusE, 133 AuthnSvcConstants.ATTR_CODE); 134 QName statusCodeQN = Utils.convertStringToQName(statusCodeStr, 135 statusE); 136 if (!AuthnSvcConstants.NS_AUTHN_SVC 137 .equals(statusCodeQN.getNamespaceURI())) { 138 throw new AuthnSvcException("invalidStatusCodeNS"); 139 } 140 141 statusCode = statusCodeQN.getLocalPart(); 142 143 for(i = i + 1; i < length; i++) { 144 Node child = nl.item(i); 145 if (child.getNodeType() == Node.ELEMENT_NODE) { 146 Element childElement = (Element)child; 147 String localName = childElement.getLocalName(); 148 String namespaceURI = childElement.getNamespaceURI(); 149 if (AuthnSvcConstants.NS_AUTHN_SVC.equals(namespaceURI)) { 150 if (AuthnSvcConstants.TAG_STATUS.equals(localName)) { 151 throw new AuthnSvcException("tooManyStatus"); 152 } else if(AuthnSvcConstants.TAG_PASSWORD_TRANSFORMS 153 .equals(localName)){ 154 if (ptE != null) { 155 throw new AuthnSvcException("tooManyPT"); 156 } else if (dataE != null || roE != null || 157 credentialsE != null) { 158 throw new AuthnSvcException("invalidSeq"); 159 } 160 ptE = childElement; 161 } else if(AuthnSvcConstants.TAG_DATA.equals(localName)){ 162 if (dataE != null) { 163 throw new AuthnSvcException("tooManyData"); 164 } else if (roE != null || credentialsE != null) { 165 throw new AuthnSvcException("invalidSeq"); 166 } 167 dataE = childElement; 168 } else if(AuthnSvcConstants.TAG_CREDENTIALS 169 .equals(localName)){ 170 if (credentialsE != null) { 171 throw new AuthnSvcException("tooManyCr"); 172 } 173 credentialsE = childElement; 174 } else { 175 throw new AuthnSvcException("invalidChild"); 176 } 177 } else if (DiscoConstants.DISCO_NS.equals(namespaceURI) && 178 AuthnSvcConstants.TAG_RESOURCE_OFFERING 179 .equals(localName)) { 180 if (roE != null) { 181 throw new AuthnSvcException("tooManyRO"); 182 } else if (credentialsE != null) { 183 throw new AuthnSvcException("invalidSeq"); 184 } 185 roE = childElement; 186 } else { 187 throw new AuthnSvcException("invalidChild"); 188 } 189 } 190 } 191 192 if (ptE != null) { 193 passwordTransforms = new PasswordTransforms(ptE); 194 } 195 196 data = AuthnSvcUtils.decodeDataElement(dataE); 197 198 if (roE != null) { 199 try { 200 resourceOffering = new ResourceOffering(roE); 201 } catch (Exception ex) { 202 throw new AuthnSvcException(ex); 203 } 204 } 205 206 if (credentialsE != null) { 207 credentials = new ArrayList(); 208 nl = credentialsE.getChildNodes(); 209 for(i = 0; i < nl.getLength(); i++) { 210 Node child = nl.item(i); 211 if (child.getNodeType() == Node.ELEMENT_NODE) { 212 credentials.add(child); 213 } 214 } 215 } 216 217 serverMechanism = XMLUtils.getNodeAttributeValue( 218 element, 219 AuthnSvcConstants.ATTR_SERVER_MECHANISM); 220 221 id = XMLUtils.getNodeAttributeValue(element, 222 AuthnSvcConstants.ATTR_id); 223 224 } 225 226 /** 227 * Returns value of attribute 'code' of Element 'Status'. 228 * @return value of attribute 'code' of Element 'Status' 229 * @see #setStatusCode(String) 230 */ 231 public String getStatusCode() 232 { 233 return statusCode; 234 } 235 236 /** 237 * Returns child Element 'PasswordTransforms'. 238 * @return child Element 'PasswordTransforms' 239 * @see #setPasswordTransforms(PasswordTransforms) 240 */ 241 public PasswordTransforms getPasswordTransforms() 242 { 243 return passwordTransforms; 244 } 245 246 /** 247 * Returns value of Element 'Data'. 248 * @return value of Element 'Data' 249 * @see #setData(byte[]) 250 */ 251 public byte[] getData() 252 { 253 return data; 254 } 255 256 /** 257 * Returns Element <code>ResourceOffering</code>. 258 * @return Element <code>ResourceOffering</code>. 259 * @see #setResourceOffering(ResourceOffering) 260 */ 261 public ResourceOffering getResourceOffering() { 262 return resourceOffering; 263 } 264 265 /** 266 * Returns a list of child Element of 'Credentials' Element. 267 * @return a list of child Element of 'Credentials' Element 268 * @see #setCredentials(List) 269 */ 270 public List getCredentials() { 271 return credentials; 272 } 273 274 /** 275 * Returns value of <code>serverMechanism</code> attribute. 276 * @return value of <code>serverMechanism</code> attribute 277 * @see #setServerMechanism(String) 278 */ 279 public String getServerMechanism() { 280 return serverMechanism; 281 } 282 283 /** 284 * Returns value of <code>id</code> attribute. 285 * @return value of <code>id</code> attribute 286 * @see #setId(String) 287 */ 288 public String getId() { 289 return id; 290 } 291 292 /** 293 * Returns value of <code>messageID</code> attribute of 294 * <code>CorrelationHeader</code>. 295 * @return value of <code>messageID</code> attribute 296 * @see #setMessageID(String) 297 */ 298 public String getMessageID() { 299 return messageID; 300 } 301 302 /** 303 * Returns value of <code>refToMessageID</code> attribute of 304 * <code>CorrelationHeader</code>. 305 * @return value of <code>refToMessageID</code> attribute 306 * @see #setRefToMessageID(String) 307 */ 308 public String getRefToMessageID() { 309 return refToMessageID; 310 } 311 312 /** 313 * Sets value of attribute 'code' of Element 'Status'. 314 * @param statusCode value of attribute 'code' of Element 'Status' 315 * @see #getStatusCode() 316 */ 317 public void setStatusCode(String statusCode) { 318 this.statusCode = statusCode; 319 } 320 321 /** 322 * Sets child Element 'PasswordTransforms' 323 * @param passwordTransforms Element 'PasswordTransforms' 324 * @see #getPasswordTransforms() 325 */ 326 public void setPasswordTransforms(PasswordTransforms passwordTransforms) 327 { 328 this.passwordTransforms = passwordTransforms; 329 } 330 331 /** 332 * Sets value of Element 'Data'. 333 * @param data value of Element 'Data' 334 * @see #getData() 335 */ 336 public void setData(byte[] data) { 337 this.data = data; 338 } 339 340 /** 341 * Sets Element <code>ResourceOffering</code>. 342 * @param resourceOffering Element <code>ResourceOffering</code> 343 * @see #getResourceOffering() 344 */ 345 public void setResourceOffering(ResourceOffering resourceOffering) { 346 this.resourceOffering = resourceOffering; 347 } 348 349 /** 350 * Sets a list of child Elements of 'Credentials' Element. 351 * @param credentials a list of child Elements of 'Credentials' Element 352 * @see #getCredentials() 353 */ 354 public void setCredentials(List credentials) { 355 this.credentials = credentials; 356 } 357 358 /** 359 * Sets value of <code>mechanism</code> attribute. 360 * @param serverMechanism value of <code>mechanism</code> attribute 361 * @see #getServerMechanism() 362 */ 363 public void setServerMechanism(String serverMechanism) { 364 this.serverMechanism = serverMechanism; 365 } 366 367 /** 368 * Sets value of <code>id</code> attribute. 369 * @param id value of <code>id</code> attribute 370 * @see #getId() 371 */ 372 public void setId(String id) { 373 this.id = id; 374 } 375 376 /** 377 * Sets value of <code>messageID</code> attribute of 378 * <code>CorrelationHeader</code>. 379 * @param messageID value of <code>messageID</code> attribute 380 * @see #getMessageID() 381 */ 382 public void setMessageID(String messageID) { 383 this.messageID = messageID; 384 } 385 386 /** 387 * Sets value of <code>refToMessageID</code> attribute of 388 * <code>CorrelationHeader</code>. 389 * @param refToMessageID value of <code>refToMessageID</code> attribute 390 * @see #getRefToMessageID() 391 */ 392 public void setRefToMessageID(String refToMessageID) { 393 this.refToMessageID = refToMessageID; 394 } 395 396 /** 397 * Returns <code>SASLResponse</code> in <code>org.w3c.dom.Element</code> 398 * format. 399 * 400 * @return <code>SASLResponse</code> in <code>org.w3c.dom.Element</code> 401 * format. 402 * @exception AuthnSvcException if an error occurs while creating the 403 * <code>SASLResponse</code> element 404 */ 405 public Element toElement() throws AuthnSvcException { 406 Document doc = null; 407 try { 408 doc = XMLUtils.newDocument(); 409 } catch (Exception ex) { 410 AuthnSvcUtils.debug.error("SASLResponse:toElement", ex); 411 throw new AuthnSvcException(ex.getMessage()); 412 } 413 414 Element saslRespE = doc.createElementNS(AuthnSvcConstants.NS_AUTHN_SVC, 415 AuthnSvcConstants.PTAG_SASL_RESPONSE); 416 saslRespE.setAttributeNS(AuthnSvcConstants.NS_XML, 417 AuthnSvcConstants.XMLNS_AUTHN_SVC, 418 AuthnSvcConstants.NS_AUTHN_SVC); 419 saslRespE.setAttributeNS(AuthnSvcConstants.NS_XML, 420 AuthnSvcConstants.XMLNS_DISCO, 421 DiscoConstants.DISCO_NS); 422 423 Element statusE = doc.createElementNS(AuthnSvcConstants.NS_AUTHN_SVC, 424 AuthnSvcConstants.PTAG_STATUS); 425 statusE.setAttributeNS(null, AuthnSvcConstants.ATTR_CODE, 426 AuthnSvcConstants.PREFIX_AUTHN_SVC + ":" + statusCode); 427 saslRespE.appendChild(statusE); 428 429 if (passwordTransforms != null) { 430 passwordTransforms.addToParent(saslRespE); 431 } 432 433 if (data != null) { 434 Element dataE = doc.createElementNS(AuthnSvcConstants.NS_AUTHN_SVC, 435 AuthnSvcConstants.PTAG_DATA); 436 dataE.appendChild(doc.createTextNode(Base64.encode(data))); 437 saslRespE.appendChild(dataE); 438 } 439 440 if (resourceOffering != null) { 441 Document roDoc = 442 XMLUtils.toDOMDocument(resourceOffering.toString(), 443 AuthnSvcUtils.debug); 444 if (roDoc == null) { 445 throw new AuthnSvcException("invalidRO"); 446 } 447 saslRespE.appendChild(doc.importNode(roDoc.getDocumentElement(), 448 true)); 449 } 450 451 if (credentials != null && !credentials.isEmpty()) { 452 Element credentialsE = 453 doc.createElementNS(AuthnSvcConstants.NS_AUTHN_SVC, 454 AuthnSvcConstants.PTAG_CREDENTIALS); 455 Iterator iter = credentials.iterator(); 456 while (iter.hasNext()) { 457 credentialsE.appendChild(doc.importNode((Element)iter.next(), 458 true)); 459 } 460 saslRespE.appendChild(credentialsE); 461 } 462 463 if (serverMechanism != null) { 464 saslRespE.setAttributeNS(null, 465 AuthnSvcConstants.ATTR_SERVER_MECHANISM, 466 serverMechanism); 467 } 468 469 if (id != null) { 470 saslRespE.setAttributeNS(null, AuthnSvcConstants.ATTR_id, id); 471 } 472 473 doc.appendChild(saslRespE); 474 return doc.getDocumentElement(); 475 } 476}