miconda / sipexer

Modern and flexible SIP/VoIP cli tool
GNU General Public License v3.0
293 stars 37 forks source link

Nonce count is always 1 #26

Closed 0oga83 closed 5 months ago

0oga83 commented 5 months ago

With the Belle-sip server (and perhaps others), it seems that a SIP INFO must use the same authentication session as the previous SIP INVITE. Otherwise, the response to SIP INFO is 491. This means that the Authentication digest value must be calculated with the same Nonce value used for INVITE and the Nonce count must be incremented. For the moment, the implementation does not allow passing the Nonce count as a field (-field-val parameter). The value nc=00000001 is hardcoded The only solution I see would be to calculate the entire Proxy-Authorization header before invoking sipexer and pass it with -extra-header (but that's overkill !) It would be great if we could pass the authentication values (Nonce, Nonce count, Opaque, ...) from a previous SIP message when making a new call to sipexer

[EDIT] I'm currently trying to implement this

0oga83 commented 5 months ago

The solution I have implemented is to extract informations from the SIP/INVITE and use them to prepare the Proxy-Authorization passed to the following SIP INFO, using the same Nonce with a Nounce count of 2. Not very elegant but it works. What would be great is to have a feature in sipexec to reuse informations between different commands (CSeq, Routes, CallId, ...). (something similiar to the --cookie-jar with curl)

# SIP INVITE
sipexer -invite ... > invite.tmp
#

# Extract infos from INVITE/ACK
CallID=`cat invite.tmp | tr -d '\0' | grep "Call-ID" | head -n 1 | awk -F ' ' '{print $2}' | tr -d '\"\n\r'`
ruri=`cat invite.tmp | tr -d '\0' | grep "ACK " | tail -n 1 | awk -F ' ' '{print $2}' | sed -r "s/\x1B\[([0-9]{1,2}(;[0-9]{1,2})?)?[m|K]//g"`
fromtag=`cat invite.tmp | tr -d '\0' | grep "From:" | tail -n 1 | awk -F 'tag=' '{print $2}' | tr -d '\n\r'`
totag=`cat invite.tmp | tr -d '\0' | grep "To:" | tail -n 1 | awk -F 'tag=' '{print $2}' | tr -d '\n\r'`
CSeq=$((`cat invite.tmp | tr -d '\0' | grep "CSeq" | tail -n 1 | awk -F ' ' '{print $2}'`+1))
RouteHeaders=`cat invite.tmp | tr -d '\0' | grep "Record-Route" | sort | uniq | awk -F ' ' '{print "Route:"$2}' | head -c -2 | sed -z "s/\nRoute:</\nRoute: </g"`
QOP=`cat invite.tmp | tr -d '\0' | grep "qop=" | tail -n 1 | awk -F 'qop=' '{print $2}' | awk -F ',' '{print $1}' | tr -d '\n\r'` 
Nonce=`cat invite.tmp | tr -d '\0' | grep " nonce=" | tail -n 1 | awk -F 'nonce="' '{print $2}' | awk -F '"' '{print $1}' | tr -d '\n\r'` 
Realm=`cat invite.tmp | tr -d '\0' | grep "realm=" | tail -n 1 | awk -F 'realm="' '{print $2}' | awk -F '"' '{print $1}' | tr -d '\n\r'` 
Opaque=`cat invite.tmp | tr -d '\0' | grep "opaque=" | tail -n 1 | awk -F 'opaque="' '{print $2}' | awk -F '"' '{print $1}' | tr -d '\n\r'`

# Compute auth manually :
AuthMethod="INFO"
AuthUsername="$User"
AuthRealm="sip.mydomain.com"
AuthPassword="$Password"
AuthUri="$ruri"
AuthNonce=`cat invite.tmp | tr -d '\0' | grep "Proxy-Authenticate" | awk -F '"' '{print $4}' | tr -d '\n\r'`
AuthNonceCount="00000002"
AuthCNonce="$RANDOM"
AuthQop="auth"
AuthOpaque=`cat invite.tmp | tr -d '\0' | grep "Proxy-Authenticate" | awk -F '"' '{print $6}' | tr -d '\n\r'`
ha1=`printf "$AuthUsername:$AuthRealm:$AuthPassword" | md5sum | awk '{print $1}'`
ha2=`printf "$AuthMethod:$AuthUri" | md5sum | awk '{print $1}'`
ha3=`printf "$ha1:$AuthNonce:$AuthNonceCount:$AuthCNonce:$AuthQop:$ha2" | md5sum | awk '{print $1}'`

# SIP INFO
sipexer \
    -info \
    -extra-header "$RouteHeaders" \
    -extra-header "Proxy-Authorization:Digest username=\"$AuthUsername\", realm=\"$AuthRealm\", nonce=\"$AuthNonce\", uri=\"$AuthUri\", cnonce=\"$AuthCNonce\", nc=$AuthNonceCount, qop=auth, opaque=\"$AuthOpaque\", algorithm=MD5, response=\"$ha3\"" \
    -field-val "cseqnum:$CSeq" \
    -field-val "callid:$CallID" \
    -field-val "maxforwards:70" \
    -field-val "fromtag:$fromtag" \
    -field-val "totag:$totag" \
    -message-body $'Signal=1\r\nDuration=250\r\n' \
    -ruri "$ruri" \
    -auth-user "$User" \
    -auth-password "$Password" \
    udp:sip.mydomain.com:5060 > info.tmp