Skip to content

Commit

Permalink
Add SHA-256 and SHA-512-256 as authentication digest algorithms
Browse files Browse the repository at this point in the history
* Refactored pjproject code to support the new algorithms and
added a patch file to third-party/pjproject/patches

* Added new parameters to the pjsip auth object:
  * password_digest = <algorithm>:<digest>
  * supported_algorithms_uac = List of algorithms to support
    when acting as a UAC.
  * supported_algorithms_uas = List of algorithms to support
    when acting as a UAS.
  See the auth object in pjsip.conf.sample for detailed info.

* Updated both res_pjsip_authenticator_digest.c (for UAS) and
res_pjsip_outbound_authentocator_digest.c (UAC) to suport the
new algorithms.

The new algorithms are only available with the bundled version
of pjproject, or an external version > 2.14.1.  OpenSSL version
1.1.1 or greater is required to support SHA-512-256.

Resolves: asterisk#948

UserNote: The SHA-256 and SHA-512-256 algorithms are now available
for authentication as both a UAS and a UAC.
  • Loading branch information
gtjoseph committed Nov 5, 2024
1 parent 5782b03 commit 7478bc5
Show file tree
Hide file tree
Showing 16 changed files with 4,240 additions and 545 deletions.
175 changes: 129 additions & 46 deletions configs/samples/pjsip.conf.sample
Original file line number Diff line number Diff line change
Expand Up @@ -1028,52 +1028,122 @@
; "config show help res_pjsip auth realm" or on the wiki for the
; difference.
;
;auth_type=userpass ; Authentication type. May be
; "userpass" for plain text passwords or
; "md5" for pre-hashed credentials.
; (default: "userpass")
;nonce_lifetime=32 ; Lifetime of a nonce associated with this
; authentication config (default: "32")
;md5_cred= ; As an alternative to specifying a plain text password,
; you can hash the username, realm and password
; together one time and place the hash value here.
; The input to the hash function must be in the
; following format:
; <username>:<realm>:<password>
; For incoming authentication (asterisk is the UAS),
; the realm must match either the realm set in this object
; or the default set in in the "global" object.
;
; For outgoing authentication (asterisk is the UAC),
; the realm must match what the server will be sending
; in their WWW-Authenticate header. It can't be blank
; unless you expect the server to be sending a blank
; realm in the header.
; You can generate the hash with the following shell
; command:
; $ echo -n "myname:myrealm:mypassword" | md5sum
; Note the '-n'. You don't want a newline to be part
; of the hash. (default: "")
;password= ; PlainText password used for authentication (default: "")
;realm= ; For incoming authentication (asterisk is the UAS),
; this is the realm to be sent on WWW-Authenticate
; headers. If not specified, the global object's
; "default_realm" will be used.
;
; For outgoing authentication (asterisk is the UAC), this
; must either be the realm the server is expected to send,
; or left blank or contain a single '*' to automatically
; use the realm sent by the server. If you have multiple
; auth objects for an endpoint, the realm is also used to
; match the auth object to the realm the server sent.
;
; Using the same auth section for inbound and outbound
; authentication is not recommended. There is a difference in
; meaning for an empty realm setting between inbound and outbound
; authentication uses.
; (default: "")
;type= ; Must be auth (default: "")
;username= ; Username to use for account (default: "")
;type= ; Must be auth (default: "")

;auth_type= ; Authentication mechanism.
; Must be one of:
; "digest" : The standard HTTP/SIP digest
; authentication. "password" and/or one or more
; "password_digest" parameters must also be specified.
; "google_oauth": Google OAuth authentication used by
; Google Voice.
; "userpass" : (deprecated). Automatically converted
; to "digest". Used to mean plain-text password but
; that is now determined automatically.
; "md5" : (deprecated) Automatically converted
; to "digest". Used to mean pre-hashed password but
; that is now determined automatically.
; (default: "digest")

