");
}
sprint("}");
}
} catch (IllegalAccessException ex1) {
continue; // we are accessing a private field...
}
}
sprint("}");
return stringRepresentation;
}
/**
* Formatter with a given starting indentation (for nested structs).
* @param indent int to set
* @return String
*/
public String debugDump(int indent) {
int save = indentation;
indentation = indent;
String retval = this.debugDump();
indentation = save;
return retval;
}
/** Encode this to a string.
*
*@return string representation for this object.
*/
public String toString() {
return this.encode();
}
}
java/gov/nist/javax/sip/address/NetObjectList.java 0100644 0000000 0000000 00000007661 13513104763 021220 0 ustar 00 0000000 0000000 /*
* Conditions Of Use
*
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), an agency of the Federal Government.
* Pursuant to title 15 Untied States Code Section 105, works of NIST
* employees are not subject to copyright protection in the United States
* and are considered to be in the public domain. As a result, a formal
* license is not needed to use the software.
*
* This software is provided by NIST as a service and is expressly
* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY. NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement
*
* .
*
*/
/*******************************************************************************
* Product of NIST/ITL Advanced Networking Technologies Division (ANTD). *
*******************************************************************************/
package gov.nist.javax.sip.address;
import gov.nist.core.*;
import java.util.ListIterator;
import java.util.LinkedList;
import java.util.Iterator;
import java.lang.reflect.*;
/**
* Root class for all the collection objects in this list:
* a wrapper class on the GenericObjectList class for lists of objects
* that can appear in NetObjects.
* IMPORTANT NOTE: NetObjectList cannot derive from NetObject as this
* will screw up the way in which we attach objects to headers.
*
*@version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:22 $
*
*@author M. Ranganathan
*
*
*
*/
public class NetObjectList extends GenericObjectList {
/**
*
*/
private static final long serialVersionUID = -1551780600806959023L;
/**
* Construct a NetObject List given a list name.
* @param lname String to set
*/
public NetObjectList(String lname) {
super(lname);
}
/**
* Construct a NetObject List given a list name and a class for
* the objects that go into the list.
* @param lname String to set
* @param cname Class to set
*/
public NetObjectList(String lname, Class> cname) {
super(lname, cname);
}
/**
* Construct an empty NetObjectList.
*/
public NetObjectList() {
super();
}
/**
* Add a new object to the list.
* @param obj NetObject to set
*/
public void add(NetObject obj) {
super.add(obj);
}
/** concatenate the two Lists
* @param net_obj_list NetObjectList to set
*/
public void concatenate(NetObjectList net_obj_list) {
super.concatenate(net_obj_list);
}
/** returns the first element
* @return GenericObject
*/
public GenericObject first() {
return (NetObject) super.first();
}
/** returns the next element
* @return GenericObject
*/
public GenericObject next() {
return (NetObject) super.next();
}
/** returns the next element
* @param li ListIterator to set
* @return GenericObject
*/
public GenericObject next(ListIterator li) {
return (NetObject) super.next(li);
}
/** set the class
* @param cl Class to set
*/
public void setMyClass(Class cl) {
super.setMyClass(cl);
}
/**
* Convert to a string given an indentation(for pretty printing).
* @param indent int to set
* @return String
*/
public String debugDump(int indent) {
return super.debugDump(indent);
}
/**
* Encode this to a string.
*
*@return a string representation for this object.
*/
public String toString() {
return this.encode();
}
}
java/gov/nist/javax/sip/address/ParameterNames.java 0100644 0000000 0000000 00000010736 13513104763 021410 0 ustar 00 0000000 0000000 /*
* Conditions Of Use
*
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), an agency of the Federal Government.
* Pursuant to title 15 Untied States Code Section 105, works of NIST
* employees are not subject to copyright protection in the United States
* and are considered to be in the public domain. As a result, a formal
* license is not needed to use the software.
*
* This software is provided by NIST as a service and is expressly
* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY. NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement
*
* .
*
*/
package gov.nist.javax.sip.address;
/**
* Common parameter names.
*
* @version 1.2 $Revision: 1.6 $ $Date: 2009/07/17 18:57:22 $
*
* @author M. Ranganathan
*
*
*/
public interface ParameterNames {
public static final String SIP_URI_SCHEME = "sip";
public static final String SIPS_URI_SCHEME = "sips";
public static final String TEL_URI_SCHEME = "tel";
public static final String POSTDIAL = "postdial";
public static final String PHONE_CONTEXT_TAG = "context-tag";
public static final String ISUB = "isub";
public static final String PROVIDER_TAG = "provider-tag";
public static final String UDP = GenericURI.UDP;
public static final String TCP = GenericURI.TCP;
public static final String TLS = GenericURI.TLS;
}
/*
* $Log: ParameterNames.java,v $
* Revision 1.6 2009/07/17 18:57:22 emcho
* Converts indentation tabs to spaces so that we have a uniform indentation policy in the whole project.
*
* Revision 1.5 2006/07/13 09:02:30 mranga
* Issue number:
* Obtained from:
* Submitted by: jeroen van bemmel
* Reviewed by: mranga
* Moved some changes from jain-sip-1.2 to java.net
*
* CVS: ----------------------------------------------------------------------
* CVS: Issue number:
* CVS: If this change addresses one or more issues,
* CVS: then enter the issue number(s) here.
* CVS: Obtained from:
* CVS: If this change has been taken from another system,
* CVS: then name the system in this line, otherwise delete it.
* CVS: Submitted by:
* CVS: If this code has been contributed to the project by someone else; i.e.,
* CVS: they sent us a patch or a set of diffs, then include their name/email
* CVS: address here. If this is your work then delete this line.
* CVS: Reviewed by:
* CVS: If we are doing pre-commit code reviews and someone else has
* CVS: reviewed your changes, include their name(s) here.
* CVS: If you have not had it reviewed then delete this line.
*
* Revision 1.3 2006/06/19 06:47:26 mranga
* javadoc fixups
*
* Revision 1.2 2006/06/16 15:26:29 mranga
* Added NIST disclaimer to all public domain files. Clean up some javadoc. Fixed a leak
*
* Revision 1.1.1.1 2005/10/04 17:12:34 mranga
*
* Import
*
*
* Revision 1.3 2004/10/28 19:02:49 mranga
* Submitted by: Daniel Martinez
* Reviewed by: M. Ranganathan
*
* Added changes for TLS support contributed by Daniel Martinez
*
* Revision 1.2 2004/01/22 13:26:28 sverker
* Issue number:
* Obtained from:
* Submitted by: sverker
* Reviewed by: mranga
*
* Major reformat of code to conform with style guide. Resolved compiler and javadoc warnings. Added CVS tags.
*
* CVS: ----------------------------------------------------------------------
* CVS: Issue number:
* CVS: If this change addresses one or more issues,
* CVS: then enter the issue number(s) here.
* CVS: Obtained from:
* CVS: If this change has been taken from another system,
* CVS: then name the system in this line, otherwise delete it.
* CVS: Submitted by:
* CVS: If this code has been contributed to the project by someone else; i.e.,
* CVS: they sent us a patch or a set of diffs, then include their name/email
* CVS: address here. If this is your work then delete this line.
* CVS: Reviewed by:
* CVS: If we are doing pre-commit code reviews and someone else has
* CVS: reviewed your changes, include their name(s) here.
* CVS: If you have not had it reviewed then delete this line.
*
*/
java/gov/nist/javax/sip/address/RFC2396UrlDecoder.java 0100644 0000000 0000000 00000010231 13513104763 021401 0 ustar 00 0000000 0000000 /*
* Conditions Of Use
*
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), an agency of the Federal Government.
* Pursuant to title 15 Untied States Code Section 105, works of NIST
* employees are not subject to copyright protection in the United States
* and are considered to be in the public domain. As a result, a formal
* license is not needed to use the software.
*
* This software is provided by NIST as a service and is expressly
* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY. NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement
*
* .
*
*/
package gov.nist.javax.sip.address;
import java.io.UnsupportedEncodingException;
/**
* Copied from Apache Excalibur project.
* Source code available at http://www.google.com/codesearch?hl=en&q=+excalibur+decodePath+show:sK_gDY0W5Rw:OTjCHAiSuF0:th3BdHtpX20&sa=N&cd=1&ct=rc&cs_p=http://apache.edgescape.com/excalibur/excalibur-sourceresolve/source/excalibur-sourceresolve-1.1-src.zip&cs_f=excalibur-sourceresolve-1.1/src/java/org/apache/excalibur/source/SourceUtil.java
* @author Jean Deruelle
*
*/
public class RFC2396UrlDecoder {
/**
* Decode a path.
*
* Interprets %XX (where XX is hexadecimal number) as UTF-8 encoded bytes.
*
The validity of the input path is not checked (i.e. characters that
* were not encoded will not be reported as errors).
*
This method differs from URLDecoder.decode in that it always uses UTF-8
* (while URLDecoder uses the platform default encoding, often ISO-8859-1),
* and doesn't translate + characters to spaces.
*
* @param uri the path to decode
* @return the decoded path
*/
public static String decode(String uri) {
StringBuffer translatedUri = new StringBuffer(uri.length());
byte[] encodedchars = new byte[uri.length() / 3];
int i = 0;
int length = uri.length();
int encodedcharsLength = 0;
while (i < length) {
if (uri.charAt(i) == '%') {
//we must process all consecutive %-encoded characters in one go, because they represent
//an UTF-8 encoded string, and in UTF-8 one character can be encoded as multiple bytes
while (i < length && uri.charAt(i) == '%') {
if (i + 2 < length) {
try {
byte x = (byte)Integer.parseInt(uri.substring(i + 1, i + 3), 16);
encodedchars[encodedcharsLength] = x;
} catch (NumberFormatException e) {
throw new IllegalArgumentException("Illegal hex characters in pattern %" + uri.substring(i + 1, i + 3));
}
encodedcharsLength++;
i += 3;
} else {
throw new IllegalArgumentException("% character should be followed by 2 hexadecimal characters.");
}
}
try {
String translatedPart = new String(encodedchars, 0, encodedcharsLength, "UTF-8");
translatedUri.append(translatedPart);
} catch (UnsupportedEncodingException e) {
//the situation that UTF-8 is not supported is quite theoretical, so throw a runtime exception
throw new RuntimeException("Problem in decodePath: UTF-8 encoding not supported.");
}
encodedcharsLength = 0;
} else {
//a normal character
translatedUri.append(uri.charAt(i));
i++;
}
}
return translatedUri.toString();
}
} java/gov/nist/javax/sip/address/RouterExt.java 0100644 0000000 0000000 00000002526 13513104763 020443 0 ustar 00 0000000 0000000 /*
* Conditions Of Use
*
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), an agency of the Federal Government.
* Pursuant to title 15 Untied States Code Section 105, works of NIST
* employees are not subject to copyright protection in the United States
* and are considered to be in the public domain. As a result, a formal
* license is not needed to use the software.
*
* This software is provided by NIST as a service and is expressly
* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY. NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement
*
*
*/
package gov.nist.javax.sip.address;
import javax.sip.address.Hop;
import javax.sip.address.Router;
/**
*
*/
public interface RouterExt extends Router {
/**
* Record that a transaction failure occured for the given hop.
*
*/
public void transactionTimeout(Hop hop);
}
java/gov/nist/javax/sip/address/SipURIExt.java 0100644 0000000 0000000 00000001574 13513104763 020300 0 ustar 00 0000000 0000000 package gov.nist.javax.sip.address;
import javax.sip.address.SipURI;
/**
* URI Interface extensions that will be added to version 2.0 of the JSR 32 spec.
*
* @author mranga
*
* @since 2.0
*
*/
public interface SipURIExt extends SipURI {
/**
* Strip the headers that are tacked to the URI.
*
* @since 2.0
*/
public void removeHeaders();
/**
* Strip a specific header tacked to the URI.
*
* @param headerName -- the name of the header.
*
* @since 2.0
*/
public void removeHeader(String headerName);
/**
* Returns whether the gr
parameter is set.
*
* @since 2.0
*/
public boolean hasGrParam();
/**
* Sets the gr
parameter.
*
* @param value -- the GRUU param value.
*
* @since 2.0
*/
public void setGrParam(String value);
}
java/gov/nist/javax/sip/address/SipUri.java 0100644 0000000 0000000 00000102122 13513104763 017706 0 ustar 00 0000000 0000000 /*
* Conditions Of Use
*
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), an agency of the Federal Government.
* Pursuant to title 15 Untied States Code Section 105, works of NIST
* employees are not subject to copyright protection in the United States
* and are considered to be in the public domain. As a result, a formal
* license is not needed to use the software.
*
* This software is provided by NIST as a service and is expressly
* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY. NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement
*
* .
*
*/
/*******************************************************************************
* Product of NIST/ITL Advanced Networking Technologies Division (ANTD). *
*******************************************************************************/
package gov.nist.javax.sip.address;
/*
*Bug fix contributions
*Daniel J. Martinez Manzano
*Stefan Marx.
*pmusgrave@newheights.com (Additions for gruu and outbound drafts)
*Jeroen van Bemmel ( additions for SCTP transport )
*/
import gov.nist.core.*;
import java.util.*;
import java.text.ParseException;
import javax.sip.PeerUnavailableException;
import javax.sip.SipFactory;
import javax.sip.address.SipURI;
import javax.sip.header.Header;
import javax.sip.header.HeaderFactory;
/**
* Implementation of the SipURI interface.
*
*
* @author M. Ranganathan
* @version 1.2 $Revision: 1.22 $ $Date: 2009/11/15 19:50:45 $
*
*
*
*/
public class SipUri extends GenericURI implements javax.sip.address.SipURI , SipURIExt{
private static final long serialVersionUID = 7749781076218987044L;
/** Authority for the uri.
*/
protected Authority authority;
/** uriParms list
*/
protected NameValueList uriParms;
/** qheaders list
*/
protected NameValueList qheaders;
/** telephoneSubscriber field
*/
protected TelephoneNumber telephoneSubscriber;
public SipUri() {
this.scheme = SIP;
this.uriParms = new NameValueList();
this.qheaders = new NameValueList();
this.qheaders.setSeparator("&");
}
/** Constructor given the scheme.
* The scheme must be either Sip or Sips
*/
public void setScheme(String scheme) {
if (scheme.compareToIgnoreCase(SIP) != 0
&& scheme.compareToIgnoreCase(SIPS) != 0)
throw new IllegalArgumentException("bad scheme " + scheme);
this.scheme = scheme.toLowerCase();
}
/** Get the scheme.
*/
public String getScheme() {
return scheme;
}
/**
* clear all URI Parameters.
* @since v1.0
*/
public void clearUriParms() {
uriParms = new NameValueList();
}
/**
*Clear the password from the user part if it exists.
*/
public void clearPassword() {
if (this.authority != null) {
UserInfo userInfo = authority.getUserInfo();
if (userInfo != null)
userInfo.clearPassword();
}
}
/** Get the authority.
*/
public Authority getAuthority() {
return this.authority;
}
/**
* Clear all Qheaders.
*/
public void clearQheaders() {
qheaders = new NameValueList();
}
/**
* Compare two URIs and return true if they are equal.
* @param that the object to compare to.
* @return true if the object is equal to this object.
*
* JvB: Updated to define equality in terms of API methods, according to the rules
* in RFC3261 section 19.1.4
*
* Jean Deruelle: Updated to define equality of API methods, according to the rules
* in RFC3261 section 19.1.4 convert potential ie :
* %HEX HEX encoding parts of the URI before comparing them
* transport param added in comparison
* header equality enforced in comparison
*
*/
@SuppressWarnings("unchecked")
@Override
public boolean equals(Object that) {
// Shortcut for same object
if (that==this) return true;
if (that instanceof SipURI) {
final SipURI a = this;
final SipURI b = (SipURI) that;
// A SIP and SIPS URI are never equivalent
if ( a.isSecure() ^ b.isSecure() ) return false;
// For two URIs to be equal, the user, password, host, and port
// components must match; comparison of userinfo is case-sensitive
if (a.getUser()==null ^ b.getUser()==null) return false;
if (a.getUserPassword()==null ^ b.getUserPassword()==null) return false;
if (a.getUser()!=null && !RFC2396UrlDecoder.decode(a.getUser()).equals(RFC2396UrlDecoder.decode(b.getUser()))) return false;
if (a.getUserPassword()!=null && !RFC2396UrlDecoder.decode(a.getUserPassword()).equals(RFC2396UrlDecoder.decode(b.getUserPassword()))) return false;
if (a.getHost() == null ^ b.getHost() == null) return false;
if (a.getHost() != null && !a.getHost().equalsIgnoreCase(b.getHost())) return false;
if (a.getPort() != b.getPort()) return false;
// URI parameters
for (Iterator i = a.getParameterNames(); i.hasNext();) {
String pname = (String) i.next();
String p1 = a.getParameter(pname);
String p2 = b.getParameter(pname);
// those present in both must match (case-insensitive)
if (p1!=null && p2!=null && !RFC2396UrlDecoder.decode(p1).equalsIgnoreCase(RFC2396UrlDecoder.decode(p2))) return false;
}
// transport, user, ttl or method must match when present in either
if (a.getTransportParam()==null ^ b.getTransportParam()==null) return false;
if (a.getUserParam()==null ^ b.getUserParam()==null) return false;
if (a.getTTLParam()==-1 ^ b.getTTLParam()==-1) return false;
if (a.getMethodParam()==null ^ b.getMethodParam()==null) return false;
if (a.getMAddrParam()==null ^ b.getMAddrParam()==null) return false;
// Headers: must match according to their definition.
if(a.getHeaderNames().hasNext() && !b.getHeaderNames().hasNext()) return false;
if(!a.getHeaderNames().hasNext() && b.getHeaderNames().hasNext()) return false;
if(a.getHeaderNames().hasNext() && b.getHeaderNames().hasNext()) {
HeaderFactory headerFactory = null;
try {
headerFactory = SipFactory.getInstance().createHeaderFactory();
} catch (PeerUnavailableException e) {
Debug.logError("Cannot get the header factory to parse the header of the sip uris to compare", e);
return false;
}
for (Iterator i = a.getHeaderNames(); i.hasNext();) {
String hname = (String) i.next();
String h1 = a.getHeader(hname);
String h2 = b.getHeader(hname);
if(h1 == null && h2 != null) return false;
if(h2 == null && h1 != null) return false;
// The following check should not be needed but we add it for findbugs.
if(h1 == null && h2 == null) continue;
try {
Header header1 = headerFactory.createHeader(hname, RFC2396UrlDecoder.decode(h1));
Header header2 = headerFactory.createHeader(hname, RFC2396UrlDecoder.decode(h2));
// those present in both must match according to the equals method of the corresponding header
if (!header1.equals(header2)) return false;
} catch (ParseException e) {
Debug.logError("Cannot parse one of the header of the sip uris to compare " + a + " " + b, e);
return false;
}
}
}
// Finally, we can conclude that they are indeed equal
return true;
}
return false;
}
/**
* Construct a URL from the parsed structure.
* @return String
*/
public String encode() {
return encode(new StringBuffer()).toString();
}
public StringBuffer encode(StringBuffer buffer) {
buffer.append(scheme).append(COLON);
if (authority != null)
authority.encode(buffer);
if (!uriParms.isEmpty()) {
buffer.append(SEMICOLON);
uriParms.encode(buffer);
}
if (!qheaders.isEmpty()) {
buffer.append(QUESTION);
qheaders.encode(buffer);
}
return buffer;
}
/** Return a string representation.
*
*@return the String representation of this URI.
*
*/
public String toString() {
return this.encode();
}
/**
* getUser@host
* @return user@host portion of the uri (null if none exists).
*
* Peter Musgrave - handle null user
*/
public String getUserAtHost() {
String user = "";
if (authority.getUserInfo() != null)
user = authority.getUserInfo().getUser();
String host = authority.getHost().encode();
StringBuffer s = null;
if (user.equals("")) {
s = new StringBuffer();
} else {
s = new StringBuffer(user).append(AT);
}
return s.append(host).toString();
}
/**
* getUser@host
* @return user@host portion of the uri (null if none exists).
*/
public String getUserAtHostPort() {
String user = "";
if (authority.getUserInfo() != null)
user = authority.getUserInfo().getUser();
String host = authority.getHost().encode();
int port = authority.getPort();
// If port not set assign the default.
StringBuffer s = null;
if (user.equals("")) {
s = new StringBuffer();
} else {
s = new StringBuffer(user).append(AT);
}
if (port != -1) {
return s.append(host).append(COLON).append(port).toString();
} else
return s.append(host).toString();
}
/**
* get the parameter (do a name lookup) and return null if none exists.
* @param parmname Name of the parameter to get.
* @return Parameter of the given name (null if none exists).
*/
public Object getParm(String parmname) {
Object obj = uriParms.getValue(parmname);
return obj;
}
/**
* Get the method parameter.
* @return Method parameter.
*/
public String getMethod() {
return (String) getParm(METHOD);
}
/**
* Accessor for URI parameters
* @return A name-value list containing the parameters.
*/
public NameValueList getParameters() {
return uriParms;
}
/** Remove the URI parameters.
*
*/
public void removeParameters() {
this.uriParms = new NameValueList();
}
/**
* Accessor forSIPObjects
* @return Get the query headers (that appear after the ? in
* the URL)
*/
public NameValueList getQheaders() {
return qheaders;
}
/**
* Get the urse parameter.
* @return User parameter (user= phone or user=ip).
*/
public String getUserType() {
return (String) uriParms.getValue(USER);
}
/**
* Get the password of the user.
* @return User password when it embedded as part of the uri
* ( a very bad idea).
*/
public String getUserPassword() {
if (authority == null)
return null;
return authority.getPassword();
}
/** Set the user password.
*@param password - password to set.
*/
public void setUserPassword(String password) {
if (this.authority == null)
this.authority = new Authority();
authority.setPassword(password);
}
/**
* Returns the stucture corresponding to the telephone number
* provided that the user is a telephone subscriber.
* @return TelephoneNumber part of the url (only makes sense
* when user = phone is specified)
*/
public TelephoneNumber getTelephoneSubscriber() {
if (telephoneSubscriber == null) {
telephoneSubscriber = new TelephoneNumber();
}
return telephoneSubscriber;
}
/**
* Get the host and port of the server.
* @return get the host:port part of the url parsed into a
* structure.
*/
public HostPort getHostPort() {
if (authority == null || authority.getHost() == null )
return null;
else {
return authority.getHostPort();
}
}
/** Get the port from the authority field.
*
*@return the port from the authority field.
*/
public int getPort() {
HostPort hp = this.getHostPort();
if (hp == null)
return -1;
return hp.getPort();
}
/** Get the host protion of the URI.
* @return the host portion of the url.
*/
public String getHost() {
if ( authority == null) return null;
else if (authority.getHost() == null ) return null;
else return authority.getHost().encode();
}
/**
* returns true if the user is a telephone subscriber.
* If the host is an Internet telephony
* gateway, a telephone-subscriber field MAY be used instead
* of a user field. The telephone-subscriber field uses the
* notation of RFC 2806 [19]. Any characters of the un-escaped
* "telephone-subscriber" that are not either in the set
* "unreserved" or "user-unreserved" MUST be escaped. The set
* of characters not reserved in the RFC 2806 description of
* telephone-subscriber contains a number of characters in
* various syntax elements that need to be escaped when used
* in SIP URLs, for example quotation marks (%22), hash (%23),
* colon (%3a), at-sign (%40) and the "unwise" characters,
* i.e., punctuation of %5b and above.
*
* The telephone number is a special case of a user name and
* cannot be distinguished by a BNF. Thus, a URL parameter,
* user, is added to distinguish telephone numbers from user
* names.
*
* The user parameter value "phone" indicates that the user
* part contains a telephone number. Even without this
* parameter, recipients of SIP URLs MAY interpret the pre-@
* part as a telephone number if local restrictions on the
* @return true if the user is a telephone subscriber.
*/
public boolean isUserTelephoneSubscriber() {
String usrtype = (String) uriParms.getValue(USER);
if (usrtype == null)
return false;
return usrtype.equalsIgnoreCase(PHONE);
}
/**
*remove the ttl value from the parameter list if it exists.
*/
public void removeTTL() {
if (uriParms != null)
uriParms.delete(TTL);
}
/**
*Remove the maddr param if it exists.
*/
public void removeMAddr() {
if (uriParms != null)
uriParms.delete(MADDR);
}
/**
*Delete the transport string.
*/
public void removeTransport() {
if (uriParms != null)
uriParms.delete(TRANSPORT);
}
/** Remove a header given its name (provided it exists).
* @param name name of the header to remove.
*/
public void removeHeader(String name) {
if (qheaders != null)
qheaders.delete(name);
}
/** Remove all headers.
*/
public void removeHeaders() {
qheaders = new NameValueList();
}
/**
* Set the user type.
*/
public void removeUserType() {
if (uriParms != null)
uriParms.delete(USER);
}
/**
*remove the port setting.
*/
public void removePort() {
authority.removePort();
}
/**
* remove the Method.
*/
public void removeMethod() {
if (uriParms != null)
uriParms.delete(METHOD);
}
/** Sets the user of SipURI. The identifier of a particular resource at
* the host being addressed. The user and the user password including the
* "at" sign make up the user-info.
*
* @param uname The new String value of the user.
* @throws ParseException which signals that an error has been reached
* unexpectedly while parsing the user value.
*/
public void setUser(String uname) {
if (this.authority == null) {
this.authority = new Authority();
}
this.authority.setUser(uname);
}
/** Remove the user.
*/
public void removeUser() {
this.authority.removeUserInfo();
}
/** Set the default parameters for this URI.
* Do nothing if the parameter is already set to some value.
* Otherwise set it to the given value.
* @param name Name of the parameter to set.
* @param value value of the parameter to set.
*/
public void setDefaultParm(String name, Object value) {
if (uriParms.getValue(name) == null) {
NameValue nv = new NameValue(name, value);
uriParms.set(nv);
}
}
/** Set the authority member
* @param authority Authority to set.
*/
public void setAuthority(Authority authority) {
this.authority = authority;
}
/** Set the host for this URI.
* @param h host to set.
*/
public void setHost(Host h) {
if (this.authority == null)
this.authority = new Authority();
this.authority.setHost(h);
}
/** Set the uriParms member
* @param parms URI parameters to set.
*/
public void setUriParms(NameValueList parms) {
uriParms = parms;
}
/**
* Set a given URI parameter. Note - parameter must be properly
* encoded before the function is called.
* @param name Name of the parameter to set.
* @param value value of the parameter to set.
*/
public void setUriParm(String name, Object value) {
NameValue nv = new NameValue(name, value);
uriParms.set(nv);
}
/** Set the qheaders member
* @param parms query headers to set.
*/
public void setQheaders(NameValueList parms) {
qheaders = parms;
}
/**
* Set the MADDR parameter .
* @param mAddr Host Name to set
*/
public void setMAddr(String mAddr) {
NameValue nameValue = uriParms.getNameValue(MADDR);
Host host = new Host();
host.setAddress(mAddr);
if (nameValue != null)
nameValue.setValueAsObject(host);
else {
nameValue = new NameValue(MADDR, host);
uriParms.set(nameValue);
}
}
/** Sets the value of the user parameter. The user URI parameter exists to
* distinguish telephone numbers from user names that happen to look like
* telephone numbers. This is equivalent to setParameter("user", user).
*
* @param usertype New value String value of the method parameter
*/
public void setUserParam(String usertype) {
uriParms.set(USER, usertype);
}
/**
* Set the Method
* @param method method parameter
*/
public void setMethod(String method) {
uriParms.set(METHOD, method);
}
/**
* Sets ISDN subaddress of SipURL
* @param isdnSubAddress ISDN subaddress
*/
public void setIsdnSubAddress(String isdnSubAddress) {
if (telephoneSubscriber == null)
telephoneSubscriber = new TelephoneNumber();
telephoneSubscriber.setIsdnSubaddress(isdnSubAddress);
}
/**
* Set the telephone subscriber field.
* @param tel Telephone subscriber field to set.
*/
public void setTelephoneSubscriber(TelephoneNumber tel) {
telephoneSubscriber = tel;
}
/** set the port to a given value.
* @param p Port to set.
*/
public void setPort(int p) {
if (authority == null)
authority = new Authority();
authority.setPort(p);
}
/**
* Boolean to check if a parameter of a given name exists.
* @param name Name of the parameter to check on.
* @return a boolean indicating whether the parameter exists.
*/
public boolean hasParameter(String name) {
return uriParms.getValue(name) != null;
}
/**
* Set the query header when provided as a name-value pair.
* @param nameValue qeuery header provided as a name,value pair.
*/
public void setQHeader(NameValue nameValue) {
this.qheaders.set(nameValue);
}
/** Set the parameter as given.
*@param nameValue - parameter to set.
*/
public void setUriParameter(NameValue nameValue) {
this.uriParms.set(nameValue);
}
/** Return true if the transport parameter is defined.
* @return true if transport appears as a parameter and false otherwise.
*/
public boolean hasTransport() {
return hasParameter(TRANSPORT);
}
/**
* Remove a parameter given its name
* @param name -- name of the parameter to remove.
*/
public void removeParameter(String name) {
uriParms.delete(name);
}
/** Set the hostPort field of the imbedded authority field.
*@param hostPort is the hostPort to set.
*/
public void setHostPort(HostPort hostPort) {
if (this.authority == null) {
this.authority = new Authority();
}
authority.setHostPort(hostPort);
}
/** clone this.
*/
public Object clone() {
SipUri retval = (SipUri) super.clone();
if (this.authority != null)
retval.authority = (Authority) this.authority.clone();
if (this.uriParms != null)
retval.uriParms = (NameValueList) this.uriParms.clone();
if (this.qheaders != null)
retval.qheaders = (NameValueList) this.qheaders.clone();
if (this.telephoneSubscriber != null)
retval.telephoneSubscriber = (TelephoneNumber) this.telephoneSubscriber.clone();
return retval;
}
/**
* Returns the value of the named header, or null if it is not set.
* SIP/SIPS URIs may specify headers. As an example, the URI
* sip:joe@jcp.org?priority=urgent has a header "priority" whose
* value is "urgent".
*
* @param name name of header to retrieve
* @return the value of specified header
*/
public String getHeader(String name) {
return this.qheaders.getValue(name) != null
? this.qheaders.getValue(name).toString()
: null;
}
/**
* Returns an Iterator over the names (Strings) of all headers present
* in this SipURI.
*
* @return an Iterator over all the header names
*/
public Iterator getHeaderNames() {
return this.qheaders.getNames();
}
/** Returns the value of the lr
parameter, or null if this
* is not set. This is equivalent to getParameter("lr").
*
* @return the value of the lr
parameter
*/
public String getLrParam() {
boolean haslr = this.hasParameter(LR);
return haslr ? "true" : null;
}
/** Returns the value of the maddr
parameter, or null if this
* is not set. This is equivalent to getParameter("maddr").
*
* @return the value of the maddr
parameter
*/
public String getMAddrParam() {
NameValue maddr = uriParms.getNameValue(MADDR);
if (maddr == null)
return null;
String host = (String) maddr.getValueAsObject();
return host;
}
/**
* Returns the value of the method
parameter, or null if this
* is not set. This is equivalent to getParameter("method").
*
* @return the value of the method
parameter
*/
public String getMethodParam() {
return this.getParameter(METHOD);
}
/**
* Returns the value of the named parameter, or null if it is not set. A
* zero-length String indicates flag parameter.
*
* @param name name of parameter to retrieve
* @return the value of specified parameter
*/
public String getParameter(String name) {
Object val = uriParms.getValue(name);
if (val == null)
return null;
if (val instanceof GenericObject)
return ((GenericObject) val).encode();
else
return val.toString();
}
/**
* Returns an Iterator over the names (Strings) of all parameters present
*
* in this ParametersHeader.
*
*
*
* @return an Iterator over all the parameter names
*
*/
public Iterator getParameterNames() {
return this.uriParms.getNames();
}
/** Returns the value of the "ttl" parameter, or -1 if this is not set.
* This method is equivalent to getParameter("ttl").
*
* @return the value of the ttl
parameter
*/
public int getTTLParam() {
Integer ttl = (Integer) uriParms.getValue("ttl");
if (ttl != null)
return ttl.intValue();
else
return -1;
}
/** Returns the value of the "transport" parameter, or null if this is not
* set. This is equivalent to getParameter("transport").
*
* @return the transport paramter of the SipURI
*/
public String getTransportParam() {
if (uriParms != null) {
return (String) uriParms.getValue(TRANSPORT);
} else
return null;
}
/** Returns the value of the userParam
,
*or null if this is not set.
*
* This is equivalent to getParameter("user").
*
* @return the value of the userParam
of the SipURI
*/
public String getUser() {
return authority.getUser();
}
/** Returns true if this SipURI is secure i.e. if this SipURI represents a
* sips URI. A sip URI returns false.
*
* @return true
if this SipURI represents a sips URI, and
* false
if it represents a sip URI.
*/
public boolean isSecure() {
return this.getScheme().equalsIgnoreCase(SIPS);
}
/** This method determines if this is a URI with a scheme of "sip" or "sips".
*
* @return true if the scheme is "sip" or "sips", false otherwise.
*/
public boolean isSipURI() {
return true;
}
/** Sets the value of the specified header fields to be included in a
* request constructed from the URI. If the header already had a value it
* will be overwritten.
*
* @param name - a String specifying the header name
* @param value - a String specifying the header value
*/
public void setHeader(String name, String value) {
NameValue nv = new NameValue(name, value);
qheaders.set(nv);
}
/**
* Set the host portion of the SipURI
*
* @param host host to set.
*/
public void setHost(String host) throws ParseException {
Host h = new Host(host);
this.setHost(h);
}
/** Sets the value of the lr
parameter of this SipURI. The lr
* parameter, when present, indicates that the element responsible for
* this resource implements the routing mechanisms specified in RFC 3261.
* This parameter will be used in the URIs proxies place in the
* Record-Route header field values, and may appear in the URIs in a
* pre-existing route set.
*/
public void setLrParam() {
this.uriParms.set("lr",null); // JvB: fixed to not add duplicates
}
/**
* Sets the value of the maddr
parameter of this SipURI. The
* maddr parameter indicates the server address to be contacted for this
* user, overriding any address derived from the host field. This is
* equivalent to setParameter("maddr", maddr).
*
* @param maddr New value of the maddr
parameter
*/
public void setMAddrParam(String maddr) throws ParseException {
if (maddr == null)
throw new NullPointerException("bad maddr");
setParameter("maddr", maddr);
}
/** Sets the value of the method
parameter. This specifies
* which SIP method to use in requests directed at this URI. This is
* equivalent to setParameter("method", method).
*
* @param method - new value String value of the method parameter
*/
public void setMethodParam(String method) throws ParseException {
setParameter("method", method);
}
/**
* Sets the value of the specified parameter. If the parameter already had
*
* a value it will be overwritten. A zero-length String indicates flag
*
* parameter.
*
*
*
* @param name - a String specifying the parameter name
*
* @param value - a String specifying the parameter value
*
* @throws ParseException which signals that an error has been reached
*
* unexpectedly while parsing the parameter name or value.
*
*/
public void setParameter(String name, String value) throws ParseException {
if (name.equalsIgnoreCase("ttl")) {
try {
Integer.parseInt(value);
} catch (NumberFormatException ex) {
throw new ParseException("bad parameter " + value, 0);
}
}
uriParms.set(name,value);
}
/** Sets the scheme of this URI to sip or sips depending on whether the
* argument is true or false. The default value is false.
*
* @param secure - the boolean value indicating if the SipURI is secure.
*/
public void setSecure(boolean secure) {
if (secure)
this.scheme = SIPS;
else
this.scheme = SIP;
}
/** Sets the value of the ttl
parameter. The ttl parameter
* specifies the time-to-live value when packets are sent using UDP
* multicast. This is equivalent to setParameter("ttl", ttl).
*
* @param ttl - new value of the ttl
parameter
*/
public void setTTLParam(int ttl) {
if (ttl <= 0)
throw new IllegalArgumentException("Bad ttl value");
if (uriParms != null) {
NameValue nv = new NameValue("ttl", Integer.valueOf(ttl));
uriParms.set(nv);
}
}
/** Sets the value of the "transport" parameter. This parameter specifies
* which transport protocol to use for sending requests and responses to
* this entity. The following values are defined: "udp", "tcp", "sctp",
* "tls", but other values may be used also. This method is equivalent to
* setParameter("transport", transport). Transport parameter constants
* are defined in the {@link javax.sip.ListeningPoint}.
*
* @param transport - new value for the "transport" parameter
* @see javax.sip.ListeningPoint
*/
public void setTransportParam(String transport) throws ParseException {
if (transport == null)
throw new NullPointerException("null arg");
if (transport.compareToIgnoreCase("UDP") == 0
|| transport.compareToIgnoreCase("TLS") == 0
|| transport.compareToIgnoreCase("TCP") == 0
|| transport.compareToIgnoreCase("SCTP") == 0) {
NameValue nv = new NameValue(TRANSPORT, transport.toLowerCase());
uriParms.set(nv);
} else
throw new ParseException("bad transport " + transport, 0);
}
/** Returns the user part of this SipURI, or null if it is not set.
*
* @return the user part of this SipURI
*/
public String getUserParam() {
return getParameter("user");
}
/** Returns whether the the lr
parameter is set. This is
* equivalent to hasParameter("lr"). This interface has no getLrParam as
* RFC3261 does not specify any values for the "lr" paramater.
*
* @return true if the "lr" parameter is set, false otherwise.
*/
public boolean hasLrParam() {
return uriParms.getNameValue("lr") != null;
}
/**
* Returns whether the gr
parameter is set.
*
* Not part on the interface since gruu is not part of the base RFC3261.
*/
public boolean hasGrParam() {
return uriParms.getNameValue(GRUU) != null;
}
/**
* Sets the gr
parameter.
*
* Not part on the interface since gruu is not part of the base RFC3261.
*/
public void setGrParam(String value) {
this.uriParms.set(GRUU, value); // JvB: fixed to not add duplicates
}
/**
* Sets the gr
parameter.
*
* Not part on the interface since gruu is not part of the base RFC3261.
*/
public String getGrParam() {
return (String) this.uriParms.getValue(GRUU); // JvB: fixed to not add duplicates
}
/**
*remove the +sip-instance value from the parameter list if it exists.
*/
}
java/gov/nist/javax/sip/address/TelURLImpl.java 0100644 0000000 0000000 00000014775 13513104763 020444 0 ustar 00 0000000 0000000 /*
* Conditions Of Use
*
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), an agency of the Federal Government.
* Pursuant to title 15 Untied States Code Section 105, works of NIST
* employees are not subject to copyright protection in the United States
* and are considered to be in the public domain. As a result, a formal
* license is not needed to use the software.
*
* This software is provided by NIST as a service and is expressly
* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY. NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement
*
* .
*
*/
package gov.nist.javax.sip.address;
import gov.nist.core.NameValueList;
import java.text.ParseException;
import java.util.Iterator;
/**
* Implementation of the TelURL interface.
*
* @version 1.2 $Revision: 1.10 $ $Date: 2009/11/15 19:50:45 $
*
* @author M. Ranganathan
*
*/
public class TelURLImpl
extends GenericURI
implements javax.sip.address.TelURL {
private static final long serialVersionUID = 5873527320305915954L;
protected TelephoneNumber telephoneNumber;
/** Creates a new instance of TelURLImpl */
public TelURLImpl() {
this.scheme = "tel";
}
/** Set the telephone number.
*@param telephoneNumber -- telephone number to set.
*/
public void setTelephoneNumber(TelephoneNumber telephoneNumber) {
this.telephoneNumber = telephoneNumber;
}
/** Returns the value of the isdnSubAddress
parameter, or null
* if it is not set.
*
* @return the value of the isdnSubAddress
parameter
*/
public String getIsdnSubAddress() {
return telephoneNumber.getIsdnSubaddress();
}
/** Returns the value of the postDial
parameter, or null if it
* is not set.
*
* @return the value of the postDial
parameter
*/
public String getPostDial() {
return telephoneNumber.getPostDial();
}
/** Returns the value of the "scheme" of this URI, for example "sip", "sips"
* or "tel".
*
* @return the scheme paramter of the URI
*/
public String getScheme() {
return this.scheme;
}
/** Returns true
if this TelURL is global i.e. if the TelURI
* has a global phone user.
*
* @return true
if this TelURL represents a global phone user,
* and false
otherwise.
*/
public boolean isGlobal() {
return telephoneNumber.isGlobal();
}
/** This method determines if this is a URI with a scheme of "sip" or "sips".
*
* @return true if the scheme is "sip" or "sips", false otherwise.
*/
public boolean isSipURI() {
return false;
}
/** Sets phone user of this TelURL to be either global or local. The default
* value is false, hence the TelURL is defaulted to local.
*
* @param global - the boolean value indicating if the TelURL has a global
* phone user.
*/
public void setGlobal(boolean global) {
this.telephoneNumber.setGlobal(global);
}
/** Sets ISDN subaddress of this TelURL. If a subaddress is present, it is
* appended to the phone number after ";isub=".
*
* @param isdnSubAddress - new value of the isdnSubAddress
* parameter
*/
public void setIsdnSubAddress(String isdnSubAddress) {
this.telephoneNumber.setIsdnSubaddress(isdnSubAddress);
}
/** Sets post dial of this TelURL. The post-dial sequence describes what and
* when the local entity should send to the phone line.
*
* @param postDial - new value of the postDial
parameter
*/
public void setPostDial(String postDial) {
this.telephoneNumber.setPostDial(postDial);
}
/**
* Set the telephone number.
* @param telephoneNumber long phone number to set.
*/
public void setPhoneNumber(String telephoneNumber) {
this.telephoneNumber.setPhoneNumber(telephoneNumber);
}
/** Get the telephone number.
*
*@return -- the telephone number.
*/
public String getPhoneNumber() {
return this.telephoneNumber.getPhoneNumber();
}
/** Return the string encoding.
*
*@return -- the string encoding.
*/
public String toString() {
return this.scheme + ":" + telephoneNumber.encode();
}
public String encode() {
return encode(new StringBuffer()).toString();
}
public StringBuffer encode(StringBuffer buffer) {
buffer.append(this.scheme).append(':');
telephoneNumber.encode(buffer);
return buffer;
}
/** Deep copy clone operation.
*
*@return -- a cloned version of this telephone number.
*/
public Object clone() {
TelURLImpl retval = (TelURLImpl) super.clone();
if (this.telephoneNumber != null)
retval.telephoneNumber = (TelephoneNumber) this.telephoneNumber.clone();
return retval;
}
public String getParameter(String parameterName) {
return telephoneNumber.getParameter(parameterName);
}
public void setParameter(String name, String value) {
telephoneNumber.setParameter(name, value);
}
public Iterator getParameterNames() {
return telephoneNumber.getParameterNames();
}
public NameValueList getParameters() {
return telephoneNumber.getParameters();
}
public void removeParameter(String name) {
telephoneNumber.removeParameter(name);
}
/* (non-Javadoc)
* @see javax.sip.address.TelURL#setPhoneContext(java.lang.String)
*/
public void setPhoneContext(String phoneContext) throws ParseException {
// JvB: set (null) should be interpreted as 'remove'
if (phoneContext==null) {
this.removeParameter("phone-context");
} else {
this.setParameter("phone-context",phoneContext);
}
}
/* (non-Javadoc)
* @see javax.sip.address.TelURL#getPhoneContext()
*/
public String getPhoneContext() {
return this.getParameter("phone-context");
}
}
java/gov/nist/javax/sip/address/TelephoneNumber.java 0100644 0000000 0000000 00000014430 13513104763 021573 0 ustar 00 0000000 0000000 /*
* Conditions Of Use
*
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), an agency of the Federal Government.
* Pursuant to title 15 Untied States Code Section 105, works of NIST
* employees are not subject to copyright protection in the United States
* and are considered to be in the public domain. As a result, a formal
* license is not needed to use the software.
*
* This software is provided by NIST as a service and is expressly
* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY. NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement
*
* .
*
*/
package gov.nist.javax.sip.address;
import gov.nist.core.*;
import java.util.Iterator;
/**
* Telephone number class.
* @version 1.2
* @version 1.2 $Revision: 1.10 $ $Date: 2009/07/17 18:57:23 $
*
* @author M. Ranganathan
*
*/
public class TelephoneNumber extends NetObject {
public static final String POSTDIAL = ParameterNames.POSTDIAL;
public static final String PHONE_CONTEXT_TAG =
ParameterNames.PHONE_CONTEXT_TAG;
public static final String ISUB = ParameterNames.ISUB;
public static final String PROVIDER_TAG = ParameterNames.PROVIDER_TAG;
/** isglobal field
*/
protected boolean isglobal;
/** phoneNumber field
*/
protected String phoneNumber;
/** parmeters list
*/
protected NameValueList parameters;
/** Creates new TelephoneNumber */
public TelephoneNumber() {
parameters = new NameValueList();
}
/** delete the specified parameter.
* @param name String to set
*/
public void deleteParm(String name) {
parameters.delete(name);
}
/** get the PhoneNumber field
* @return String
*/
public String getPhoneNumber() {
return phoneNumber;
}
/** get the PostDial field
* @return String
*/
public String getPostDial() {
return (String) parameters.getValue(POSTDIAL);
}
/**
* Get the isdn subaddress for this number.
* @return String
*/
public String getIsdnSubaddress() {
return (String) parameters.getValue(ISUB);
}
/** returns true if th PostDial field exists
* @return boolean
*/
public boolean hasPostDial() {
return parameters.getValue(POSTDIAL) != null;
}
/** return true if this header has parameters.
* @param pname String to set
* @return boolean
*/
public boolean hasParm(String pname) {
return parameters.hasNameValue(pname);
}
/**
* return true if the isdn subaddress exists.
* @return boolean
*/
public boolean hasIsdnSubaddress() {
return hasParm(ISUB);
}
/**
* is a global telephone number.
* @return boolean
*/
public boolean isGlobal() {
return isglobal;
}
/** remove the PostDial field
*/
public void removePostDial() {
parameters.delete(POSTDIAL);
}
/**
* Remove the isdn subaddress (if it exists).
*/
public void removeIsdnSubaddress() {
deleteParm(ISUB);
}
/**
* Set the list of parameters.
* @param p NameValueList to set
*/
public void setParameters(NameValueList p) {
parameters = p;
}
/** set the Global field
* @param g boolean to set
*/
public void setGlobal(boolean g) {
isglobal = g;
}
/** set the PostDial field
* @param p String to set
*/
public void setPostDial(String p) {
NameValue nv = new NameValue(POSTDIAL, p);
parameters.set(nv);
}
/** set the specified parameter
* @param name String to set
* @param value Object to set
*/
public void setParm(String name, Object value) {
NameValue nv = new NameValue(name, value);
parameters.set(nv);
}
/**
* set the isdn subaddress for this structure.
* @param isub String to set
*/
public void setIsdnSubaddress(String isub) {
setParm(ISUB, isub);
}
/** set the PhoneNumber field
* @param num String to set
*/
public void setPhoneNumber(String num) {
phoneNumber = num;
}
public String encode() {
return encode(new StringBuffer()).toString();
}
public StringBuffer encode(StringBuffer buffer) {
if (isglobal)
buffer.append('+');
buffer.append(phoneNumber);
if (!parameters.isEmpty()) {
buffer.append(SEMICOLON);
parameters.encode(buffer);
}
return buffer;
}
/**
* Returns the value of the named parameter, or null if it is not set. A
* zero-length String indicates flag parameter.
*
* @param name name of parameter to retrieve
*
* @return the value of specified parameter
*
*/
public String getParameter(String name) {
Object val = parameters.getValue(name);
if (val == null)
return null;
if (val instanceof GenericObject)
return ((GenericObject) val).encode();
else
return val.toString();
}
/**
*
* Returns an Iterator over the names (Strings) of all parameters.
*
* @return an Iterator over all the parameter names
*
*/
public Iterator getParameterNames() {
return this.parameters.getNames();
}
public void removeParameter(String parameter) {
this.parameters.delete(parameter);
}
public void setParameter(String name, String value) {
NameValue nv = new NameValue(name, value);
this.parameters.set(nv);
}
public Object clone() {
TelephoneNumber retval = (TelephoneNumber) super.clone();
if (this.parameters != null)
retval.parameters = (NameValueList) this.parameters.clone();
return retval;
}
public NameValueList getParameters() {
return this.parameters;
}
}
java/gov/nist/javax/sip/address/UserInfo.java 0100644 0000000 0000000 00000011625 13513104763 020234 0 ustar 00 0000000 0000000 /*
* Conditions Of Use
*
* This software was developed by employees of the National Institute of
* Standards and Technology (NIST), an agency of the Federal Government.
* Pursuant to title 15 Untied States Code Section 105, works of NIST
* employees are not subject to copyright protection in the United States
* and are considered to be in the public domain. As a result, a formal
* license is not needed to use the software.
*
* This software is provided by NIST as a service and is expressly
* provided "AS IS." NIST MAKES NO WARRANTY OF ANY KIND, EXPRESS, IMPLIED
* OR STATUTORY, INCLUDING, WITHOUT LIMITATION, THE IMPLIED WARRANTY OF
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE, NON-INFRINGEMENT
* AND DATA ACCURACY. NIST does not warrant or make any representations
* regarding the use of the software or the results thereof, including but
* not limited to the correctness, accuracy, reliability or usefulness of
* the software.
*
* Permission to use this software is contingent upon your acceptance
* of the terms of this agreement
*
* .
*
*/
/*
* Acknowledgement -- Lamine Brahimi
* Submitted a bug fix for a this class.
*/
/*******************************************************************************
* Product of NIST/ITL Advanced Networking Technologies Division (ANTD). *
*******************************************************************************/
package gov.nist.javax.sip.address;
/**
* User information part of a URL.
*
* @version 1.2 $Revision: 1.8 $ $Date: 2009/07/17 18:57:23 $
* @author M. Ranganathan
*
*/
public final class UserInfo extends NetObject {
private static final long serialVersionUID = 7268593273924256144L;
/** user field
*/
protected String user;
/** password field
*/
protected String password;
/** userType field
*/
protected int userType;
/** Constant field
*/
public final static int TELEPHONE_SUBSCRIBER = 1;
/** constant field
*/
public final static int USER = 2;
/** Default constructor
*/
public UserInfo() {
super();
}
/**
* Compare for equality.
* @param obj Object to set
* @return true if the two headers are equals, false otherwise.
*/
public boolean equals(Object obj) {
if (getClass() != obj.getClass()) {
return false;
}
UserInfo other = (UserInfo) obj;
if (this.userType != other.userType) {
return false;
}
if (!this.user.equalsIgnoreCase(other.user)) {
return false;
}
if (this.password != null && other.password == null)
return false;
if (other.password != null && this.password == null)
return false;
if (this.password == other.password)
return true;
return (this.password.equals(other.password));
}
/**
* Encode the user information as a string.
* @return String
*/
public String encode() {
return encode(new StringBuffer()).toString();
}
public StringBuffer encode(StringBuffer buffer) {
if (password != null)
buffer.append(user).append(COLON).append(password);
else
buffer.append(user);
return buffer;
}
/** Clear the password field.
*/
public void clearPassword() {
this.password = null;
}
/**
* Gets the user type (which can be set to TELEPHONE_SUBSCRIBER or USER)
* @return the type of user.
*/
public int getUserType() {
return userType;
}
/** get the user field.
* @return String
*/
public String getUser() {
return user;
}
/** get the password field.
* @return String
*/
public String getPassword() {
return password;
}
/**
* Set the user member
* @param user String to set
*/
public void setUser(String user) {
this.user = user;
// BUG Fix submitted by Lamine Brahimi
// add this (taken form sip_messageParser)
// otherwise comparison of two SipUrl will fail because this
// parameter is not set (whereas it is set in sip_messageParser).
if (user != null
&& (user.indexOf(POUND) >= 0 || user.indexOf(SEMICOLON) >= 0)) {
setUserType(TELEPHONE_SUBSCRIBER);
} else {
setUserType(USER);
}
}
/**
* Set the password member
* @param p String to set
*/
public void setPassword(String p) {
password = p;
}
/**
* Set the user type (to TELEPHONE_SUBSCRIBER or USER).
* @param type int to set
* @throws IllegalArgumentException if type is not in range.
*/
public void setUserType(int type) throws IllegalArgumentException {
if (type != TELEPHONE_SUBSCRIBER && type != USER) {
throw new IllegalArgumentException("Parameter not in range");
}
userType = type;
}
}
java/gov/nist/javax/sip/address/package.html 0100644 0000000 0000000 00000000113 13513104763 020106 0 ustar 00 0000000 0000000
Implementation of the address package of the JAIN SIP API.
java/gov/nist/javax/sip/clientauthutils/ 0040755 0000000 0000000 00000000000 13513104763 017431 5 ustar 00 0000000 0000000 java/gov/nist/javax/sip/clientauthutils/AccountManager.java 0100644 0000000 0000000 00000001250 13513104763 023156 0 ustar 00 0000000 0000000 package gov.nist.javax.sip.clientauthutils;
import javax.sip.ClientTransaction;
public interface AccountManager {
/**
* Returns the user credentials for a given SIP Domain.
* You can implement any desired method (such as popping up a dialog for example )
* to retrieve the credentials.
*
* @param challengedTransaction - the transaction that is being challenged.
* @param realm - the realm that is being challenged for which a credential should be
* returned.
* @return -- the user credentials associated with the domain.
*/
UserCredentials getCredentials(ClientTransaction challengedTransaction, String realm);
}
java/gov/nist/javax/sip/clientauthutils/AuthenticationHelper.java 0100644 0000000 0000000 00000005306 13513104763 024414 0 ustar 00 0000000 0000000 package gov.nist.javax.sip.clientauthutils;
import java.text.ParseException;
import java.util.Collection;
import javax.sip.ClientTransaction;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import javax.sip.SipProvider;
import javax.sip.header.AuthorizationHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
/**
* A helper interface that provides useful functionality for clients that need to authenticate
* with servers.
*
* @author Emil Ivov
* @author Jeroen van Bemmel
* @author M. Ranganathan
*
* @since 2.0
*
*
*/
public interface AuthenticationHelper {
/**
* Uses securityAuthority to determinie a set of valid user credentials for
* the specified Response (Challenge) and appends it to the challenged
* request so that it could be retransmitted.
*
*
*
* @param challenge
* the 401/407 challenge response
* @param challengedTransaction
* the transaction established by the challenged request
* @param transactionCreator
* the JAIN SipProvider that we should use to create the new
* transaction.
* @param cacheTime The amount of time (seconds ) for which the authentication helper
* will keep a reference to the generated credentials in a cache.
* If you specify -1, then the authentication credentials are cached
* until you remove them from the cache. If you choose this option, make sure
* you remove the cached headers or you will have a memory leak.
*
* @return a transaction containing a re-originated request with the
* necessary authorization header.
* @throws SipException
* if we get an exception white creating the new transaction
* @throws NullPointerException
* if an argument or a header is null.
*/
public abstract ClientTransaction handleChallenge(Response challenge,
ClientTransaction challengedTransaction,
SipProvider transactionCreator, int cacheTime ) throws SipException,
NullPointerException;
/**
* Attach authentication headers to the given request. This looks up
* the credential cache and picks up any stored authentication headers
* for the given call ID and attaches it to the request.
* @param request - the request for which we attach the authentication headers.
*/
public abstract void setAuthenticationHeaders(Request request) ;
/**
* Remove cached entry.
*
* @param callId -- the call Id for which we want to remove the cached headers.
*
*/
public abstract void removeCachedAuthenticationHeaders(String callId);
}
java/gov/nist/javax/sip/clientauthutils/AuthenticationHelperImpl.java 0100644 0000000 0000000 00000045325 13513104763 025243 0 ustar 00 0000000 0000000 package gov.nist.javax.sip.clientauthutils;
/*
*
* This code has been contributed with permission from:
*
* SIP Communicator, the OpenSource Java VoIP and Instant Messaging client but has been significantly changed.
* It is donated to the JAIN-SIP project as it is common code that many sip clients
* need to perform class and others will consitute a set of utility functions
* that will implement common operations that ease the life of the developer.
*
* Acknowledgements:
* ----------------
*
* Fredrik Wickstrom reported that dialog cseq counters are not incremented
* when resending requests. He later uncovered additional problems and
* proposed a way to fix them (his proposition was taken into account).
*/
import gov.nist.javax.sip.SipStackImpl;
import gov.nist.javax.sip.address.SipUri;
import gov.nist.javax.sip.message.SIPRequest;
import gov.nist.javax.sip.stack.SIPClientTransaction;
import gov.nist.javax.sip.stack.SIPTransactionStack;
import java.text.ParseException;
import java.util.Collection;
import java.util.Iterator;
import java.util.ListIterator;
import java.util.Timer;
import javax.sip.ClientTransaction;
import javax.sip.DialogState;
import javax.sip.InvalidArgumentException;
import javax.sip.SipException;
import javax.sip.SipProvider;
import javax.sip.address.Hop;
import javax.sip.address.SipURI;
import javax.sip.address.URI;
import javax.sip.header.AuthorizationHeader;
import javax.sip.header.CSeqHeader;
import javax.sip.header.Header;
import javax.sip.header.HeaderFactory;
import javax.sip.header.ProxyAuthenticateHeader;
import javax.sip.header.ProxyAuthorizationHeader;
import javax.sip.header.ViaHeader;
import javax.sip.header.WWWAuthenticateHeader;
import javax.sip.message.Request;
import javax.sip.message.Response;
/**
* The class handles authentication challenges, caches user credentials and takes care (through
* the SecurityAuthority interface) about retrieving passwords.
*
*
* @author Emil Ivov
* @author Jeroen van Bemmel
* @author M. Ranganathan
*
* @since 2.0
*/
public class AuthenticationHelperImpl implements AuthenticationHelper {
/**
* Credentials cached so far.
*/
private CredentialsCache cachedCredentials;
/**
* The account manager for the system. Stores user credentials.
*/
private Object accountManager = null;
/*
* Header factory for this security manager.
*/
private HeaderFactory headerFactory;
private SipStackImpl sipStack;
Timer timer;
/**
* Default constructor for the security manager. There is one Account manager. There is one
* SipSecurity manager for every user name,
*
* @param sipStack -- our stack.
* @param accountManager -- an implementation of the AccountManager interface.
* @param headerFactory -- header factory.
*/
public AuthenticationHelperImpl(SipStackImpl sipStack, AccountManager accountManager,
HeaderFactory headerFactory) {
this.accountManager = accountManager;
this.headerFactory = headerFactory;
this.sipStack = sipStack;
this.cachedCredentials = new CredentialsCache(((SIPTransactionStack) sipStack).getTimer());
}
/**
* Default constructor for the security manager. There is one Account manager. There is one
* SipSecurity manager for every user name,
*
* @param sipStack -- our stack.
* @param accountManager -- an implementation of the AccountManager interface.
* @param headerFactory -- header factory.
*/
public AuthenticationHelperImpl(SipStackImpl sipStack, SecureAccountManager accountManager,
HeaderFactory headerFactory) {
this.accountManager = accountManager;
this.headerFactory = headerFactory;
this.sipStack = sipStack;
this.cachedCredentials = new CredentialsCache(((SIPTransactionStack) sipStack).getTimer());
}
/*
* (non-Javadoc)
*
* @see gov.nist.javax.sip.clientauthutils.AuthenticationHelper#handleChallenge(javax.sip.message.Response,
* javax.sip.ClientTransaction, javax.sip.SipProvider)
*/
public ClientTransaction handleChallenge(Response challenge,
ClientTransaction challengedTransaction, SipProvider transactionCreator, int cacheTime)
throws SipException, NullPointerException {
try {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug("handleChallenge: " + challenge);
}
SIPRequest challengedRequest = ((SIPRequest) challengedTransaction.getRequest());
Request reoriginatedRequest = null;
/*
* If the challenged request is part of a Dialog and the
* Dialog is confirmed the re-originated request should be
* generated as an in-Dialog request.
*/
if ( challengedRequest.getToTag() != null ||
challengedTransaction.getDialog() == null ||
challengedTransaction.getDialog().getState() != DialogState.CONFIRMED) {
reoriginatedRequest = (Request) challengedRequest.clone();
} else {
/*
* Re-originate the request by consulting the dialog. In particular
* the route set could change between the original request and the
* in-dialog challenge.
*/
reoriginatedRequest =
challengedTransaction.getDialog().createRequest(challengedRequest.getMethod());
Iterator headerNames = challengedRequest.getHeaderNames();
while (headerNames.hasNext()) {
String headerName = headerNames.next();
if ( reoriginatedRequest.getHeader(headerName) != null) {
ListIterator iterator = reoriginatedRequest.getHeaders(headerName);
while (iterator.hasNext()) {
reoriginatedRequest.addHeader(iterator.next());
}
}
}
}
// remove the branch id so that we could use the request in a new
// transaction
removeBranchID(reoriginatedRequest);
if (challenge == null || reoriginatedRequest == null) {
throw new NullPointerException("A null argument was passed to handle challenge.");
}
ListIterator authHeaders = null;
if (challenge.getStatusCode() == Response.UNAUTHORIZED) {
authHeaders = challenge.getHeaders(WWWAuthenticateHeader.NAME);
} else if (challenge.getStatusCode() == Response.PROXY_AUTHENTICATION_REQUIRED) {
authHeaders = challenge.getHeaders(ProxyAuthenticateHeader.NAME);
} else {
throw new IllegalArgumentException("Unexpected status code ");
}
if (authHeaders == null) {
throw new IllegalArgumentException(
"Could not find WWWAuthenticate or ProxyAuthenticate headers");
}
// Remove all authorization headers from the request (we'll re-add them
// from cache)
reoriginatedRequest.removeHeader(AuthorizationHeader.NAME);
reoriginatedRequest.removeHeader(ProxyAuthorizationHeader.NAME);
// rfc 3261 says that the cseq header should be augmented for the new
// request. do it here so that the new dialog (created together with
// the new client transaction) takes it into account.
// Bug report - Fredrik Wickstrom
CSeqHeader cSeq = (CSeqHeader) reoriginatedRequest.getHeader((CSeqHeader.NAME));
try {
cSeq.setSeqNumber(cSeq.getSeqNumber() + 1l);
} catch (InvalidArgumentException ex) {
throw new SipException("Invalid CSeq -- could not increment : "
+ cSeq.getSeqNumber());
}
/* Resolve this to the next hop based on the previous lookup. If we are not using
* lose routing (RFC2543) then just attach hop as a maddr param.
*/
if ( challengedRequest.getRouteHeaders() == null ) {
Hop hop = ((SIPClientTransaction) challengedTransaction).getNextHop();
SipURI sipUri = (SipURI) reoriginatedRequest.getRequestURI();
// BEGIN android-added
if ( !hop.getHost().equalsIgnoreCase(sipUri.getHost())
&& !hop.equals(sipStack.getRouter(challengedRequest).getOutboundProxy()) )
// END android-added
sipUri.setMAddrParam(hop.getHost());
if ( hop.getPort() != -1 ) sipUri.setPort(hop.getPort());
}
ClientTransaction retryTran = transactionCreator
.getNewClientTransaction(reoriginatedRequest);
WWWAuthenticateHeader authHeader = null;
SipURI requestUri = (SipURI) challengedTransaction.getRequest().getRequestURI();
while (authHeaders.hasNext()) {
authHeader = (WWWAuthenticateHeader) authHeaders.next();
String realm = authHeader.getRealm();
AuthorizationHeader authorization = null;
String sipDomain;
if ( this.accountManager instanceof SecureAccountManager ) {
UserCredentialHash credHash =
((SecureAccountManager)this.accountManager).getCredentialHash(challengedTransaction,realm);
URI uri = reoriginatedRequest.getRequestURI();
sipDomain = credHash.getSipDomain();
authorization = this.getAuthorization(reoriginatedRequest
.getMethod(), uri.toString(),
(reoriginatedRequest.getContent() == null) ? "" : new String(
reoriginatedRequest.getRawContent()), authHeader, credHash);
} else {
UserCredentials userCreds = ((AccountManager) this.accountManager).getCredentials(challengedTransaction, realm);
sipDomain = userCreds.getSipDomain();
if (userCreds == null)
throw new SipException(
"Cannot find user creds for the given user name and realm");
// we haven't yet authenticated this realm since we were
// started.
authorization = this.getAuthorization(reoriginatedRequest
.getMethod(), reoriginatedRequest.getRequestURI().toString(),
(reoriginatedRequest.getContent() == null) ? "" : new String(
reoriginatedRequest.getRawContent()), authHeader, userCreds);
}
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logDebug(
"Created authorization header: " + authorization.toString());
if (cacheTime != 0)
cachedCredentials.cacheAuthorizationHeader(sipDomain,
authorization, cacheTime);
reoriginatedRequest.addHeader(authorization);
}
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logDebug(
"Returning authorization transaction." + retryTran);
}
return retryTran;
} catch (SipException ex) {
throw ex;
} catch (Exception ex) {
sipStack.getStackLogger().logError("Unexpected exception ", ex);
throw new SipException("Unexpected exception ", ex);
}
}
/**
* Generates an authorisation header in response to wwwAuthHeader.
*
* @param method method of the request being authenticated
* @param uri digest-uri
* @param requestBody the body of the request.
* @param authHeader the challenge that we should respond to
* @param userCredentials username and pass
*
* @return an authorisation header in response to authHeader.
*
* @throws OperationFailedException if auth header was malformated.
*/
private AuthorizationHeader getAuthorization(String method, String uri, String requestBody,
WWWAuthenticateHeader authHeader, UserCredentials userCredentials) {
String response = null;
// JvB: authHeader.getQop() is a quoted _list_ of qop values
// (e.g. "auth,auth-int") Client is supposed to pick one
String qopList = authHeader.getQop();
String qop = (qopList != null) ? "auth" : null;
String nc_value = "00000001";
String cnonce = "xyz";
response = MessageDigestAlgorithm.calculateResponse(authHeader.getAlgorithm(),
userCredentials.getUserName(), authHeader.getRealm(), userCredentials
.getPassword(), authHeader.getNonce(), nc_value, // JvB added
cnonce, // JvB added
method, uri, requestBody, qop,sipStack.getStackLogger());// jvb changed
AuthorizationHeader authorization = null;
try {
if (authHeader instanceof ProxyAuthenticateHeader) {
authorization = headerFactory.createProxyAuthorizationHeader(authHeader
.getScheme());
} else {
authorization = headerFactory.createAuthorizationHeader(authHeader.getScheme());
}
authorization.setUsername(userCredentials.getUserName());
authorization.setRealm(authHeader.getRealm());
authorization.setNonce(authHeader.getNonce());
authorization.setParameter("uri", uri);
authorization.setResponse(response);
if (authHeader.getAlgorithm() != null) {
authorization.setAlgorithm(authHeader.getAlgorithm());
}
if (authHeader.getOpaque() != null) {
authorization.setOpaque(authHeader.getOpaque());
}
// jvb added
if (qop != null) {
authorization.setQop(qop);
authorization.setCNonce(cnonce);
authorization.setNonceCount(Integer.parseInt(nc_value));
}
authorization.setResponse(response);
} catch (ParseException ex) {
throw new RuntimeException("Failed to create an authorization header!");
}
return authorization;
}
/**
* Generates an authorisation header in response to wwwAuthHeader.
*
* @param method method of the request being authenticated
* @param uri digest-uri
* @param requestBody the body of the request.
* @param authHeader the challenge that we should respond to
* @param userCredentials username and pass
*
* @return an authorisation header in response to authHeader.
*
* @throws OperationFailedException if auth header was malformated.
*/
private AuthorizationHeader getAuthorization(String method, String uri, String requestBody,
WWWAuthenticateHeader authHeader, UserCredentialHash userCredentials) {
String response = null;
// JvB: authHeader.getQop() is a quoted _list_ of qop values
// (e.g. "auth,auth-int") Client is supposed to pick one
String qopList = authHeader.getQop();
String qop = (qopList != null) ? "auth" : null;
String nc_value = "00000001";
String cnonce = "xyz";
response = MessageDigestAlgorithm.calculateResponse(authHeader.getAlgorithm(),
userCredentials.getHashUserDomainPassword(), authHeader.getNonce(), nc_value, // JvB added
cnonce, // JvB added
method, uri, requestBody, qop,sipStack.getStackLogger());// jvb changed
AuthorizationHeader authorization = null;
try {
if (authHeader instanceof ProxyAuthenticateHeader) {
authorization = headerFactory.createProxyAuthorizationHeader(authHeader
.getScheme());
} else {
authorization = headerFactory.createAuthorizationHeader(authHeader.getScheme());
}
authorization.setUsername(userCredentials.getUserName());
authorization.setRealm(authHeader.getRealm());
authorization.setNonce(authHeader.getNonce());
authorization.setParameter("uri", uri);
authorization.setResponse(response);
if (authHeader.getAlgorithm() != null) {
authorization.setAlgorithm(authHeader.getAlgorithm());
}
if (authHeader.getOpaque() != null) {
authorization.setOpaque(authHeader.getOpaque());
}
// jvb added
if (qop != null) {
authorization.setQop(qop);
authorization.setCNonce(cnonce);
authorization.setNonceCount(Integer.parseInt(nc_value));
}
authorization.setResponse(response);
} catch (ParseException ex) {
throw new RuntimeException("Failed to create an authorization header!");
}
return authorization;
}
/**
* Removes all via headers from request and replaces them with a new one, equal to
* the one that was top most.
*
* @param request the Request whose branchID we'd like to remove.
*
*/
private void removeBranchID(Request request) {
ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
viaHeader.removeParameter("branch");
}
/*
* (non-Javadoc)
*
* @see gov.nist.javax.sip.clientauthutils.AuthenticationHelper#attachAuthenticationHeaders(javax.sip.message.Request)
*/
public void setAuthenticationHeaders(Request request) {
SIPRequest sipRequest = (SIPRequest) request;
String callId = sipRequest.getCallId().getCallId();
request.removeHeader(AuthorizationHeader.NAME);
Collection authHeaders = this.cachedCredentials
.getCachedAuthorizationHeaders(callId);
if (authHeaders == null) {
if (sipStack.isLoggingEnabled())
sipStack.getStackLogger().logDebug(
"Could not find authentication headers for " + callId);
return;
}
for (AuthorizationHeader authHeader : authHeaders) {
request.addHeader(authHeader);
}
}
/*
* (non-Javadoc)
*
* @see gov.nist.javax.sip.clientauthutils.AuthenticationHelper#removeCachedAuthenticationHeaders(java.lang.String)
*/
public void removeCachedAuthenticationHeaders(String callId) {
if (callId == null)
throw new NullPointerException("Null callId argument ");
this.cachedCredentials.removeAuthenticationHeader(callId);
}
}
java/gov/nist/javax/sip/clientauthutils/CredentialsCache.java 0100644 0000000 0000000 00000007110 13513104763 023451 0 ustar 00 0000000 0000000 package gov.nist.javax.sip.clientauthutils;
import java.util.*;
import java.util.concurrent.ConcurrentHashMap;
import javax.sip.*;
import javax.sip.header.*;
import javax.sip.address.*;
import javax.sip.message.*;
/**
* A cache of authorization headers to be used for subsequent processing when we
* set up calls. We cache credentials on a per proxy domain per user basis.
*
*/
class CredentialsCache {
/**
* The key for this map is the proxy domain name. A given proxy authorizes a
* user for a number of domains. The Hashtable value of the mapping is a
* mapping of user names to AuthorizationHeader list for that proxy domain.
*/
private ConcurrentHashMap> authorizationHeaders =
new ConcurrentHashMap>();
private Timer timer;
class TimeoutTask extends TimerTask {
String callId;
String userName;
public TimeoutTask(String userName, String proxyDomain) {
this.callId = proxyDomain;
this.userName = userName;
}
@Override
public void run() {
authorizationHeaders.remove(callId);
}
}
CredentialsCache (Timer timer) {
this.timer = timer;
}
/**
* Cache the bindings of proxyDomain and authorization header.
*
* @param callid
* the id of the call that the authorization header
* belongs to.
* @param authorization
* the authorization header that we'd like to cache.
*/
void cacheAuthorizationHeader(String callId,
AuthorizationHeader authorization, int cacheTime) {
String user = authorization.getUsername();
if ( callId == null) throw new NullPointerException("Call ID is null!");
if ( authorization == null) throw new NullPointerException("Null authorization domain");
List authHeaders = authorizationHeaders.get(callId);
if (authHeaders == null) {
authHeaders = new LinkedList();
authorizationHeaders.put(callId, authHeaders);
} else {
String realm = authorization.getRealm();
for (ListIterator li = authHeaders.listIterator(); li.hasNext();) {
AuthorizationHeader authHeader = (AuthorizationHeader) li.next();
if ( realm.equals(authHeader.getRealm()) ) {
li.remove();
}
}
}
authHeaders.add(authorization);
TimeoutTask timeoutTask = new TimeoutTask( callId,user);
if ( cacheTime != -1)
this.timer.schedule(timeoutTask, cacheTime*1000);
}
/**
* Returns an authorization header cached for the specified call id and null
* if no authorization header has been previously cached for this call.
*
* @param callid
* the call id that we'd like to retrive a cached authorization
* header for.
*
* @return authorization header corresponding to that user for the given
* proxy domain.
*/
Collection getCachedAuthorizationHeaders(
String callid) {
if (callid == null)
throw new NullPointerException("Null arg!");
return this.authorizationHeaders.get(callid);
}
/**
* Remove a cached authorization header.
*
* @param callId
*/
public void removeAuthenticationHeader(String callId) {
this.authorizationHeaders.remove(callId);
}
}
java/gov/nist/javax/sip/clientauthutils/MessageDigestAlgorithm.java 0100644 0000000 0000000 00000022244 13513104763 024670 0 ustar 00 0000000 0000000 package gov.nist.javax.sip.clientauthutils;
import gov.nist.core.StackLogger;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
/**
* The class takes standard Http Authentication details and returns a response according to the
* MD5 algorithm
*
* @author Emil Ivov
*/
public class MessageDigestAlgorithm {
/**
* Calculates an http authentication response in accordance with rfc2617.
*
*
* @param algorithm a string indicating a pair of algorithms (MD5 (default), or MD5-sess) used
* to produce the digest and a checksum.
* @param hashUserNameRealmPasswd MD5 hash of (username:realm:password)
* @param nonce_value A server-specified data string provided in the challenge.
* @param cnonce_value an optional client-chosen value whose purpose is to foil chosen
* plaintext attacks.
* @param method the SIP method of the request being challenged.
* @param digest_uri_value the value of the "uri" directive on the Authorization header in the
* request.
* @param entity_body the entity-body
* @param qop_value Indicates what "quality of protection" the client has applied to the
* message.
* @param nc_value the hexadecimal count of the number of requests (including the current
* request) that the client has sent with the nonce value in this request.
* @return a digest response as defined in rfc2617
* @throws NullPointerException in case of incorrectly null parameters.
*/
static String calculateResponse(String algorithm, String hashUserNameRealmPasswd,
String nonce_value, String nc_value, String cnonce_value,
String method, String digest_uri_value, String entity_body, String qop_value,
StackLogger stackLogger) {
if (stackLogger.isLoggingEnabled()) {
stackLogger.logDebug("trying to authenticate using : " + algorithm + ", "+
hashUserNameRealmPasswd + ", " + nonce_value + ", "
+ nc_value + ", " + cnonce_value + ", " + method + ", " + digest_uri_value
+ ", " + entity_body + ", " + qop_value);
}
if (hashUserNameRealmPasswd == null || method == null
|| digest_uri_value == null || nonce_value == null)
throw new NullPointerException(
"Null parameter to MessageDigestAlgorithm.calculateResponse()");
// The following follows closely the algorithm for generating a response
// digest as specified by rfc2617
if (cnonce_value == null || cnonce_value.length() == 0)
throw new NullPointerException(
"cnonce_value may not be absent for MD5-Sess algorithm.");
String A2 = null;
if (qop_value == null || qop_value.trim().length() == 0
|| qop_value.trim().equalsIgnoreCase("auth")) {
A2 = method + ":" + digest_uri_value;
} else {
if (entity_body == null)
entity_body = "";
A2 = method + ":" + digest_uri_value + ":" + H(entity_body);
}
String request_digest = null;
if (cnonce_value != null && qop_value != null && nc_value != null
&& (qop_value.equalsIgnoreCase("auth") || qop_value.equalsIgnoreCase("auth-int")))
{
request_digest = KD(hashUserNameRealmPasswd, nonce_value + ":" + nc_value + ":" + cnonce_value + ":"
+ qop_value + ":" + H(A2));
} else {
request_digest = KD(hashUserNameRealmPasswd, nonce_value + ":" + H(A2));
}
return request_digest;
}
/**
* Calculates an http authentication response in accordance with rfc2617.
*
*
* @param algorithm a string indicating a pair of algorithms (MD5 (default), or MD5-sess) used
* to produce the digest and a checksum.
* @param username_value username_value (see rfc2617)
* @param realm_value A string that has been displayed to the user in order to determine the
* context of the username and password to use.
* @param passwd the password to encode in the challenge response.
* @param nonce_value A server-specified data string provided in the challenge.
* @param cnonce_value an optional client-chosen value whose purpose is to foil chosen
* plaintext attacks.
* @param method the SIP method of the request being challenged.
* @param digest_uri_value the value of the "uri" directive on the Authorization header in the
* request.
* @param entity_body the entity-body
* @param qop_value Indicates what "quality of protection" the client has applied to the
* message.
* @param nc_value the hexadecimal count of the number of requests (including the current
* request) that the client has sent with the nonce value in this request.
* @return a digest response as defined in rfc2617
* @throws NullPointerException in case of incorrectly null parameters.
*/
static String calculateResponse(String algorithm, String username_value, String realm_value,
String passwd, String nonce_value, String nc_value, String cnonce_value,
String method, String digest_uri_value, String entity_body, String qop_value,
StackLogger stackLogger) {
if (stackLogger.isLoggingEnabled()) {
stackLogger.logDebug("trying to authenticate using : " + algorithm + ", "
+ username_value + ", " + realm_value + ", "
+ (passwd != null && passwd.trim().length() > 0) + ", " + nonce_value + ", "
+ nc_value + ", " + cnonce_value + ", " + method + ", " + digest_uri_value
+ ", " + entity_body + ", " + qop_value);
}
if (username_value == null || realm_value == null || passwd == null || method == null
|| digest_uri_value == null || nonce_value == null)
throw new NullPointerException(
"Null parameter to MessageDigestAlgorithm.calculateResponse()");
// The following follows closely the algorithm for generating a response
// digest as specified by rfc2617
String A1 = null;
if (algorithm == null || algorithm.trim().length() == 0
|| algorithm.trim().equalsIgnoreCase("MD5")) {
A1 = username_value + ":" + realm_value + ":" + passwd;
} else {
if (cnonce_value == null || cnonce_value.length() == 0)
throw new NullPointerException(
"cnonce_value may not be absent for MD5-Sess algorithm.");
A1 = H(username_value + ":" + realm_value + ":" + passwd) + ":" + nonce_value + ":"
+ cnonce_value;
}
String A2 = null;
if (qop_value == null || qop_value.trim().length() == 0
|| qop_value.trim().equalsIgnoreCase("auth")) {
A2 = method + ":" + digest_uri_value;
} else {
if (entity_body == null)
entity_body = "";
A2 = method + ":" + digest_uri_value + ":" + H(entity_body);
}
String request_digest = null;
if (cnonce_value != null && qop_value != null && nc_value != null
&& (qop_value.equalsIgnoreCase("auth") || qop_value.equalsIgnoreCase("auth-int")))
{
request_digest = KD(H(A1), nonce_value + ":" + nc_value + ":" + cnonce_value + ":"
+ qop_value + ":" + H(A2));
} else {
request_digest = KD(H(A1), nonce_value + ":" + H(A2));
}
return request_digest;
}
/**
* Defined in rfc 2617 as H(data) = MD5(data);
*
* @param data data
* @return MD5(data)
*/
private static String H(String data) {
try {
MessageDigest digest = MessageDigest.getInstance("MD5");
return toHexString(digest.digest(data.getBytes()));
} catch (NoSuchAlgorithmException ex) {
// shouldn't happen
throw new RuntimeException("Failed to instantiate an MD5 algorithm", ex);
}
}
/**
* Defined in rfc 2617 as KD(secret, data) = H(concat(secret, ":", data))
*
* @param data data
* @param secret secret
* @return H(concat(secret, ":", data));
*/
private static String KD(String secret, String data) {
return H(secret + ":" + data);
}
// the following code was copied from the NIST-SIP instant
// messenger (its author is Olivier Deruelle). Thanks for making it public!
/**
* to hex converter
*/
private static final char[] toHex = {
'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'a', 'b', 'c', 'd', 'e', 'f'
};
/**
* Converts b[] to hex string.
*
* @param b the bte array to convert
* @return a Hex representation of b.
*/
private static String toHexString(byte b[]) {
int pos = 0;
char[] c = new char[b.length * 2];
for (int i = 0; i < b.length; i++) {
c[pos++] = toHex[(b[i] >> 4) & 0x0F];
c[pos++] = toHex[b[i] & 0x0f];
}
return new String(c);
}
}
java/gov/nist/javax/sip/clientauthutils/SecureAccountManager.java 0100644 0000000 0000000 00000001264 13513104763 024332 0 ustar 00 0000000 0000000 package gov.nist.javax.sip.clientauthutils;
import javax.sip.ClientTransaction;
public interface SecureAccountManager {
/**
* Returns the user credentials for a given SIP Domain.
* You can implement any desired method (such as popping up a dialog for example )
* to retrieve the credentials.
*
* @param challengedTransaction - the transaction that is being challenged.
* @param realm - the realm that is being challenged for which a credential should be
* returned.
* @return -- the user credentials associated with the domain.
*/
UserCredentialHash getCredentialHash(ClientTransaction challengedTransaction, String realm);
}
java/gov/nist/javax/sip/clientauthutils/UserCredentialHash.java 0100644 0000000 0000000 00000001535 13513104763 024012 0 ustar 00 0000000 0000000 package gov.nist.javax.sip.clientauthutils;
/**
* Interface for those clients that only supply
* hash(user:domain:password). This is more secure than simply supplying
* password because the password cannot be extracted. Implementations
* tend to prefer to store information in user accounts using such a
* hash rather than plain text passwords because it offers better security.
*
*/
public interface UserCredentialHash {
/**
* Get the user name.
*
* @return userName
*/
public String getUserName();
/**
* Get the SipDomain.
*
* @return the SIP Domain.
*/
public String getSipDomain();
/**
* Get the MD5(userName:sipdomain:password)
*
* @return the MD5 hash of userName:sipDomain:password.
*/
public String getHashUserDomainPassword();
}
java/gov/nist/javax/sip/clientauthutils/UserCredentials.java 0100644 0000000 0000000 00000001456 13513104763 023373 0 ustar 00 0000000 0000000 package gov.nist.javax.sip.clientauthutils;
/**
* The class is used whenever user credentials for a particular realm (site
* server or service) are necessary
* @author Emil Ivov
* @author M. Ranganathan
* @version 1.0
*/
public interface UserCredentials
{
/**
* Returns the name of the user that these credentials relate to.
* @return the user name.
*/
public String getUserName();
/**
* Returns a password associated with this set of credentials.
*
* @return a password associated with this set of credentials.
*/
public String getPassword();
/**
* Returns the SIP Domain for this username password combination.
*
* @return the sip domain
*/
public String getSipDomain();
}
java/gov/nist/javax/sip/clientauthutils/package.html 0100644 0000000 0000000 00000001046 13513104763 021710 0 ustar 00 0000000 0000000
This package contains a set of utilities for client side Authentication Challenge handling. It has been
adapted from the SIP communicator project and generously dontated to the JAIN-SIP project
It is not part of the standard JAIN-SIP implementation at this point but is being considered for
addition as this is an operation that is commonly required by all SIP clients; it is hence a good capability
to include in a library such as JAIN-SIP.
Primary authors of this code are Emil Ivov with corrections from Jeroen van Bemmel.