/** * 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; }
/** * 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 username * @param password * @return an authorisation header in response to authHeader. * @throws OperationFailedException if auth header was malformated. */ public static AuthorizationHeader getAuthorizationHeader( String method, String uri, String requestBody, WWWAuthenticateHeader authHeader, String username, String password) { String response = null; HeaderFactory headerFactory = SipFactories.headerFactory; // 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"; try { response = MessageDigestResponseAlgorithm.calculateResponse( authHeader.getAlgorithm(), username, authHeader.getRealm(), password, authHeader.getNonce(), nc_value, // JvB added cnonce, // JvB added method, uri, requestBody, qop); // jvb changed } catch (NullPointerException exc) { throw new IllegalStateException("The authenticate header was malformatted", exc); } AuthorizationHeader authorization = null; try { if (authHeader instanceof ProxyAuthenticateHeader) { authorization = headerFactory.createProxyAuthorizationHeader(authHeader.getScheme()); } else { authorization = headerFactory.createAuthorizationHeader(authHeader.getScheme()); } authorization.setUsername(username); 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 && authHeader.getOpaque().length() > 0) { 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 SecurityException("Failed to create an authorization header!"); } return authorization; }
/* * (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<String> headerNames = challengedRequest.getHeaderNames(); while (headerNames.hasNext()) { String headerName = headerNames.next(); if (reoriginatedRequest.getHeader(headerName) != null) { ListIterator<Header> 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(); 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); } 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); } }