;realm= ; For incoming authentication (asterisk is the UAS),
; this is the realm to be sent on WWW-Authenticate
; headers. If not specified, the global object's
; "default_realm" will be used.
;
; For outgoing authentication (asterisk is the UAC), this
; must either be the realm the server is expected to send,
; or left blank or contain a single '*' to automatically
; use the realm sent by the server. If you have multiple
; auth objects for an endpoint, the realm is also used to
; match the auth object to the realm the server sent.
;
; Using the same auth section for inbound and outbound
; authentication is not recommended. There is a difference in
; meaning for an empty realm setting between inbound and outbound
; authentication uses.
;
; If more than one auth object with the same realm or
; more than one wildcard auth object is associated to
; an endpoint, only the first one of each defined on
; the endpoint will be used.
;
; (default: "")

;username= ; Username to use for account (default: "")

;password= ; PlainText password used for authentication (default: "")

;password_digest= <digest-spec>[,<digest_spec>]...
; As an alternative to specifying a plain text password, you can
; specify one or more pre-computed digests separated by commas.
;
; <digest-spec> = <hash-algorithm>:<hashed-credential>
; <hash-algorithm>: One of the supported hash algorithms
; which currently are "MD5", "SHA-256" and
; "SHA-512-256". (case-insensitive)
; If you are NOT using the bundled pjproject or a system
; pjproject version > 2.14.1, only "MD5" is supported.
; Also, OpenSSL versions < 1.1.1 do not support "SHA-512-256".
; You can see the current list by running the CLI command
; "pjproject show buildopts".
; <hashed-credential>: The result of passing the following
; string through the selected hash algorithm:
; <username>:<realm>:<password>
; Example:
; $ echo -n "fred:asterisk:mypass" | openssl dgst -md5
; MD5(stdin)= 43a8d9be3da524f9a59ca0593d7b1b5d
; would be specified as...
;password_digest = MD5:43a8d9be3da524f9a59ca0593d7b1b5d
; Ensure you don't accidentally include a trailing '\n'
; in the input to the hash function and see the notes above
; concerning 'realm".
; Also note that the name used by OpenSSL is NOT the official
; IANA name which is required by Asterisk and SIP.
; You may specify multiple password_digest parameters or
; specify multiple digest-specs separated by commas in one
; password_digest entry.

;md5_cred= ; (deprecated) Will be automatically converted to a
; "password_digest" parameter.

;supported_algorithms_uas= <IANA_digest_algorithm>[,<IANA_digest_algorithm>]...
; Specify the digest algorithms to offer when this auth object
; is used by Asterisk acting as a UAS.
; A WWW-Authenticate header will be created for each algorithm
; in the order the algorithms appear here. If a plain text
; password isn't specified in this object, then a
; password_digest parameter must be specified for each
; algorithm. If neither condition is met, validation will fail
; and the object will not load. The default may be specified by the
; "default_auth_algorithms_uas" parameter in the "global"
; object. If that's not specified, the default is "MD5".

;supported_algorithms_uac= <IANA_digest_algorithm>[,<IANA_digest_algorithm>]...
; Specify the digest algorithms to respond with when this auth
; object is used by Asterisk acting as a UAC.
; The algorithm specified in each received
; WWW/Proxy-Authenticate header in a 401/407 response will be
; checked against this list. If the algorithm received doesn't
; appear in the list, that header will be ignored. Order
; doesn't matter as the UAS is supposed to send the headers
; in their preferred order. As with supported_algorithms_uas,
; If a plain text password isn't specified in this object,
; then a password_digest parameter must be specified for each
; algorithm. If neither condition is met, the algorithm
; will automatically be removed from the list. If no
; algorithms remain, the object will fail to load.
; The default may be specified by the
; "default_auth_algorithms_uac" parameter in the "global"
; object. If that's not specified, the default is "MD5".

;nonce_lifetime=32 ; Lifetime of a nonce associated with this
; authentication config (default: "32")

