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