Header & Auth Methods

Introduction

The TestSipLuaAgent Lua API library file test_sip_agent.lua provides a method for accessing SIP message headers and constructing header values related to authentication.

Header & Auth Methods

Header Fetch

The header_fetch method fetches a specific header value from a SIP message that is returned by an “expect” API method such as invite_expect_response.

The header_fetch takes the following arguments:

Argument Type Description
headers Object Pass this parameter as request.headers or response.headers from the returned request or response message.
header_name String The name (case-insensitive) of the header to process and return.

The returned value is nil (with a failed match test being generated) if the header is not found.

If the indicated header is found then a single table structure is returned:

Argument Type Description
header Object A returned table containing information about the matched header.
.name String The name as per the first matching header line found.
.value String The complete string value of the first matching header line.
.values Array of String An array of each of the comma-separated parts of the matching header value.
.values_hash Table Each of the comma-separated parts of the first matching header value is examined to see if it has the form of a header parameter i.e. "(key)=(parameter)". Each matching parameter is added as an entry to this table where the key is the upper-case parameter key and the value is the parameter value.

Example: See the below example for auth_header_value.

Auth Header Value

The auth_header_value method implements the algorithm for building a Authorization header based on a received WWWW-Authenticate challenge header.

The method takes the following arguments:

Argument Type Description
context Object An INVITE or non-INVITE context created by invite_context or non_invite_context returned by invite_expect_request.
method String The SIP Request method.
www_auth_header Object The WWW-Authenticate header value returned from header_fetch.
username String The username to place into the authentication.
password String The password to place into the authentication.

Example: INVITE Request is challenged, and authenticated.

local n2svcd = require "n2.n2svcd"
local utils = require "n2.utils"
local match = require "n2.n2svcd.tester.match"
local manage = require "n2.n2svcd.tester.manage"
local edr_file_agent = require "n2.n2svcd.edr_file_agent"
local tsuo = require "n2.n2svcd.tester.test_sip_agent"

local args = ...

-- Switch the authentication mode to DIGEST.  BYE DOES require authentication.
n2svcd.management_configuration_scalar ('LHO', 'sip_auth_schema', 'digest')
n2svcd.management_configuration_scalar ('LHO', 'sip_open_bye', '0')
n2svcd.management_configuration_scalar ('LHO', 'sip_open_ack', '1')

-- Checkpoint stats for "Logic" and "LHO" apps.
local stats_Logic = match.stats ('Logic')
local stats_LHO = match.stats ('LHO')

-- Static for our call.
local endpoints = tsuo.default_endpoints ({ local_rtp_port = 3668 })
local calling_party = '665566'
local called_party = '4000'
local username = '665566'
local password = 'ABC'

-- Get a SIP outcall context from our helper library.
local context = tsuo.invite_context (endpoints, calling_party, called_party, {
    contact_sip_instance = '"<urn:uuid:27b843f9-d300-49fb-b108-fff03a6369e3>"',
    contact_expires = '3600'
})

-- Construct the SDP
local sdp_offer = tsuo.sdp_offer (context, tsuo.SDP_LINPHONE)

-- Start timer for elapsed checking.
local tv = match.elapsed ()

-- Construct and Send INVITE Request.
tsuo.invite_send_request (context, sdp_offer, {
    { name = 'Record-Route', value = '<sip:p2.domain.com;lr>'},
    { name = 'Record-Route', value = '<sip:p1.example.com;lr>'},
})

-- Expect INVITE response (401 Unauthorized) and ACK.
local response = tsuo.invite_expect_response (context, 401, "Unauthorized")
tsuo.invite_send_decline_ack (context)

-- Generate the authorization header for our request.
local www_auth_header = tsuo.header_fetch (response.headers, "WWW-Authenticate")
local authorization_header = tsuo.auth_header_value (context, 'INVITE', www_auth_header, username, password)

-- Re-Send INVITE Request with Authorization.
tsuo.invite_send_request (context, sdp_offer, {
    { name = "Authorization", value = authorization_header },
    { name = 'Record-Route', value = '<sip:p2.domain.com;lr>'},
    { name = 'Record-Route', value = '<sip:p1.example.com;lr>'},
})

-- Expect Trying & Ringing.
tsuo.invite_expect_response (context, 100, "Trying", { ['User-Agent'] = "N-Squared LHO" })
tsuo.invite_expect_response (context, 180, "Ringing", {
    ['Record-Route'] = { '<sip:p2.domain.com;lr>', '<sip:p1.example.com;lr>' }
})
tv = match.elapsed ("Ring Notification (immediate)", tv, 0.0)