; For the Google OAuth authentication mechanism, the following parameters are
; required:
;refresh_token= ; OAuth 2.0 refresh token
;oauth_clientid= ; OAuth 2.0 application's client id
;oauth_secret= ; OAuth 2.0 application's secret


;==========================DOMAIN_ALIAS SECTION OPTIONS=========================
Expand Down Expand Up @@ -1400,6 +1470,19 @@
; 183 Session Progress to the endpoint.
; (default: "no")

;default_auth_algorithms_uas = MD5
; The default list of digest algorithms to support when an
; auth object is used as a UAS. See the "supported_algorithms_uas"
; parameter in the "auth" object above.
; The default is MD5

;default_auth_algorithms_uac = MD5
; The default list of digest algorithms to support when an
; auth object is used as a UAC. See the "supported_algorithms_uac"
; parameter in the "auth" object above.
; The default is MD5


; MODULE PROVIDING BELOW SECTION(S): res_pjsip_acl
;==========================ACL SECTION OPTIONS=========================
;[acl]
Expand Down
115 changes: 115 additions & 0 deletions configure
Original file line number Diff line number Diff line change
Expand Up @@ -941,6 +941,10 @@ PBX_POPT
POPT_DIR
POPT_INCLUDE
POPT_LIB
PBX_PJSIP_AUTH_NEW_DIGESTS
PJSIP_AUTH_NEW_DIGESTS_DIR
PJSIP_AUTH_NEW_DIGESTS_INCLUDE
PJSIP_AUTH_NEW_DIGESTS_LIB
PBX_PJSIP_TLS_TRANSPORT_RESTART
PJSIP_TLS_TRANSPORT_RESTART_DIR
PJSIP_TLS_TRANSPORT_RESTART_INCLUDE
Expand Down Expand Up @@ -11231,6 +11235,9 @@ printf "%s\n" "#define HAVE_PJPROJECT_ON_VALID_ICE_PAIR_CALLBACK 1" >>confdefs.h
printf "%s\n" "#define HAVE_PJSIP_TLS_TRANSPORT_RESTART 1" >>confdefs.h


printf "%s\n" "#define HAVE_PJSIP_AUTH_NEW_DIGESTS 1" >>confdefs.h





Expand Down Expand Up @@ -13414,6 +13421,18 @@ PBX_PJSIP_TLS_TRANSPORT_RESTART=0




PJSIP_AUTH_NEW_DIGESTS_DESCRIP="PJSIP Auth new digests like SHA-256 and SHA-512-256"
PJSIP_AUTH_NEW_DIGESTS_OPTION=pjsip
PJSIP_AUTH_NEW_DIGESTS_DIR=${PJPROJECT_DIR}

PBX_PJSIP_AUTH_NEW_DIGESTS=0






fi


Expand Down Expand Up @@ -28291,6 +28310,102 @@ _ACEOF
fi



if test "x${PBX_PJSIP_AUTH_NEW_DIGESTS}" != "x1" -a "${USE_PJSIP_AUTH_NEW_DIGESTS}" != "no"; then
pbxlibdir=""
# if --with-PJSIP_AUTH_NEW_DIGESTS=DIR has been specified, use it.
if test "x${PJSIP_AUTH_NEW_DIGESTS_DIR}" != "x"; then
if test -d ${PJSIP_AUTH_NEW_DIGESTS_DIR}/lib; then
pbxlibdir="-L${PJSIP_AUTH_NEW_DIGESTS_DIR}/lib"
else
pbxlibdir="-L${PJSIP_AUTH_NEW_DIGESTS_DIR}"
fi
fi

