3

I am developing a SIP client using JAIN SIP library in eclipse environment.

I am having trouble getting authorization. I have also implemented the MD5 challenge and added Authorization to the second Register function.

The authorization credentials are also correct as I checked them with available SIP application. I was able to Register and make calls with it.

This is the code for initialization and registration

String username = "username";
String server = "10.99.00.00";
String password = "password";
String realm = null ;
private String nonce = null;

// Objects used to communicate to the JAIN SIP API.
SipFactory sipFactory;          // Used to access the SIP API.
SipStack sipStack;              // The SIP stack.
SipProvider sipProvider;        // Used to send SIP messages.
MessageFactory messageFactory;  // Used to create SIP message factory.
HeaderFactory headerFactory;    // Used to create SIP headers.
AddressFactory addressFactory;  // Used to create SIP URIs.
ListeningPoint listeningPoint;  // SIP listening IP address/port.
Properties properties;          // Other properties.
ClientTransaction inviteTid;
Request request;
Response response;

// Objects keeping local configuration.
String proxy = null;
String sipIP="10.99.00.00"; 
String localIP= null;
// The local IP address.
int sipport = 5060;                // The local port.
int rport = 52216;
String protocol = "UDP";        // The local protocol (UDP).
int tag = (new Random()).nextInt(); // The local tag.
Address contactAddress;         // The contact address.
ContactHeader contactHeader;    // The contact header.
private Dialog dialog;
private Logger logger;
private String current_process;

public test() throws NoSuchAlgorithmException, ParseException{
    init();
    Response response = null;
    register(response);
}

public void init() {
    try {
    // Get the local IP address.
    localIP = InetAddress.getLocalHost().getHostAddress();

    // Create the SIP factory and set the path name.
    sipFactory = SipFactory.getInstance();
    sipFactory.setPathName("gov.nist");
    // Create and set the SIP stack properties.
    properties = new Properties();
    properties.setProperty("javax.sip.STACK_NAME", "stack");
    properties.setProperty("gov.nist.javax.sip.TRACE_LEVEL", "32");

    if(proxy != null) {
    properties.setProperty("javax.sip.OUTBOUND_PROXY", sipIP + ':' + sipport + '/' + protocol);
    }

    properties.setProperty("gov.nist.javax.sip.LOG_MESSAGE_CONTENT", "true");
    properties.setProperty("gov.nist.javax.sip.DEBUG_LOG",  "mss-jsip-debuglog.txt");
    properties.setProperty("gov.nist.javax.sip.SERVER_LOG","mss-jsip-messages.xml");
    // Create the SIP stack.
    sipStack = sipFactory.createSipStack(this.properties);
    // Create the SIP message factory.
    messageFactory = sipFactory.createMessageFactory();
    // Create the SIP header factory.
    headerFactory = sipFactory.createHeaderFactory();
    // Create the SIP address factory.
    addressFactory = sipFactory.createAddressFactory();
    // Create the SIP listening point and bind it to the local IP
    // address, port and protocol.
    listeningPoint = sipStack.createListeningPoint(localIP, rport, protocol);
    // Create the SIP provider.
    sipProvider = sipStack.createSipProvider(listeningPoint);
    // Add our application as a SIP listener.
    sipProvider.addSipListener(this);


    // Display the local IP address and port in the text area.
    } catch (Exception e) {
    e.printStackTrace();
    // If an error occurs, display an error message box and exit.
    System.exit(-1);
    }
    }
    int cseq;
