1600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpackage gov.nist.javax.sip.clientauthutils;
2600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
3600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/*
4600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
5600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * This code has been contributed with permission from:
6600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
7600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * SIP Communicator, the OpenSource Java VoIP and Instant Messaging client but has been significantly changed.
8600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * It is donated to the JAIN-SIP project as it is common code that many sip clients
9600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * need to perform class and others will consitute a set of utility functions
10600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * that will implement common operations that ease the life of the developer.
11600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
12600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Acknowledgements:
13600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * ----------------
14600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
15600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * Fredrik Wickstrom reported that dialog cseq counters are not incremented
16600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * when resending requests. He later uncovered additional problems and
17600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * proposed a way to fix them (his proposition was taken into account).
18600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */
19600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
20600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.SipStackImpl;
21600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.address.SipUri;
22600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.message.SIPRequest;
23600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.SIPClientTransaction;
24600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport gov.nist.javax.sip.stack.SIPTransactionStack;
25600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
26600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.text.ParseException;
27600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Collection;
28600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Iterator;
29600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.ListIterator;
30600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport java.util.Timer;
31600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
32600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.ClientTransaction;
33600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.DialogState;
34600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.InvalidArgumentException;
35600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.SipException;
36600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.SipProvider;
37600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.address.Hop;
38600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.address.SipURI;
39600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.address.URI;
40600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.AuthorizationHeader;
41600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.CSeqHeader;
42600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.Header;
43600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.HeaderFactory;
44600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ProxyAuthenticateHeader;
45600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ProxyAuthorizationHeader;
46600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.ViaHeader;
47600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.header.WWWAuthenticateHeader;
48600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.message.Request;
49600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangimport javax.sip.message.Response;
50600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
51600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang/**
52600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * The class handles authentication challenges, caches user credentials and takes care (through
53600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * the SecurityAuthority interface) about retrieving passwords.
54600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
55600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
56600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author Emil Ivov
57600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author Jeroen van Bemmel
58600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @author M. Ranganathan
59600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang *
60600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang * @since 2.0
61600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang */
62600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
63600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wangpublic class AuthenticationHelperImpl implements AuthenticationHelper {
64600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
65600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
66600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Credentials cached so far.
67600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
68600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private CredentialsCache cachedCredentials;
69600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
70600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
71600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * The account manager for the system. Stores user credentials.
72600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
73600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private Object accountManager = null;
74600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
75600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
76600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Header factory for this security manager.
77600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
78600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private HeaderFactory headerFactory;
79600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
80600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private SipStackImpl sipStack;
81600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
82600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    Timer timer;
83600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
84600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
85600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Default constructor for the security manager. There is one Account manager. There is one
86600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * SipSecurity manager for every user name,
87600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
88600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param sipStack -- our stack.
89600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param accountManager -- an implementation of the AccountManager interface.
90600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param headerFactory -- header factory.
91600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
92600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public AuthenticationHelperImpl(SipStackImpl sipStack, AccountManager accountManager,
93600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            HeaderFactory headerFactory) {
94600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.accountManager = accountManager;
95600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.headerFactory = headerFactory;
96600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.sipStack = sipStack;
97600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
98600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.cachedCredentials = new CredentialsCache(((SIPTransactionStack) sipStack).getTimer());
99600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
100600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
101600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
102600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Default constructor for the security manager. There is one Account manager. There is one
103600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * SipSecurity manager for every user name,
104600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
105600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param sipStack -- our stack.
106600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param accountManager -- an implementation of the AccountManager interface.
107600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param headerFactory -- header factory.
108600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
109600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public AuthenticationHelperImpl(SipStackImpl sipStack, SecureAccountManager accountManager,
110600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            HeaderFactory headerFactory) {
111600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.accountManager = accountManager;
112600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.headerFactory = headerFactory;
113600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.sipStack = sipStack;
114600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
115600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.cachedCredentials = new CredentialsCache(((SIPTransactionStack) sipStack).getTimer());
116600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
117600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
118600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
119600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
120600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
121600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
122600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see gov.nist.javax.sip.clientauthutils.AuthenticationHelper#handleChallenge(javax.sip.message.Response,
123600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *      javax.sip.ClientTransaction, javax.sip.SipProvider)
124600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
125600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public ClientTransaction handleChallenge(Response challenge,
126600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            ClientTransaction challengedTransaction, SipProvider transactionCreator, int cacheTime)
127600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throws SipException, NullPointerException {
128600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
129600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (sipStack.isLoggingEnabled()) {
130600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.getStackLogger().logDebug("handleChallenge: " + challenge);
131600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
132600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
133600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            SIPRequest challengedRequest = ((SIPRequest) challengedTransaction.getRequest());
134600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
135600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            Request reoriginatedRequest = null;
136600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            /*
137600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang             * If the challenged request is part of a Dialog and the
138600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang             * Dialog is confirmed the re-originated request should be
139600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang             * generated as an in-Dialog request.
140600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang             */
141600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (  challengedRequest.getToTag() != null  ||
142600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    challengedTransaction.getDialog() == null ||
143600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    challengedTransaction.getDialog().getState() != DialogState.CONFIRMED)  {
144600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                reoriginatedRequest = (Request) challengedRequest.clone();
145600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else {
146600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                /*
147600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                 * Re-originate the request by consulting the dialog. In particular
148600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                 * the route set could change between the original request and the
149600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                 * in-dialog challenge.
150600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                 */
151600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                reoriginatedRequest =
152600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    challengedTransaction.getDialog().createRequest(challengedRequest.getMethod());
153600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                Iterator<String> headerNames = challengedRequest.getHeaderNames();
154600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                while (headerNames.hasNext()) {
155600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    String headerName = headerNames.next();
156600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if ( reoriginatedRequest.getHeader(headerName) != null) {
157600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        ListIterator<Header> iterator = reoriginatedRequest.getHeaders(headerName);
158600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        while (iterator.hasNext()) {
159600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            reoriginatedRequest.addHeader(iterator.next());
160600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        }
161600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    }
162600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
163600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
164600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
165600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
166600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
167600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // remove the branch id so that we could use the request in a new
168600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // transaction
169600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            removeBranchID(reoriginatedRequest);
170600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
171600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (challenge == null || reoriginatedRequest == null) {
172600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                throw new NullPointerException("A null argument was passed to handle challenge.");
173600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
174600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
175600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            ListIterator authHeaders = null;
176600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
177600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (challenge.getStatusCode() == Response.UNAUTHORIZED) {
178600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                authHeaders = challenge.getHeaders(WWWAuthenticateHeader.NAME);
179600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else if (challenge.getStatusCode() == Response.PROXY_AUTHENTICATION_REQUIRED) {
180600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                authHeaders = challenge.getHeaders(ProxyAuthenticateHeader.NAME);
181600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else {
182600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                throw new IllegalArgumentException("Unexpected status code ");
183600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
184600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
185600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (authHeaders == null) {
186600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                throw new IllegalArgumentException(
187600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        "Could not find WWWAuthenticate or ProxyAuthenticate headers");
188600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
189600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
190600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // Remove all authorization headers from the request (we'll re-add them
191600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // from cache)
192600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            reoriginatedRequest.removeHeader(AuthorizationHeader.NAME);
193600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            reoriginatedRequest.removeHeader(ProxyAuthorizationHeader.NAME);
194600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
195600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // rfc 3261 says that the cseq header should be augmented for the new
196600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // request. do it here so that the new dialog (created together with
197600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // the new client transaction) takes it into account.
198600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // Bug report - Fredrik Wickstrom
199600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            CSeqHeader cSeq = (CSeqHeader) reoriginatedRequest.getHeader((CSeqHeader.NAME));
200600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            try {
201600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                cSeq.setSeqNumber(cSeq.getSeqNumber() + 1l);
202600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } catch (InvalidArgumentException ex) {
203600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                throw new SipException("Invalid CSeq -- could not increment : "
204600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        + cSeq.getSeqNumber());
205600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
206600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
207600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
208600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            /* Resolve this to the next hop based on the previous lookup. If we are not using
209600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang             * lose routing (RFC2543) then just attach hop as a maddr param.
210600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang             */
211600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if ( challengedRequest.getRouteHeaders() == null ) {
212600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                Hop hop   = ((SIPClientTransaction) challengedTransaction).getNextHop();
213600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                SipURI sipUri = (SipURI) reoriginatedRequest.getRequestURI();
2141e0f37693341071f316852c8e05a08deef2b7fc4Chia-chi Yeh                // BEGIN android-added
215a58e4068f86c6ca3f9771d4ec8b2665d070a170eChung-yih Wang                if ( !hop.getHost().equalsIgnoreCase(sipUri.getHost())
216a58e4068f86c6ca3f9771d4ec8b2665d070a170eChung-yih Wang                        && !hop.equals(sipStack.getRouter(challengedRequest).getOutboundProxy()) )
2171e0f37693341071f316852c8e05a08deef2b7fc4Chia-chi Yeh                // END android-added
218600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipUri.setMAddrParam(hop.getHost());
219600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if ( hop.getPort() != -1 ) sipUri.setPort(hop.getPort());
220600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
221600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            ClientTransaction retryTran = transactionCreator
222600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            .getNewClientTransaction(reoriginatedRequest);
223600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
224600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            WWWAuthenticateHeader authHeader = null;
225600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            SipURI requestUri = (SipURI) challengedTransaction.getRequest().getRequestURI();
226600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            while (authHeaders.hasNext()) {
227600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                authHeader = (WWWAuthenticateHeader) authHeaders.next();
228600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                String realm = authHeader.getRealm();
229600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                AuthorizationHeader authorization = null;
230600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                String sipDomain;
231600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if ( this.accountManager instanceof SecureAccountManager ) {
232600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    UserCredentialHash credHash =
233600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        ((SecureAccountManager)this.accountManager).getCredentialHash(challengedTransaction,realm);
234600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    URI uri = reoriginatedRequest.getRequestURI();
235600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    sipDomain = credHash.getSipDomain();
236600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    authorization = this.getAuthorization(reoriginatedRequest
237600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            .getMethod(), uri.toString(),
238600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            (reoriginatedRequest.getContent() == null) ? "" : new String(
239600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            reoriginatedRequest.getRawContent()), authHeader, credHash);
240600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                } else {
241600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    UserCredentials userCreds = ((AccountManager) this.accountManager).getCredentials(challengedTransaction, realm);
242600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    sipDomain = userCreds.getSipDomain();
243600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    if (userCreds == null)
244600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                         throw new SipException(
245600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            "Cannot find user creds for the given user name and realm");
246600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
247600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    // we haven't yet authenticated this realm since we were
248600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    // started.
249600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
250600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                       authorization = this.getAuthorization(reoriginatedRequest
251600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                .getMethod(), reoriginatedRequest.getRequestURI().toString(),
252600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                (reoriginatedRequest.getContent() == null) ? "" : new String(
253600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                                reoriginatedRequest.getRawContent()), authHeader, userCreds);
254600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                }
255600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (sipStack.isLoggingEnabled())
256600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                	sipStack.getStackLogger().logDebug(
257600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        "Created authorization header: " + authorization.toString());
258600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
259600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                if (cacheTime != 0)
260600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    cachedCredentials.cacheAuthorizationHeader(sipDomain,
261600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                            authorization, cacheTime);
262600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
263600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                reoriginatedRequest.addHeader(authorization);
264600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
265600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
266600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (sipStack.isLoggingEnabled()) {
267600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                sipStack.getStackLogger().logDebug(
268600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        "Returning authorization transaction." + retryTran);
269600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
270600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return retryTran;
271600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (SipException ex) {
272600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw ex;
273600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (Exception ex) {
274600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            sipStack.getStackLogger().logError("Unexpected exception ", ex);
275600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new SipException("Unexpected exception ", ex);
276600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
277600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
278600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
279600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
280600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
281600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
282600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
283600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Generates an authorisation header in response to wwwAuthHeader.
284600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
285600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param method method of the request being authenticated
286600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param uri digest-uri
287600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param requestBody the body of the request.
288600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param authHeader the challenge that we should respond to
289600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param userCredentials username and pass
290600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
291600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return an authorisation header in response to authHeader.
292600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
293600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @throws OperationFailedException if auth header was malformated.
294600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
295600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private AuthorizationHeader getAuthorization(String method, String uri, String requestBody,
296600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            WWWAuthenticateHeader authHeader, UserCredentials userCredentials) {
297600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String response = null;
298600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
299600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // JvB: authHeader.getQop() is a quoted _list_ of qop values
300600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // (e.g. "auth,auth-int") Client is supposed to pick one
301600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String qopList = authHeader.getQop();
302600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String qop = (qopList != null) ? "auth" : null;
303600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String nc_value = "00000001";
304600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String cnonce = "xyz";
305600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
306600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        response = MessageDigestAlgorithm.calculateResponse(authHeader.getAlgorithm(),
307600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                userCredentials.getUserName(), authHeader.getRealm(), userCredentials
308600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        .getPassword(), authHeader.getNonce(), nc_value, // JvB added
309600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                cnonce, // JvB added
310600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                method, uri, requestBody, qop,sipStack.getStackLogger());// jvb changed
311600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
312600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        AuthorizationHeader authorization = null;
313600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
314600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (authHeader instanceof ProxyAuthenticateHeader) {
315600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                authorization = headerFactory.createProxyAuthorizationHeader(authHeader
316600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        .getScheme());
317600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else {
318600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                authorization = headerFactory.createAuthorizationHeader(authHeader.getScheme());
319600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
320600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
321600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            authorization.setUsername(userCredentials.getUserName());
322600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            authorization.setRealm(authHeader.getRealm());
323600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            authorization.setNonce(authHeader.getNonce());
324600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            authorization.setParameter("uri", uri);
325600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            authorization.setResponse(response);
326600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (authHeader.getAlgorithm() != null) {
327600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                authorization.setAlgorithm(authHeader.getAlgorithm());
328600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
329600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
330600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (authHeader.getOpaque() != null) {
331600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                authorization.setOpaque(authHeader.getOpaque());
332600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
333600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
334600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // jvb added
335600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (qop != null) {
336600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                authorization.setQop(qop);
337600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                authorization.setCNonce(cnonce);
338600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                authorization.setNonceCount(Integer.parseInt(nc_value));
339600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
340600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
341600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            authorization.setResponse(response);
342600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
343600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (ParseException ex) {
344600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new RuntimeException("Failed to create an authorization header!");
345600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
346600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
347600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return authorization;
348600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
349600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
350600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Generates an authorisation header in response to wwwAuthHeader.
351600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
352600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param method method of the request being authenticated
353600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param uri digest-uri
354600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param requestBody the body of the request.
355600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param authHeader the challenge that we should respond to
356600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param userCredentials username and pass
357600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
358600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @return an authorisation header in response to authHeader.
359600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
360600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @throws OperationFailedException if auth header was malformated.
361600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
362600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private AuthorizationHeader getAuthorization(String method, String uri, String requestBody,
363600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            WWWAuthenticateHeader authHeader, UserCredentialHash userCredentials) {
364600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String response = null;
365600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
366600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // JvB: authHeader.getQop() is a quoted _list_ of qop values
367600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        // (e.g. "auth,auth-int") Client is supposed to pick one
368600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String qopList = authHeader.getQop();
369600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String qop = (qopList != null) ? "auth" : null;
370600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String nc_value = "00000001";
371600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String cnonce = "xyz";
372600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
373600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        response = MessageDigestAlgorithm.calculateResponse(authHeader.getAlgorithm(),
374600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang              userCredentials.getHashUserDomainPassword(), authHeader.getNonce(), nc_value, // JvB added
375600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                cnonce, // JvB added
376600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                method, uri, requestBody, qop,sipStack.getStackLogger());// jvb changed
377600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
378600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        AuthorizationHeader authorization = null;
379600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        try {
380600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (authHeader instanceof ProxyAuthenticateHeader) {
381600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                authorization = headerFactory.createProxyAuthorizationHeader(authHeader
382600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                        .getScheme());
383600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            } else {
384600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                authorization = headerFactory.createAuthorizationHeader(authHeader.getScheme());
385600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
386600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
387600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            authorization.setUsername(userCredentials.getUserName());
388600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            authorization.setRealm(authHeader.getRealm());
389600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            authorization.setNonce(authHeader.getNonce());
390600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            authorization.setParameter("uri", uri);
391600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            authorization.setResponse(response);
392600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (authHeader.getAlgorithm() != null) {
393600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                authorization.setAlgorithm(authHeader.getAlgorithm());
394600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
395600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
396600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (authHeader.getOpaque() != null) {
397600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                authorization.setOpaque(authHeader.getOpaque());
398600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
399600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
400600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            // jvb added
401600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            if (qop != null) {
402600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                authorization.setQop(qop);
403600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                authorization.setCNonce(cnonce);
404600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                authorization.setNonceCount(Integer.parseInt(nc_value));
405600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            }
406600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
407600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            authorization.setResponse(response);
408600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
409600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        } catch (ParseException ex) {
410600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new RuntimeException("Failed to create an authorization header!");
411600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
412600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
413600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        return authorization;
414600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
415600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /**
416600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * Removes all via headers from <tt>request</tt> and replaces them with a new one, equal to
417600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * the one that was top most.
418600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
419600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @param request the Request whose branchID we'd like to remove.
420600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
421600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
422600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    private void removeBranchID(Request request) {
423600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
424600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        ViaHeader viaHeader = (ViaHeader) request.getHeader(ViaHeader.NAME);
425600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
426600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        viaHeader.removeParameter("branch");
427600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
428600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
429600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
430600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
431600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
432600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
433600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see gov.nist.javax.sip.clientauthutils.AuthenticationHelper#attachAuthenticationHeaders(javax.sip.message.Request)
434600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
435600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void setAuthenticationHeaders(Request request) {
436600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        SIPRequest sipRequest = (SIPRequest) request;
437600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
438600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        String callId = sipRequest.getCallId().getCallId();
439600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
440600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        request.removeHeader(AuthorizationHeader.NAME);
441600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        Collection<AuthorizationHeader> authHeaders = this.cachedCredentials
442600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                .getCachedAuthorizationHeaders(callId);
443600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (authHeaders == null) {
444600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        	if (sipStack.isLoggingEnabled())
445600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        		sipStack.getStackLogger().logDebug(
446600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang                    "Could not find authentication headers for " + callId);
447600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            return;
448600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
449600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
450600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        for (AuthorizationHeader authHeader : authHeaders) {
451600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            request.addHeader(authHeader);
452600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        }
453600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
454600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
455600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
456600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    /*
457600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * (non-Javadoc)
458600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     *
459600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     * @see gov.nist.javax.sip.clientauthutils.AuthenticationHelper#removeCachedAuthenticationHeaders(java.lang.String)
460600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang     */
461600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    public void removeCachedAuthenticationHeaders(String callId) {
462600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        if (callId == null)
463600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang            throw new NullPointerException("Null callId argument ");
464600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang        this.cachedCredentials.removeAuthenticationHeader(callId);
465600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
466600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang    }
467600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang
468600c7a4bbc7348167293eac928192e695b4ad5baChung-yih Wang}
469