ast_ext_lib_check_save_CFLAGS="${CFLAGS}"
CFLAGS="${CFLAGS} $PJPROJECT_CFLAGS"
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: checking for pjsip_auth_get_algorithm_by_type in -lpjsip" >&5
printf %s "checking for pjsip_auth_get_algorithm_by_type in -lpjsip... " >&6; }
if test ${ac_cv_lib_pjsip_pjsip_auth_get_algorithm_by_type+y}
then :
printf %s "(cached) " >&6
else $as_nop
ac_check_lib_save_LIBS=$LIBS
LIBS="-lpjsip ${pbxlibdir} $PJPROJECT_LIB $LIBS"
cat confdefs.h - <<_ACEOF >conftest.$ac_ext
/* end confdefs.h. */

/* Override any GCC internal prototype to avoid an error.
Use char because int might match the return type of a GCC
builtin and then its argument prototype would still apply. */
char pjsip_auth_get_algorithm_by_type ();
int
main (void)
{
return pjsip_auth_get_algorithm_by_type ();
;
return 0;
}
_ACEOF
if ac_fn_c_try_link "$LINENO"
then :
ac_cv_lib_pjsip_pjsip_auth_get_algorithm_by_type=yes
else $as_nop
ac_cv_lib_pjsip_pjsip_auth_get_algorithm_by_type=no
fi
rm -f core conftest.err conftest.$ac_objext conftest.beam \
conftest$ac_exeext conftest.$ac_ext
LIBS=$ac_check_lib_save_LIBS
fi
{ printf "%s\n" "$as_me:${as_lineno-$LINENO}: result: $ac_cv_lib_pjsip_pjsip_auth_get_algorithm_by_type" >&5
printf "%s\n" "$ac_cv_lib_pjsip_pjsip_auth_get_algorithm_by_type" >&6; }
if test "x$ac_cv_lib_pjsip_pjsip_auth_get_algorithm_by_type" = xyes
then :
AST_PJSIP_AUTH_NEW_DIGESTS_FOUND=yes
else $as_nop
AST_PJSIP_AUTH_NEW_DIGESTS_FOUND=no
fi

CFLAGS="${ast_ext_lib_check_save_CFLAGS}"


# now check for the header.
if test "${AST_PJSIP_AUTH_NEW_DIGESTS_FOUND}" = "yes"; then
PJSIP_AUTH_NEW_DIGESTS_LIB="${pbxlibdir} -lpjsip $PJPROJECT_LIB"
# if --with-PJSIP_AUTH_NEW_DIGESTS=DIR has been specified, use it.
if test "x${PJSIP_AUTH_NEW_DIGESTS_DIR}" != "x"; then
PJSIP_AUTH_NEW_DIGESTS_INCLUDE="-I${PJSIP_AUTH_NEW_DIGESTS_DIR}/include"
fi
PJSIP_AUTH_NEW_DIGESTS_INCLUDE="${PJSIP_AUTH_NEW_DIGESTS_INCLUDE} $PJPROJECT_CFLAGS"

# check for the header
ast_ext_lib_check_saved_CPPFLAGS="${CPPFLAGS}"
CPPFLAGS="${CPPFLAGS} ${PJSIP_AUTH_NEW_DIGESTS_INCLUDE}"
ac_fn_c_check_header_compile "$LINENO" "pjsip.h" "ac_cv_header_pjsip_h" "$ac_includes_default"
if test "x$ac_cv_header_pjsip_h" = xyes
then :
PJSIP_AUTH_NEW_DIGESTS_HEADER_FOUND=1
else $as_nop
PJSIP_AUTH_NEW_DIGESTS_HEADER_FOUND=0
fi

CPPFLAGS="${ast_ext_lib_check_saved_CPPFLAGS}"

if test "x${PJSIP_AUTH_NEW_DIGESTS_HEADER_FOUND}" = "x0" ; then
PJSIP_AUTH_NEW_DIGESTS_LIB=""
PJSIP_AUTH_NEW_DIGESTS_INCLUDE=""
else

PBX_PJSIP_AUTH_NEW_DIGESTS=1
cat >>confdefs.h <<_ACEOF
#define HAVE_PJSIP_AUTH_NEW_DIGESTS 1
_ACEOF

fi
fi
fi


fi
fi

