use of javax.sip.InvalidArgumentException in project Openfire by igniterealtime.
the class SipSecurityManager method handleChallenge.
/**
* Uses securityAuthority to determinie a set of valid user credentials for
* the specified Response (Challenge) and appends it to the challenged
* request so that it could be retransmitted.
* <p/>
* Fredrik Wickstrom reported that dialog cseq counters are not incremented
* when resending requests. He later uncovered additional problems and
* proposed a way to fix them (his proposition was taken into account).
*
* @param challenge the 401/407 challenge response
* @param challengedTransaction the transaction established by the challenged request
* @return a transaction containing a reoriginated request with the
* necessary authorization header.
* @throws SipSecurityException
*/
public ClientTransaction handleChallenge(Response challenge, ClientTransaction challengedTransaction) throws SipSecurityException, SipException, InvalidArgumentException, ParseException {
try {
String branchID = challengedTransaction.getBranchId();
Request challengedRequest = challengedTransaction.getRequest();
Request reoriginatedRequest = (Request) challengedRequest.clone();
ListIterator authHeaders = null;
if (challenge == null || reoriginatedRequest == null)
throw new NullPointerException("A null argument was passed to handle challenge.");
if (challenge.getStatusCode() == Response.UNAUTHORIZED)
authHeaders = challenge.getHeaders(WWWAuthenticateHeader.NAME);
else if (challenge.getStatusCode() == Response.PROXY_AUTHENTICATION_REQUIRED)
authHeaders = challenge.getHeaders(ProxyAuthenticateHeader.NAME);
if (authHeaders == null)
throw new SecurityException("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));
cSeq.setSequenceNumber(cSeq.getSequenceNumber() + 1);
ClientTransaction retryTran = transactionCreator.getNewClientTransaction(reoriginatedRequest);
WWWAuthenticateHeader authHeader = null;
CredentialsCacheEntry ccEntry = null;
while (authHeaders.hasNext()) {
authHeader = (WWWAuthenticateHeader) authHeaders.next();
String realm = authHeader.getRealm();
// Check whether we have cached credentials for authHeader's
// realm
// make sure that if such credentials exist they get removed.
// The
// challenge means that there's something wrong with them.
ccEntry = cachedCredentials.remove(realm);
// Try to guess user name and facilitate user
UserCredentials defaultCredentials = new UserCredentials();
FromHeader from = (FromHeader) reoriginatedRequest.getHeader(FromHeader.NAME);
URI uri = from.getAddress().getURI();
if (uri.isSipURI()) {
Log.debug("handleChallenge", SIPConfig.getAuthUserName());
String user = SIPConfig.getAuthUserName() != null ? SIPConfig.getAuthUserName() : ((SipURI) uri).getUser();
defaultCredentials.setAuthUserName(user == null ? SIPConfig.getUserName() : user);
}
boolean ccEntryHasSeenTran = false;
if (ccEntry != null)
ccEntryHasSeenTran = ccEntry.processResponse(branchID);
// get a new pass
if (// we don't have credentials for the
ccEntry == null || // specified realm
((!authHeader.isStale() && ccEntryHasSeenTran))) {
if (ccEntry == null) {
ccEntry = new CredentialsCacheEntry();
ccEntry.userCredentials = defaultCredentials;
}
// put the returned user name in the properties file
// so that it appears as a default one next time user is
// prompted for pass
SIPConfig.setUserName(ccEntry.userCredentials.getUserName());
} else // encode and send what we have
if (ccEntry != null && (!ccEntryHasSeenTran || authHeader.isStale())) {
}
// if user canceled or sth else went wrong
if (ccEntry.userCredentials == null)
throw new SecurityException("Unable to authenticate with realm " + realm);
AuthorizationHeader authorization = this.getAuthorization(reoriginatedRequest.getMethod(), reoriginatedRequest.getRequestURI().toString(), reoriginatedRequest.getContent() == null ? "" : reoriginatedRequest.getContent().toString(), authHeader, ccEntry.userCredentials);
ccEntry.processRequest(retryTran.getBranchId());
cachedCredentials.cacheEntry(realm, ccEntry);
reoriginatedRequest.addHeader(authorization);
// if there was trouble with the user - make sure we fix it
if (uri.isSipURI()) {
((SipURI) uri).setUser(ccEntry.userCredentials.getUserName());
Address add = from.getAddress();
add.setURI(uri);
from.setAddress(add);
reoriginatedRequest.setHeader(from);
if (challengedRequest.getMethod().equals(Request.REGISTER)) {
ToHeader to = (ToHeader) reoriginatedRequest.getHeader(ToHeader.NAME);
add.setURI(uri);
to.setAddress(add);
reoriginatedRequest.setHeader(to);
}
// very ugly but very necessary
sipManCallback.setCurrentlyUsedURI(uri.toString());
Log.debug("URI: " + uri.toString());
}
// if this is a register - fix to as well
}
return retryTran;
} catch (Exception e) {
Log.debug("ERRO REG: " + e.toString());
return null;
}
}
use of javax.sip.InvalidArgumentException in project Openfire by igniterealtime.
the class SimpleSession method prepareSubscribeRequest.
private Request prepareSubscribeRequest(String destination) throws InvalidArgumentException, ParseException {
String destUsername = destination;
String destHost = sipHost;
if (destination.indexOf("@") == 0 || destination.indexOf("@") == destination.length() - 1) {
throw new InvalidArgumentException("The address provided is invalid!");
} else if (destination.indexOf("@") > 0) {
destUsername = destination.substring(0, destination.indexOf("@"));
destHost = destination.substring(destination.indexOf("@") + 1);
}
SipURI destUri = addressFactory.createSipURI(destUsername, destHost);
return prepareRequest(RequestType.SUBSCRIBE, destUri, null, destUri, null, 1L);
}
use of javax.sip.InvalidArgumentException in project XobotOS by xamarin.
the class SIPDialog method createAck.
/*
* (non-Javadoc) The UAC core MUST generate an ACK request for each 2xx received from the
* transaction layer. The header fields of the ACK are constructed in the same way as for any
* request sent within a dialog (see Section 12) with the exception of the CSeq and the header
* fields related to authentication. The sequence number of the CSeq header field MUST be the
* same as the INVITE being acknowledged, but the CSeq method MUST be ACK. The ACK MUST
* contain the same credentials as the INVITE. If the 2xx contains an offer (based on the
* rules above), the ACK MUST carry an answer in its body. If the offer in the 2xx response is
* not acceptable, the UAC core MUST generate a valid answer in the ACK and then send a BYE
* immediately.
*
* Note that for the case of forked requests, you can create multiple outgoing invites each
* with a different cseq and hence you need to supply the invite.
*
* @see javax.sip.Dialog#createAck(long)
*/
public Request createAck(long cseqno) throws InvalidArgumentException, SipException {
// then send INVITE+ACK later on
if (!method.equals(Request.INVITE))
throw new SipException("Dialog was not created with an INVITE" + method);
if (cseqno <= 0)
throw new InvalidArgumentException("bad cseq <= 0 ");
else if (cseqno > ((((long) 1) << 32) - 1))
throw new InvalidArgumentException("bad cseq > " + ((((long) 1) << 32) - 1));
if (this.remoteTarget == null) {
throw new SipException("Cannot create ACK - no remote Target!");
}
if (this.sipStack.isLoggingEnabled()) {
this.sipStack.getStackLogger().logDebug("createAck " + this + " cseqno " + cseqno);
}
// out of order ACK sending. Old ACKs seqno's can always be ACKed.
if (lastInviteOkReceived < cseqno) {
if (sipStack.isLoggingEnabled()) {
this.sipStack.getStackLogger().logDebug("WARNING : Attempt to crete ACK without OK " + this);
this.sipStack.getStackLogger().logDebug("LAST RESPONSE = " + this.lastResponse);
}
throw new SipException("Dialog not yet established -- no OK response!");
}
try {
// JvB: Transport from first entry in route set, or remote Contact
// if none
// Only used to find correct LP & create correct Via
SipURI uri4transport = null;
if (this.routeList != null && !this.routeList.isEmpty()) {
Route r = (Route) this.routeList.getFirst();
uri4transport = ((SipURI) r.getAddress().getURI());
} else {
// should be !=null, checked above
uri4transport = ((SipURI) this.remoteTarget.getURI());
}
String transport = uri4transport.getTransportParam();
if (transport == null) {
// JvB fix: also support TLS
transport = uri4transport.isSecure() ? ListeningPoint.TLS : ListeningPoint.UDP;
}
ListeningPointImpl lp = (ListeningPointImpl) sipProvider.getListeningPoint(transport);
if (lp == null) {
if (sipStack.isLoggingEnabled()) {
sipStack.getStackLogger().logError("remoteTargetURI " + this.remoteTarget.getURI());
sipStack.getStackLogger().logError("uri4transport = " + uri4transport);
sipStack.getStackLogger().logError("No LP found for transport=" + transport);
}
throw new SipException("Cannot create ACK - no ListeningPoint for transport towards next hop found:" + transport);
}
SIPRequest sipRequest = new SIPRequest();
sipRequest.setMethod(Request.ACK);
sipRequest.setRequestURI((SipUri) getRemoteTarget().getURI().clone());
sipRequest.setCallId(this.callIdHeader);
sipRequest.setCSeq(new CSeq(cseqno, Request.ACK));
List<Via> vias = new ArrayList<Via>();
// Via via = lp.getViaHeader();
// The user may have touched the sentby for the response.
// so use the via header extracted from the response for the ACK =>
// https://jain-sip.dev.java.net/issues/show_bug.cgi?id=205
// strip the params from the via of the response and use the params from the
// original request
Via via = this.lastResponse.getTopmostVia();
via.removeParameters();
if (originalRequest != null && originalRequest.getTopmostVia() != null) {
NameValueList originalRequestParameters = originalRequest.getTopmostVia().getParameters();
if (originalRequestParameters != null && originalRequestParameters.size() > 0) {
via.setParameters((NameValueList) originalRequestParameters.clone());
}
}
// new branch
via.setBranch(Utils.getInstance().generateBranchId());
vias.add(via);
sipRequest.setVia(vias);
From from = new From();
from.setAddress(this.localParty);
from.setTag(this.myTag);
sipRequest.setFrom(from);
To to = new To();
to.setAddress(this.remoteParty);
if (hisTag != null)
to.setTag(this.hisTag);
sipRequest.setTo(to);
sipRequest.setMaxForwards(new MaxForwards(70));
if (this.originalRequest != null) {
Authorization authorization = this.originalRequest.getAuthorization();
if (authorization != null)
sipRequest.setHeader(authorization);
}
// ACKs for 2xx responses
// use the Route values learned from the Record-Route of the 2xx
// responses.
this.updateRequest(sipRequest);
return sipRequest;
} catch (Exception ex) {
InternalErrorHandler.handleException(ex);
throw new SipException("unexpected exception ", ex);
}
}
use of javax.sip.InvalidArgumentException in project XobotOS by xamarin.
the class SIPClientTransaction method fireRetransmissionTimer.
/**
* Called by the transaction stack when a retransmission timer fires.
*/
protected void fireRetransmissionTimer() {
try {
// Resend the last request sent
if (this.getState() == null || !this.isMapped)
return;
boolean inv = isInviteTransaction();
TransactionState s = this.getState();
// Bug-fix for non-INVITE transactions not retransmitted when 1xx response received
if ((inv && TransactionState.CALLING == s) || (!inv && (TransactionState.TRYING == s || TransactionState.PROCEEDING == s))) {
if (lastRequest != null) {
if (sipStack.generateTimeStampHeader && lastRequest.getHeader(TimeStampHeader.NAME) != null) {
long milisec = System.currentTimeMillis();
TimeStamp timeStamp = new TimeStamp();
try {
timeStamp.setTimeStamp(milisec);
} catch (InvalidArgumentException ex) {
InternalErrorHandler.handleException(ex);
}
lastRequest.setHeader(timeStamp);
}
super.sendMessage(lastRequest);
if (this.notifyOnRetransmit) {
TimeoutEvent txTimeout = new TimeoutEvent(this.getSipProvider(), this, Timeout.RETRANSMIT);
this.getSipProvider().handleEvent(txTimeout, this);
}
if (this.timeoutIfStillInCallingState && this.getState() == TransactionState.CALLING) {
this.callingStateTimeoutCount--;
if (callingStateTimeoutCount == 0) {
TimeoutEvent timeoutEvent = new TimeoutEvent(this.getSipProvider(), this, Timeout.RETRANSMIT);
this.getSipProvider().handleEvent(timeoutEvent, this);
this.timeoutIfStillInCallingState = false;
}
}
}
}
} catch (IOException e) {
this.raiseIOExceptionEvent();
raiseErrorEvent(SIPTransactionErrorEvent.TRANSPORT_ERROR);
}
}
use of javax.sip.InvalidArgumentException in project XobotOS by xamarin.
the class SIPDialog method resendAck.
/**
* Resend the last ack.
*/
public void resendAck() throws SipException {
if (this.getLastAckSent() != null) {
if (getLastAckSent().getHeader(TimeStampHeader.NAME) != null && sipStack.generateTimeStampHeader) {
TimeStamp ts = new TimeStamp();
try {
ts.setTimeStamp(System.currentTimeMillis());
getLastAckSent().setHeader(ts);
} catch (InvalidArgumentException e) {
}
}
this.sendAck(getLastAckSent(), false);
}
}
Aggregations