public void register(Response response) {
    try {

    cseq++;
    current_process = cseq + "REGISTER";
    ArrayList viaHeaders = new ArrayList();
    ViaHeader viaHeader = headerFactory.createViaHeader(localIP,
    rport, "udp", null);
    viaHeader.setRPort();
    viaHeaders.add(viaHeader);
    // The "Max-Forwards" header.
    MaxForwardsHeader maxForwardsHeader = headerFactory.createMaxForwardsHeader(70);
    // The "Call-Id" header.
    CallIdHeader callIdHeader = sipProvider.getNewCallId();
    // The "CSeq" header.
    @SuppressWarnings("deprecation")
    CSeqHeader cSeqHeader = headerFactory.createCSeqHeader(1L,Request.REGISTER);

    Address fromAddress = addressFactory.createAddress("sip:"
    + "username" + '@' + server);

    FromHeader fromHeader = headerFactory.createFromHeader(
    fromAddress, String.valueOf(this.tag));
    // The "To" header.

    ToHeader toHeader = headerFactory.createToHeader(fromAddress , null);

    // Create the contact address used for all SIP messages.
    contactAddress = addressFactory.createAddress("sip:" + username + "@"+ localIP +":"+rport+ ";"+ "transport=UDP");
    // Create the contact header used for all SIP messages.
    contactHeader = headerFactory.createContactHeader(contactAddress);

    URI requestURI = addressFactory.createURI("sip:" + server);

    request = messageFactory.createRequest(requestURI, Request.REGISTER,callIdHeader, cSeqHeader, fromHeader, toHeader, viaHeaders, maxForwardsHeader);

    request.addHeader(contactHeader);


//      System.out.println(request.toString());
    if (response != null) {

    AuthorizationHeader authHeader = makeAuthHeader(headerFactory, response, request, username, password);
    request.addHeader(authHeader);
    }
    inviteTid = sipProvider.getNewClientTransaction(request);
    // send the request out.
    inviteTid.sendRequest();

//      dialog = inviteTid.getDialog();

    System.out.println(request.toString());
    // Send the request statelessly through the SIP provider.
//          this.sipProvider.sendRequest(request);

    // Display the message in the text area.
//      logger.debug("Request sent:\n" + request.toString() + "\n\n");
    } catch (Exception e) {
    // If an error occurred, display the error.
    e.printStackTrace();
//      logger.debug("Request sent failed: " + e.getMessage() + "\n");
    }

    }

private AuthorizationHeader makeAuthHeader(HeaderFactory headerFactory2,  Response response, Request request, String username2,
        String password2) throws ParseException {
    // TODO Auto-generated method stub
    // Authenticate header with challenge we need to reply to
    WWWAuthenticateHeader ah_c =  (WWWAuthenticateHeader)response.getHeader(WWWAuthenticateHeader.NAME);

    // Authorization header we will build with response to challenge
    AuthorizationHeader ah_r =    headerFactory.createAuthorizationHeader(ah_c.getScheme());

    // assemble data we need to create response string
    URI request_uri = request.getRequestURI();
    String request_method = request.getMethod();
    String nonce  = ah_c.getNonce();
    String algrm  = ah_c.getAlgorithm();
    String realm  = ah_c.getRealm();

    MessageDigest mdigest;
    try {
        mdigest = MessageDigest.getInstance(algrm);

         // A1
        String A1 = username + ":" + realm + ":" + password;
        String HA1 = toHexString(mdigest.digest(A1.getBytes()));

        // A2
        String A2 = request_method.toUpperCase() + ":" + request_uri ;
        String HA2 = toHexString(mdigest.digest(A2.getBytes()));

        // KD
        String KD = HA1 + ":" + nonce + ":" + HA2;
        String responsenew = toHexString(mdigest.digest(KD.getBytes()));

        ah_r.setUsername(username);
        ah_r.setRealm(realm);
        ah_r.setNonce(nonce);
        ah_r.setURI(request_uri);
        ah_r.setAlgorithm(algrm);
        ah_r.setResponse(responsenew);


    } catch (NoSuchAlgorithmException e) {
        // TODO Auto-generated catch block
        e.printStackTrace();
    }
    return ah_r;

}

This is the Request I send and the Response I get.

REGISTER sip:10.99.00.00 SIP/2.0
Via: SIP/2.0/UDP 10.99.00.00:52016;rport;branch=z9hG4bK-   363430-38c329167b2d9108d20c996fec776b29
Max-Forwards: 70
To: <sip:tusername7@10.99.00.00>
From: <sip:username@10.99.00.00>;tag=421569181
Call-ID: 37cd8463e628a6960f62267027cf0720@10.99.00.00
CSeq: 1 REGISTER
Contact: <sip:username@10.99.00.00:52016;transport=UDP>
Content-Length: 0

SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 10.99.00.00:52016;branch=z9hG4bK- 363430-38c329167b2d9108d20c996fec776b29;received=10.99.00.00;rport=52016
From: <sip:username@10.99.00.00>;tag=421569181
To: <sip:username@10.99.00.00>;tag=as64c39fdc
Call-ID: 37cd8463e628a6960f62267027cf0720@10.99.00.00
CSeq: 1 REGISTER
Server: Asterisk PBX 10.5.1
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,REFER,SUBSCRIBE,NOTIFY,INFO,PUBLISH
Supported: replaces,timer
WWW-Authenticate: Digest algorithm=MD5,realm="xyz.com",nonce="13250a39"
Content-Length: 0


REGISTER sip:10.99.00.00 SIP/2.0
Via: SIP/2.0/UDP 10.99.00.00:52016;rport;branch=z9hG4bK-  363430-19fd7f5d12dc78762617b26d61129919
Max-Forwards: 70
To: <sip:username@10.99.00.00>
From: <sip:username@10.99.00.00>;tag=421569181
Call-ID: 68bd42d26ac8f9f90729927434eb5ad3@10.99.70.106
CSeq: 2 REGISTER
Contact: <sip:username@10.99.00.00:52016;transport=UDP>
Authorization: Digest   username="username",realm="xyz.com",nonce="13250a39",uri="sip:10.99.00.00",algorithm=MD5,response="f525cda4442d7388e6ea4a737e46b639"
Content-Length: 0


SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 10.99.00.00:52016;branch=z9hG4bK-     363430-19fd7f5d12dc78762617b26d61129919;received=10.99.00.00;rport=52016
From: <sip:username@10.99.00.00>;tag=421569181
To: <sip:username@10.99.00.00>;tag=as3b3b0796
Call-ID: 68bd42d26ac8f9f90729927434eb5ad3@10.99.00.00
CSeq: 2 REGISTER
Server: Asterisk PBX 10.5.1
Allow: INVITE,ACK,CANCEL,OPTIONS,BYE,REFER,SUBSCRIBE,NOTIFY,INFO,PUBLISH
Supported: replaces,timer
WWW-Authenticate: Digest algorithm=MD5,realm="xyz.com",nonce="22cbe904"
Content-Length: 0

And when I used A SIP application with same credentials I got this request and response

2015-04-22 11:55:42,794 SENT to 10.99.00.00/5060 [AWT-EventQueue-0]

REGISTER sip:10.99.00.00 SIP/2.0
Via: SIP/2.0/UDP 10.99.00.00:52016;rport;branch=z9hG4bKcABnbdE6G
Max-Forwards: 70
To: <sip:username@10.99.00.00>
From: <sip:username@10.99.00.00>;tag=vGbh8M9A
Call-ID: mCbF4794-1429696542758@10.99.00.00
CSeq: 1 REGISTER
Contact: <sip:username@10.99.00.00:52016;transport=UDP>


2015-04-22 11:55:42,795 RECEIVED from 10.99.00.00/5060 [TransportManager 0]

SIP/2.0 401 Unauthorized
Via: SIP/2.0/UDP 10.99.00.00:52016;branch=z9hG4bKcABnbdE6G;    received=10.99.00.00;rport=52016
From: <sip:username@10.99.00.00>;tag=vGbh8M9A
To: <sip:username@10.99.00.00>;tag=as7c9471aa
Call-ID: mCbF4794-1429696542758@10.99.00.00
CSeq: 1 REGISTER
Server: Asterisk PBX 10.5.1
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH
Supported: replaces, timer
WWW-Authenticate: Digest algorithm=MD5, realm="xyz.com",     nonce="7d0754cc"
Content-Length: 0


2015-04-22 11:55:43,637 SENT to 10.99.00.00/5060 [TransportManager 0]