Expand Down
2 changes: 2 additions & 0 deletions configure.ac
Original file line number Diff line number Diff line change
Expand Up @@ -601,6 +601,7 @@ AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_ENDPOINT_COMPACT_FORM], [PJSIP Compact Form Su
AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_TRANSPORT_DISABLE_CONNECTION_REUSE], [PJSIP Transport Connection Reuse Disabling], [PJPROJECT], [pjsip])
AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_OAUTH_AUTHENTICATION], [PJSIP OAuth Authentication Support], [PJPROJECT], [pjsip])
AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_TLS_TRANSPORT_RESTART], [PJSIP TLS Transport Restart Support], [PJPROJECT], [pjsip])
AST_EXT_LIB_SETUP_OPTIONAL([PJSIP_AUTH_NEW_DIGESTS], [PJSIP Auth new digests like SHA-256 and SHA-512-256], [PJPROJECT], [pjsip])
fi

AST_EXT_LIB_SETUP([POPT], [popt], [popt])
Expand Down Expand Up @@ -2527,6 +2528,7 @@ if test "$USE_PJPROJECT" != "no" ; then
AST_EXT_LIB_CHECK([PJSIP_AUTH_CLT_DEINIT], [pjsip], [pjsip_auth_clt_deinit], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
AST_EXT_LIB_CHECK([PJSIP_TSX_LAYER_FIND_TSX2], [pjsip], [pjsip_tsx_layer_find_tsx2], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
AST_EXT_LIB_CHECK([PJSIP_TLS_TRANSPORT_RESTART], [pjsip], [pjsip_tls_transport_restart], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
AST_EXT_LIB_CHECK([PJSIP_AUTH_NEW_DIGESTS], [pjsip], [pjsip_auth_get_algorithm_by_type], [pjsip.h], [$PJPROJECT_LIB], [$PJPROJECT_CFLAGS])
fi
fi

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,31 @@
"""Add fields to ps_auths to support new algorithms
Revision ID: abdc9ede147d
Revises: 801b9fced8b7
Create Date: 2024-10-27 15:26:25.165085
"""

# revision identifiers, used by Alembic.
revision = 'abdc9ede147d'
down_revision = '801b9fced8b7'

from alembic import op
import sqlalchemy as sa

max_value_length = 1024

def upgrade():
op.add_column('ps_auths', sa.Column('password_digest', sa.String(max_value_length)))
op.add_column('ps_auths', sa.Column('supported_algorithms_uas', sa.String(max_value_length)))
op.add_column('ps_auths', sa.Column('supported_algorithms_uac', sa.String(max_value_length)))
op.add_column('ps_globals', sa.Column('default_auth_algorithms_uas', sa.String(max_value_length)))
op.add_column('ps_globals', sa.Column('default_auth_algorithms_uac', sa.String(max_value_length)))


def downgrade():
op.drop_column('ps_auths', 'password_digest')
op.drop_column('ps_auths', 'supported_algorithms_uas')
op.drop_column('ps_auths', 'supported_algorithms_uac')
op.drop_column('ps_globals', 'default_auth_algorithms_uas')
op.drop_column('ps_globals', 'default_auth_algorithms_uac')
4 changes: 4 additions & 0 deletions include/asterisk/autoconfig.h.in
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,10 @@
/* Define to 1 if PJPROJECT has the pjsip_auth_clt_deinit support feature. */
#undef HAVE_PJSIP_AUTH_CLT_DEINIT

/* Define to 1 if PJPROJECT has the PJSIP Auth new digests like SHA-256 and
SHA-512-256 feature. */
#undef HAVE_PJSIP_AUTH_NEW_DIGESTS

/* Define to 1 if PJPROJECT has the PJSIP Dialog Create UAS with Incremented
Lock feature. */
#undef HAVE_PJSIP_DLG_CREATE_UAS_AND_INC_LOCK
Expand Down
Loading

0 comments on commit 7478bc5

Please sign in to comment.