REGISTER sip:10.99.00.00 SIP/2.0
Via: SIP/2.0/UDP 10.99.00.00:52016;rport;branch=z9hG4bK3Oe6XIIh8
Max-Forwards: 70
To: <sip:username@10.99.00.00>
From: <sip:username@10.99.00.00>;tag=vGbh8M9A
Call-ID: mCbF4794-1429696542758@10.99.00.00
CSeq: 2 REGISTER
Contact: <sip:username@10.99.00.00:52016;transport=UDP>
Authorization: Digest username="username", realm="xyz.com", nonce="7d0754cc", uri="sip:10.99.00.00", response="4150b8392729806ff601eb6d67da7c19"


2015-04-22 11:55:43,638 RECEIVED from 10.99.00.00/5060 [TransportManager 0]

OPTIONS sip:username@10.99.00.00:52016;transport=UDP SIP/2.0
Via: SIP/2.0/UDP 10.99.00.00:5060;branch=z9hG4bK21f59b09
Max-Forwards: 70
From: "asterisk" <sip:asterisk@10.99.00.00>;tag=as2093e268
To: <sip:username@10.99.00.00:52016;transport=UDP>
Contact: <sip:asterisk@10.99.00.00:5060>
Call-ID: 77805e3c524799632da223b942a4e8f1@10.99.00.00:5060
CSeq: 102 OPTIONS
User-Agent: Asterisk PBX 10.5.1
Date: Wed, 22 Apr 2015 09:55:43 GMT
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH
Supported: replaces, timer
Content-Length: 0


2015-04-22 11:55:43,660 RECEIVED from 10.99.00.00/5060 [TransportManager 0]

SIP/2.0 200 OK
Via: SIP/2.0/UDP 10.99.00.00:52016;branch=z9hG4bK3Oe6XIIh8;received=10.99.00.00;rport=52016
From: <sip:username@10.99.00.00>;tag=vGbh8M9A
To: <sip:username@10.99.00.00>;tag=as7c9471aa
Call-ID: mCbF4794-1429696542758@10.99.00.00
CSeq: 2 REGISTER
Server: Asterisk PBX 10.5.1
Allow: INVITE, ACK, CANCEL, OPTIONS, BYE, REFER, SUBSCRIBE, NOTIFY, INFO, PUBLISH
Supported: replaces, timer
Expires: 240
Contact: <sip:username@10.99.00.00:52016;transport=UDP>;expires=240
Date: Wed, 22 Apr 2015 09:55:43 GMT
Content-Length: 0

I compared both the packets and didnt find any difference. I dont understand why I am not geeting Authorized. Also the localIP and SIPIP are different in this case.

I think the problem might be with the ports but I didnt find any help on the net for assigning the rport and sipport: 5060. I would also like to get more information on it.

gourig
  • 81
  • 1
  • 11

1 Answers1

1

The call ids on both REGISTERs CSeq 1 and CSeq 2 should be the same. They are different in your case.

Vladimir Ralev
  • 1,371
  • 9
  • 18
  • Hi I fixed the issue but now, I am getting SIP/2.0 482 (Loop Detected) after the second registration request – gourig Apr 22 '15 at 14:07
  • If you are getting Loop Detected then your server doesn't like the same call id. I think your logs got edited too much and now may we can't spot the issue. Can you post original logs working and non-working. The issue is in the 3-rd party's auth requirements, not in jain-sip, so it's hard to tell without having a good sample. It should be something obvious in the logs. I think asterisk will require you to put a proper realm that it itself recognizes, so that's one possible reason. There is something weird in one of the Digest headers. Upload the logs somewhere and it will be easier to tell. – Vladimir Ralev Apr 22 '15 at 15:08
  • It works now! I had used the cseq as 1l as shown in other examples, I changed it back to cseq it worked. – gourig Apr 22 '15 at 15:10
  • Hi I get SIP 200 Ok but after that i get a continuous requestEvent OPTIONS. Is that a problem. Am I supposed to Acknowledge it? – gourig Apr 22 '15 at 16:00
  • Thank you. Can you help me further with this problem http://stackoverflow.com/q/29808060/4819349 – gourig Apr 23 '15 at 00:27