mirror of
https://github.com/coturn/coturn.git
synced 2025-10-24 04:20:59 +02:00
commit
eacb77740b
@ -4,6 +4,7 @@ Version 4.5.0.5 'dan Eider':
|
||||
- LibreSSL compatibility fixed.
|
||||
- "read_timeout" option support for MySQL.
|
||||
- new NAT behavior discovery utilty.
|
||||
- new OAuth access_token encrypt/decrypt utilty.
|
||||
|
||||
08/20/2016 Oleg Moskalenko <mom040267@gmail.com>
|
||||
Version 4.5.0.4 'dan Eider':
|
||||
|
||||
@ -34,7 +34,7 @@ SERVERAPP_HEADERS = src/apps/relay/userdb.h src/apps/relay/tls_listener.h src/ap
|
||||
SERVERAPP_MODS = src/apps/relay/mainrelay.c src/apps/relay/netengine.c src/apps/relay/libtelnet.c src/apps/relay/turn_admin_server.c src/apps/relay/userdb.c src/apps/relay/tls_listener.c src/apps/relay/dtls_listener.c ${HIREDIS_MODS} ${USERDB_MODS}
|
||||
SERVERAPP_DEPS = ${SERVERTURN_MODS} ${SERVERTURN_DEPS} ${SERVERAPP_MODS} ${SERVERAPP_HEADERS} ${COMMON_DEPS} ${IMPL_DEPS} lib/libturnclient.a
|
||||
|
||||
TURN_BUILD_RESULTS = bin/turnutils_natdiscovery bin/turnutils_stunclient bin/turnutils_rfc5769check bin/turnutils_uclient bin/turnserver bin/turnutils_peer lib/libturnclient.a include/turn/ns_turn_defs.h sqlite_empty_db
|
||||
TURN_BUILD_RESULTS = bin/turnutils_oauth bin/turnutils_natdiscovery bin/turnutils_stunclient bin/turnutils_rfc5769check bin/turnutils_uclient bin/turnserver bin/turnutils_peer lib/libturnclient.a include/turn/ns_turn_defs.h sqlite_empty_db
|
||||
|
||||
all: ${TURN_BUILD_RESULTS}
|
||||
|
||||
@ -59,6 +59,11 @@ bin/turnutils_natdiscovery: ${COMMON_DEPS} lib/libturnclient.a src/apps/natdisco
|
||||
${MKBUILDDIR} bin
|
||||
${CC} ${CPPFLAGS} ${CFLAGS} src/apps/natdiscovery/natdiscovery.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS}
|
||||
|
||||
bin/turnutils_oauth: ${COMMON_DEPS} lib/libturnclient.a src/apps/oauth/oauth.c
|
||||
pwd
|
||||
${MKBUILDDIR} bin
|
||||
${CC} ${CPPFLAGS} ${CFLAGS} src/apps/oauth/oauth.c ${COMMON_MODS} -o $@ -Llib -lturnclient -Llib ${LDFLAGS}
|
||||
|
||||
bin/turnutils_stunclient: ${COMMON_DEPS} lib/libturnclient.a src/apps/stunclient/stunclient.c
|
||||
pwd
|
||||
${MKBUILDDIR} bin
|
||||
|
||||
@ -37,6 +37,17 @@ according RFC5780. This utility discovers the actual NAT Mapping and Filtering
|
||||
behavior. Be aweare that at least two different listening IP addresses should
|
||||
be configured to be able to work properly!
|
||||
|
||||
6. turnutils_oauth: a utility that provides OAuth access_token
|
||||
generation(AEAD encryption), validation and decryption. This utility inputs
|
||||
all the keys and lifetimes and any related informations that needed for
|
||||
creation and validationi of an access_token. It outputs a JSON with all OAuth
|
||||
PoP parameters that need to pass to the client. Output is generated accoriding
|
||||
RFC7635 Appendix B, Figure 8.
|
||||
|
||||
For more details, and for the access_token structure, read rfc7635, and see
|
||||
script in examples/scripts/oauth.sh.
|
||||
|
||||
|
||||
=====================================
|
||||
|
||||
NAME
|
||||
@ -271,6 +282,74 @@ Usage:
|
||||
|
||||
$ turnutils_natdiscovery -m -f stun.example.com
|
||||
|
||||
=====================================
|
||||
|
||||
NAME
|
||||
|
||||
turnutils_oauth - a utility that helps OAuth access_token generation/encryption and validation/decyption
|
||||
|
||||
SYNOPSIS
|
||||
|
||||
$ turnutils_oauth [options]
|
||||
|
||||
DESCRIPTION
|
||||
|
||||
turnutils_oauth utilitiy provides help in OAuth access_token encryption and/or
|
||||
decryption with AEAD (Atuthenticated Encryption with Associated Data). It helps
|
||||
for an Auth Server in access_token creation, and also for debuging purposes it
|
||||
helps the access_token validation and decryption. This utility inputs all the
|
||||
keys and lifetimes and any related informations that are needed for encryption
|
||||
or decryption of an access_token. It outputs a JSON with all OAuth PoP
|
||||
parameters that need to pass to the client. Output is generated accoriding
|
||||
RFC7635 Appendix B, Figure 8. This utility could help to build an Auth Server
|
||||
service, but be awere that this utility does not generate "session key" /
|
||||
"mac_key" and not verifies lifetime of "session key" / "mac_key" or "Auth key".
|
||||
For more details, and for the access_token structure, read rfc7635, and see
|
||||
the example in examples/scripts/oauth.sh.
|
||||
|
||||
Use either -e and/or -d flag to encrypt or decrypt access_token.
|
||||
|
||||
Flags:
|
||||
|
||||
-h, --help usage
|
||||
|
||||
-v, --verbose verbose mode
|
||||
|
||||
-e, --encrypt encrypt token
|
||||
|
||||
-d, --decrypt decrypt validate token
|
||||
|
||||
Options with required values:
|
||||
|
||||
-i, --server-name server name (max. 255 char)
|
||||
|
||||
-j, --auth-key-id Auth key id (max. 32 char)
|
||||
|
||||
-k, --auth-key base64 encoded Auth key
|
||||
|
||||
-l --auth-key-timestamp Auth key timestamp (sec since epoch)
|
||||
|
||||
-m, --auth-key-lifetime Auth key lifetime in sec
|
||||
|
||||
-n, --auth-key-as-rs-alg Authorization Server(AS) - Resource Server(RS) encryption algorithm
|
||||
|
||||
-o, --token-nonce base64 encoded nonce base64(12 octet) = 16 char
|
||||
|
||||
-p, --token-mac-key base64 encoded MAC key base64(32 octet) = 44 char
|
||||
|
||||
-q, --token-timestamp timestamp in format 64 bit unsigned (Native format - Unix),
|
||||
so 48 bit for secs since epoch UTC + 16 bit for 1/64000 fractions of a second.
|
||||
e.g.: the actual unixtimestamp 16 bit left shifted. (Default: actual gmtime)
|
||||
-r, --token-lifetime lifetime in sec (Default: 3600)
|
||||
|
||||
-t, --token base64 encoded encrypted token for validation and decryption
|
||||
|
||||
-u, --hmac-alg stun client hmac algorithm
|
||||
|
||||
Usage:
|
||||
|
||||
$ turnutils_natdiscovery
|
||||
|
||||
===================================
|
||||
|
||||
DOCS
|
||||
|
||||
17
examples/scripts/oauth.sh
Executable file
17
examples/scripts/oauth.sh
Executable file
@ -0,0 +1,17 @@
|
||||
#!/bin/bash
|
||||
|
||||
OAUTH_UTILITY=bin/turnutils_oauth
|
||||
|
||||
echo "--------------create an access_token---------------"
|
||||
$OAUTH_UTILITY -e --server-name example.com --auth-key-id 1234 --auth-key SEdrajMyS0pHaXV5MDk4c2RmYXFiTmpPaWF6NzE5MjM= --auth-key-timestamp 249213600 --auth-key-lifetime 21600 --token-mac-key WmtzanB3ZW9peFhtdm42NzUzNG0= --token-timestamp 16333642137600 --token-lifetime=3600
|
||||
|
||||
echo "---------------create and validate and print out the decoded access_token---------------"
|
||||
$OAUTH_UTILITY -v -d -e --server-name example.com --auth-key-id 1234 --auth-key SEdrajMyS0pHaXV5MDk4c2RmYXFiTmpPaWF6NzE5MjM= --auth-key-timestamp 249213600 --auth-key-lifetime 21600 --token-mac-key WmtzanB3ZW9peFhtdm42NzUzNG0= --token-timestamp 16333642137600 --token-lifetime=3600
|
||||
|
||||
echo -e "\n---------------just validate only the access_token---------------"
|
||||
$OAUTH_UTILITY -d --server-name example.com --auth-key-id 1234 --auth-key SEdrajMyS0pHaXV5MDk4c2RmYXFiTmpPaWF6NzE5MjM= --auth-key-timestamp 249213600 --auth-key-lifetime 21600 --token AAy1JBYVLo16iq9gFdHyyknmx5T/Lq9YlbxgUdLcStOFS0H8xhHceHOL2f49qxp4uBpGuuLeLqk+RcAa5uP2EQ== --token-lifetime=3600
|
||||
|
||||
echo -e "\n---------------validate and print out the decoded access_token---------------"
|
||||
$OAUTH_UTILITY -v -d --server-name example.com --auth-key-id 1234 --auth-key SEdrajMyS0pHaXV5MDk4c2RmYXFiTmpPaWF6NzE5MjM= --auth-key-timestamp 249213600 --auth-key-lifetime 21600 --token AAy1JBYVLo16iq9gFdHyyknmx5T/Lq9YlbxgUdLcStOFS0H8xhHceHOL2f49qxp4uBpGuuLeLqk+RcAa5uP2EQ== --token-lifetime=3600
|
||||
|
||||
|
||||
@ -2,15 +2,16 @@
|
||||
|
||||
rm -rf man/man1/*
|
||||
|
||||
txt2man -s 1 -t TURN -I turnserver -I turnadmin -I turnutils -I turnutils_uclient -I turnutils_stunclient -I turnutils_rfc5769check -I turnutils_peer -I turnutils_natdiscovery -B "TURN Server" README.turnserver | sed -e 's/-/\\-/g' > man/man1/turnserver.1
|
||||
txt2man -s 1 -t TURN -I turnserver -I turnadmin -I turnutils -I turnutils_uclient -I turnutils_stunclient -I turnutils_rfc5769check -I turnutils_peer -I turnutils_natdiscovery -I turnutils_oauth -B "TURN Server" README.turnserver | sed -e 's/-/\\-/g' > man/man1/turnserver.1
|
||||
|
||||
txt2man -s 1 -t TURN -I turnserver -I turnadmin -I turnutils -I turnutils_uclient -I turnutils_stunclient -I turnutils_rfc5769check -I turnutils_peer -I turnutils_natdiscovery -B "TURN Server" README.turnadmin | sed -e 's/-/\\-/g'> man/man1/turnadmin.1
|
||||
txt2man -s 1 -t TURN -I turnserver -I turnadmin -I turnutils -I turnutils_uclient -I turnutils_stunclient -I turnutils_rfc5769check -I turnutils_peer -I turnutils_natdiscovery -I turnutils_oauth -B "TURN Server" README.turnadmin | sed -e 's/-/\\-/g'> man/man1/turnadmin.1
|
||||
|
||||
txt2man -s 1 -t TURN -I turnserver -I turnadmin -I turnutils -I turnutils_uclient -I turnutils_stunclient -I turnutils_rfc5769check -I turnutils_peer -I turnutils_natdiscovery -B "TURN Server" README.turnutils | sed -e 's/-/\\-/g' > man/man1/turnutils.1
|
||||
txt2man -s 1 -t TURN -I turnserver -I turnadmin -I turnutils -I turnutils_uclient -I turnutils_stunclient -I turnutils_rfc5769check -I turnutils_peer -I turnutils_natdiscovery -I turnutils_oauth -B "TURN Server" README.turnutils | sed -e 's/-/\\-/g' > man/man1/turnutils.1
|
||||
|
||||
cd man/man1; ln -s turnutils.1 turnutils_uclient.1;cd ../..
|
||||
cd man/man1; ln -s turnutils.1 turnutils_peer.1;cd ../..
|
||||
cd man/man1; ln -s turnutils.1 turnutils_stunclient.1;cd ../..
|
||||
cd man/man1; ln -s turnutils.1 turnutils_natdiscovery.1;cd ../..
|
||||
cd man/man1; ln -s turnutils.1 turnutils_oauth.1;cd ../..
|
||||
cd man/man1; ln -s turnserver.1 coturn.1;cd ../..
|
||||
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
.\" Text automatically generated by txt2man
|
||||
.TH TURN 1 "04 September 2016" "" ""
|
||||
.TH TURN 1 "07 September 2016" "" ""
|
||||
.SH GENERAL INFORMATION
|
||||
|
||||
\fIturnadmin\fP is a TURN administration tool. This tool can be used to manage
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
.\" Text automatically generated by txt2man
|
||||
.TH TURN 1 "04 September 2016" "" ""
|
||||
.TH TURN 1 "07 September 2016" "" ""
|
||||
.SH GENERAL INFORMATION
|
||||
|
||||
The \fBTURN Server\fP project contains the source code of a TURN server and TURN client
|
||||
|
||||
@ -1,5 +1,5 @@
|
||||
.\" Text automatically generated by txt2man
|
||||
.TH TURN 1 "04 September 2016" "" ""
|
||||
.TH TURN 1 "07 September 2016" "" ""
|
||||
.SH GENERAL INFORMATION
|
||||
|
||||
A set of turnutils_* programs provides some utility functionality to be used
|
||||
@ -48,7 +48,22 @@ $ ./scripts/secure_relay.sh
|
||||
according RFC5780. This utility discovers the actual NAT Mapping and Filtering
|
||||
behavior. Be aweare that at least two different listening IP addresses should
|
||||
be configured to be able to work properly!
|
||||
.TP
|
||||
.B
|
||||
6.
|
||||
\fIturnutils_oauth\fP: a utility that provides OAuth access_token
|
||||
\fBgeneration\fP(AEAD encryption), validation and decryption. This utility inputs
|
||||
all the keys and lifetimes and any related informations that needed for
|
||||
creation and validationi of an access_token. It outputs a JSON with all OAuth
|
||||
PoP parameters that need to pass to the client. Output is generated accoriding
|
||||
RFC7635 Appendix B, Figure 8.
|
||||
.PP
|
||||
For more details, and for the access_token structure, read rfc7635, and see
|
||||
script in examples/scripts/oauth.sh.
|
||||
.RE
|
||||
.PP
|
||||
|
||||
.RS
|
||||
=====================================
|
||||
.SS NAME
|
||||
\fB
|
||||
@ -414,6 +429,112 @@ Usage:
|
||||
.PP
|
||||
$ \fIturnutils_natdiscovery\fP \fB\-m\fP \fB\-f\fP stun.example.com
|
||||
.PP
|
||||
=====================================
|
||||
.SS NAME
|
||||
\fB
|
||||
\fBturnutils_oauth \fP\- a utility that helps OAuth access_token generation/encryption and validation/decyption
|
||||
\fB
|
||||
.SS SYNOPSIS
|
||||
.nf
|
||||
.fam C
|
||||
|
||||
$ \fIturnutils_oauth\fP [\fIoptions\fP]
|
||||
|
||||
.fam T
|
||||
.fi
|
||||
.fam T
|
||||
.fi
|
||||
.SS DESCRIPTION
|
||||
|
||||
\fIturnutils_oauth\fP utilitiy provides help in OAuth access_token encryption and/or
|
||||
decryption with AEAD (Atuthenticated Encryption with Associated Data). It helps
|
||||
for an Auth Server in access_token creation, and also for debuging purposes it
|
||||
helps the access_token validation and decryption. This utility inputs all the
|
||||
keys and lifetimes and any related informations that are needed for encryption
|
||||
or decryption of an access_token. It outputs a JSON with all OAuth PoP
|
||||
parameters that need to pass to the client. Output is generated accoriding
|
||||
RFC7635 Appendix B, Figure 8. This utility could help to build an Auth Server
|
||||
service, but be awere that this utility does not generate "session key" /
|
||||
"mac_key" and not verifies lifetime of "session key" / "mac_key" or "Auth key".
|
||||
For more details, and for the access_token structure, read rfc7635, and see
|
||||
the example in examples/scripts/oauth.sh.
|
||||
.PP
|
||||
Use either \fB\-e\fP and/or \fB\-d\fP flag to encrypt or decrypt access_token.
|
||||
.PP
|
||||
Flags:
|
||||
.TP
|
||||
.B
|
||||
\fB\-h\fP, \fB\-\-help\fP
|
||||
usage
|
||||
.TP
|
||||
.B
|
||||
\fB\-v\fP, \fB\-\-verbose\fP
|
||||
verbose mode
|
||||
.TP
|
||||
.B
|
||||
\fB\-e\fP, \fB\-\-encrypt\fP
|
||||
encrypt token
|
||||
.TP
|
||||
.B
|
||||
\fB\-d\fP, \fB\-\-decrypt\fP
|
||||
decrypt validate token
|
||||
.PP
|
||||
Options with required values:
|
||||
.TP
|
||||
.B
|
||||
\fB\-i\fP, \fB\-\-server\-name\fP
|
||||
server name (max. 255 char)
|
||||
.TP
|
||||
.B
|
||||
\fB\-j\fP, \fB\-\-auth\-key\-id\fP
|
||||
Auth key id (max. 32 char)
|
||||
.TP
|
||||
.B
|
||||
\fB\-k\fP, \fB\-\-auth\-key\fP
|
||||
base64 encoded Auth key
|
||||
.TP
|
||||
.B
|
||||
\fB\-l\fP
|
||||
\fB\-\-auth\-key\-timestamp\fP Auth key timestamp (sec since epoch)
|
||||
.TP
|
||||
.B
|
||||
\fB\-m\fP, \fB\-\-auth\-key\-lifetime\fP
|
||||
Auth key lifetime in sec
|
||||
.TP
|
||||
.B
|
||||
\fB\-n\fP, \fB\-\-auth\-key\-as\-rs\-alg\fP
|
||||
Authorization \fBServer\fP(AS) \- Resource \fBServer\fP(RS) encryption algorithm
|
||||
.TP
|
||||
.B
|
||||
\fB\-o\fP, \fB\-\-token\-nonce\fP
|
||||
base64 encoded nonce \fBbase64\fP(12 octet) = 16 char
|
||||
.TP
|
||||
.B
|
||||
\fB\-p\fP, \fB\-\-token\-mac\-key\fP
|
||||
base64 encoded MAC key \fBbase64\fP(32 octet) = 44 char
|
||||
.TP
|
||||
.B
|
||||
\fB\-q\fP, \fB\-\-token\-timestamp\fP
|
||||
timestamp in format 64 bit unsigned (Native format \- Unix),
|
||||
so 48 bit for secs since epoch UTC + 16 bit for 1/64000 fractions of a second.
|
||||
e.g.: the actual unixtimestamp 16 bit left shifted. (Default: actual gmtime)
|
||||
.TP
|
||||
.B
|
||||
\fB\-r\fP, \fB\-\-token\-lifetime\fP
|
||||
lifetime in sec (Default: 3600)
|
||||
.TP
|
||||
.B
|
||||
\fB\-t\fP, \fB\-\-token\fP
|
||||
base64 encoded encrypted token for validation and decryption
|
||||
.TP
|
||||
.B
|
||||
\fB\-u\fP, \fB\-\-hmac\-alg\fP
|
||||
stun client hmac algorithm
|
||||
.PP
|
||||
Usage:
|
||||
.PP
|
||||
$ \fIturnutils_natdiscovery\fP
|
||||
.PP
|
||||
===================================
|
||||
.SH DOCS
|
||||
|
||||
|
||||
1
man/man1/turnutils_oauth.1
Symbolic link
1
man/man1/turnutils_oauth.1
Symbolic link
@ -0,0 +1 @@
|
||||
turnutils.1
|
||||
482
src/apps/oauth/oauth.c
Normal file
482
src/apps/oauth/oauth.c
Normal file
@ -0,0 +1,482 @@
|
||||
/*
|
||||
* Copyright (C) 2011, 2012, 2013 Citrix Systems
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions
|
||||
* are met:
|
||||
* 1. Redistributions of source code must retain the above copyright
|
||||
* notice, this list of conditions and the following disclaimer.
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
* 3. Neither the name of the project nor the names of its contributors
|
||||
* may be used to endorse or promote products derived from this software
|
||||
* without specific prior written permission.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED BY THE PROJECT AND CONTRIBUTORS ``AS IS'' AND
|
||||
* ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
|
||||
* IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
|
||||
* ARE DISCLAIMED. IN NO EVENT SHALL THE PROJECT OR CONTRIBUTORS BE LIABLE
|
||||
* FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
|
||||
* DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
|
||||
* OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
|
||||
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
|
||||
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
|
||||
* OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
|
||||
* SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
#include <err.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <time.h>
|
||||
#include <unistd.h>
|
||||
#include <getopt.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include "ns_turn_utils.h"
|
||||
#include "apputils.h"
|
||||
#include "stun_buffer.h"
|
||||
|
||||
////////////////////////////////////////////////////
|
||||
|
||||
#define OAUTH_TOKEN_SIZE 1000 //TODO: find insted of 1000 the real max of encoded token length
|
||||
#define OAUTH_MAC_KEY_SIZE 32
|
||||
#define OAUTH_LTK_ID_SIZE 32
|
||||
#define OAUTH_LTK_SIZE 32
|
||||
#define OAUTH_LTK_BASE64ENCODED_SIZE 44
|
||||
#define OAUTH_TOKEN_LIFETIME 3600
|
||||
#define OAUTH_AS_RS_ALG_SIZE 7
|
||||
#define OAUTH_SERVER_NAME_SIZE 255
|
||||
#define OAUTH_GCM_NONCE_BASE64ENCODED_SIZE 16
|
||||
#define OAUTH_HMAC_ALG_SIZE 20
|
||||
|
||||
|
||||
static int setup_ikm_key(const char *kid,
|
||||
const char *ikm_key,
|
||||
const turn_time_t key_timestamp,
|
||||
const turn_time_t key_lifetime,
|
||||
const char *as_rs_alg,
|
||||
oauth_key *key) {
|
||||
|
||||
ns_bzero(key,sizeof(*key));
|
||||
|
||||
oauth_key_data okd;
|
||||
ns_bzero(&okd,sizeof(okd));
|
||||
|
||||
{
|
||||
oauth_key_data_raw okdr;
|
||||
ns_bzero(&okdr,sizeof(okdr));
|
||||
|
||||
STRCPY(okdr.kid,kid);
|
||||
STRCPY(okdr.ikm_key,ikm_key);
|
||||
STRCPY(okdr.as_rs_alg,as_rs_alg);
|
||||
okdr.timestamp = key_timestamp;
|
||||
okdr.lifetime = key_lifetime;
|
||||
|
||||
convert_oauth_key_data_raw(&okdr, &okd);
|
||||
}
|
||||
|
||||
char err_msg[1025] = "\0";
|
||||
size_t err_msg_size = sizeof(err_msg) - 1;
|
||||
|
||||
if (convert_oauth_key_data(&okd, key, err_msg, err_msg_size) < 0) {
|
||||
fprintf(stderr, "%s\n", err_msg);
|
||||
return -1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
|
||||
static int encode_token(const char* server_name,
|
||||
const char* gcm_nonce,
|
||||
const char* mac_key,
|
||||
const uint64_t token_timestamp,
|
||||
const uint32_t token_lifetime,
|
||||
const oauth_key key,
|
||||
char* base64encoded_etoken) {
|
||||
|
||||
|
||||
oauth_token ot;
|
||||
ns_bzero(&ot,sizeof(ot));
|
||||
|
||||
const size_t mac_key_length=strlen(mac_key);
|
||||
ot.enc_block.key_length = (uint16_t)mac_key_length;
|
||||
STRCPY(ot.enc_block.mac_key,mac_key);
|
||||
ot.enc_block.timestamp = token_timestamp;
|
||||
ot.enc_block.lifetime = token_lifetime;
|
||||
|
||||
encoded_oauth_token etoken;
|
||||
ns_bzero(&etoken,sizeof(etoken));
|
||||
|
||||
// TODO: avoid this hack
|
||||
if (!*gcm_nonce) gcm_nonce='\0';
|
||||
|
||||
if (encode_oauth_token((const u08bits *) server_name, &etoken, &key, &ot,(const u08bits *) gcm_nonce) < 0) {
|
||||
fprintf(stderr, "%s: cannot encode oauth token\n",
|
||||
__FUNCTION__);
|
||||
return -1;
|
||||
}
|
||||
|
||||
size_t base64encoded_etoken_length;
|
||||
const char *tmp=base64_encode((unsigned char *)(etoken.token), etoken.size, &base64encoded_etoken_length);
|
||||
STRCPY(base64encoded_etoken,tmp);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int validate_decode_token(const char* server_name,
|
||||
const oauth_key key,
|
||||
const char* base64encoded_etoken, oauth_token* dot) {
|
||||
|
||||
|
||||
ns_bzero((dot),sizeof(*dot));
|
||||
|
||||
encoded_oauth_token etoken;
|
||||
ns_bzero(&etoken,sizeof(etoken));
|
||||
|
||||
const size_t base64encoded_etoken_length=strlen(base64encoded_etoken);
|
||||
const unsigned char *tmp = base64_decode(base64encoded_etoken,base64encoded_etoken_length,&etoken.size);
|
||||
memcpy(etoken.token,tmp,etoken.size);
|
||||
|
||||
if (decode_oauth_token((const u08bits *) server_name, &etoken, &key, dot) < 0) {
|
||||
fprintf(stderr, "%s: cannot decode oauth token\n",
|
||||
__FUNCTION__);
|
||||
return -1;
|
||||
} else {
|
||||
return 0;
|
||||
};
|
||||
}
|
||||
|
||||
static void print_token_body(oauth_token* dot) {
|
||||
printf("\n");
|
||||
printf("Token non-encrpyted body:\n");
|
||||
printf("{\n");
|
||||
size_t base64encoded_nonce_length;
|
||||
const char *base64encoded_nonce = base64_encode((unsigned char *)dot->enc_block.nonce, dot->enc_block.nonce_length,&base64encoded_nonce_length);
|
||||
printf(" nonce: %s\n", base64encoded_nonce);
|
||||
printf(" nonce length: %d\n", (int) dot->enc_block.nonce_length);
|
||||
printf("Token encrpyted body:\n");
|
||||
printf("{\n");
|
||||
printf(" mac key: %s\n", (char*) dot->enc_block.mac_key);
|
||||
printf(" mac key length: %d\n", (int) dot->enc_block.key_length);
|
||||
time_t time=dot->enc_block.timestamp>>16;
|
||||
unsigned msec=(dot->enc_block.timestamp & 0xFFFF)*64;
|
||||
printf(" timestamp:\n");
|
||||
printf(" unixtime: %u (localtime: %s )", (unsigned int)time, ctime(&time));
|
||||
printf(" msec:%u\n", msec);
|
||||
printf(" lifetime: %lu\n", (unsigned long) dot->enc_block.lifetime);
|
||||
printf("}\n");
|
||||
}
|
||||
|
||||
//////////////// local definitions /////////////////
|
||||
|
||||
const char Usage[] =
|
||||
"Usage: oauth [ -e / -d ] [options]\n"
|
||||
"Options:\n"
|
||||
"\n"
|
||||
" -h, --help usage\n\n"
|
||||
" -v, --verbose verbose mode\n\n"
|
||||
" -e, --encrypt encrypt token\n"
|
||||
" -d, --decrypt decrypt validate token\n\n"
|
||||
" -i, --server-name server name (max. 255 char)\n"
|
||||
" -j, --auth-key-id Auth key id (max. 32 char)\n"
|
||||
" -k, --auth-key base64 encoded Auth key\n"
|
||||
" -l --auth-key-timestamp Auth key timestamp (sec since epoch)\n"
|
||||
" -m, --auth-key-lifetime Auth key lifetime in sec\n"
|
||||
" -n, --auth-key-as-rs-alg Authorization Server(AS) - Resource Server (RS) encryption algorithm\n"
|
||||
" -o, --token-nonce base64 encoded nonce base64(12 octet) = 16 char\n"
|
||||
" -p, --token-mac-key base64 encoded MAC key base64(32 octet) = 44 char\n"
|
||||
" -q, --token-timestamp timestamp in format 64 bit unsigned (Native format - Unix),\n"
|
||||
" so 48 bit for secs since epoch UTC + 16 bit for 1/64000 fractions of a second.\n"
|
||||
" e.g.: the actual unixtimestamp 16 bit left shifted. (Default: actual gmtime)\n"
|
||||
" -r, --token-lifetime lifetime in sec (Default: 3600)\n"
|
||||
" -t, --token base64 encoded encrypted token for validation and decryption\n"
|
||||
" -u, --hmac-alg stun client hmac algorithm\n";
|
||||
|
||||
//////////////////////////////////////////////////
|
||||
|
||||
|
||||
int main(int argc, char **argv)
|
||||
{
|
||||
|
||||
oauth_key key;
|
||||
|
||||
//init vars with default values
|
||||
char gcm_nonce[OAUTH_GCM_NONCE_SIZE+1]="";
|
||||
|
||||
char mac_key[OAUTH_MAC_KEY_SIZE+1]="";
|
||||
|
||||
time_t current_time = time(NULL);
|
||||
struct tm* gmt = gmtime(¤t_time);
|
||||
uint64_t token_timestamp = (unsigned long long)mktime(gmt) << 16;
|
||||
uint32_t token_lifetime = OAUTH_TOKEN_LIFETIME;
|
||||
|
||||
//oauth_key
|
||||
char kid[OAUTH_LTK_ID_SIZE+1] = "";
|
||||
char base64encoded_ltk[OAUTH_LTK_BASE64ENCODED_SIZE+1]="";
|
||||
turn_time_t key_timestamp = 0;
|
||||
turn_time_t key_lifetime = 0;
|
||||
char as_rs_alg[OAUTH_AS_RS_ALG_SIZE+1]="A256GCM";
|
||||
char server_name[OAUTH_SERVER_NAME_SIZE+1] = "";
|
||||
|
||||
char base64encoded_etoken[OAUTH_TOKEN_SIZE]="";
|
||||
|
||||
//TODO: replace SHA1 with an option. Actualy both big browser chrome and mozilla supports AFAIU implemented only SHA1.
|
||||
char hmac_alg[OAUTH_HMAC_ALG_SIZE+1]="HMAC-SHA1";
|
||||
|
||||
static int verbose_flag=0;
|
||||
static int encrypt_flag=0;
|
||||
static int decrypt_flag=0;
|
||||
|
||||
static struct option long_options[] =
|
||||
{
|
||||
/* These options set a flag. */
|
||||
{"verbose", no_argument, &verbose_flag, 1},
|
||||
{"encrypt", no_argument, &encrypt_flag, 1},
|
||||
{"decrypt", no_argument, &decrypt_flag, 1},
|
||||
{"help", no_argument, 0, 'h'},
|
||||
{"server-name", required_argument, 0, 'i'},
|
||||
{"auth-key-id", required_argument, 0, 'j'},
|
||||
{"auth-key", required_argument, 0, 'k'},
|
||||
{"auth-key-timestamp", required_argument, 0, 'l'},
|
||||
{"auth-key-lifetime", required_argument, 0, 'm'},
|
||||
{"auth-key-as-rs-alg", required_argument, 0, 'n'},
|
||||
{"token-nonce", required_argument, 0, 'o'},
|
||||
{"token-mac-key", required_argument, 0, 'p'},
|
||||
{"token-timestamp", required_argument, 0, 'q'},
|
||||
{"token-lifetime", required_argument, 0, 'r'},
|
||||
{"token", required_argument, 0, 't'},
|
||||
{"hmac-alg", required_argument, 0, 'u'},
|
||||
{0, 0, 0, 0}
|
||||
};
|
||||
/* getopt_long stores the option index here. */
|
||||
int option_index = 0;
|
||||
|
||||
//tmp vars
|
||||
size_t nonce_size=0;
|
||||
char *nonce_val;
|
||||
|
||||
size_t mac_key_size;
|
||||
char *mac_key_val;
|
||||
|
||||
|
||||
int i;
|
||||
int c=0;
|
||||
|
||||
set_logfile("stdout");
|
||||
set_system_parameters(0);
|
||||
|
||||
while ((c = getopt_long(argc, argv, "hvedi:j:k:l:m:n:o:p:q:r:t:u:",long_options, &option_index)) != -1) {
|
||||
switch(c) {
|
||||
case 'h':
|
||||
fprintf(stderr, "%s\n", Usage);
|
||||
exit(1);
|
||||
break;
|
||||
case 'v':
|
||||
verbose_flag=1;
|
||||
break;
|
||||
case 'e':
|
||||
encrypt_flag=1;
|
||||
break;
|
||||
case 'd':
|
||||
decrypt_flag=1;
|
||||
break;
|
||||
case 'i':
|
||||
//server-name
|
||||
if ( strlen(optarg) <= OAUTH_SERVER_NAME_SIZE ) {
|
||||
STRCPY(server_name,optarg);
|
||||
} else {
|
||||
fprintf(stderr,"Server-name must not exceed %d!\n", OAUTH_LTK_ID_SIZE );
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'j':
|
||||
//auth-key-id
|
||||
if ( strlen(optarg) <= OAUTH_LTK_ID_SIZE ) {
|
||||
STRCPY(kid,optarg);
|
||||
} else {
|
||||
fprintf(stderr,"Key ID must not exceed %d!\n", OAUTH_LTK_ID_SIZE );
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'k':
|
||||
//auth-key
|
||||
if ( strlen(optarg) <= OAUTH_LTK_BASE64ENCODED_SIZE ) {
|
||||
STRCPY(base64encoded_ltk,optarg);
|
||||
} else {
|
||||
fprintf(stderr,"Key must not exceed %d!\n", OAUTH_LTK_BASE64ENCODED_SIZE );
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'l':
|
||||
//auth-key-timestamp
|
||||
key_timestamp = atoi(optarg);
|
||||
break;
|
||||
case 'm':
|
||||
//auth-key-lifetime
|
||||
key_lifetime=atoi(optarg);
|
||||
break;
|
||||
case 'n':
|
||||
//auth-key-as-rs-alg
|
||||
if ( strlen(optarg) <= OAUTH_AS_RS_ALG_SIZE ) {
|
||||
STRCPY(as_rs_alg,optarg);
|
||||
} else {
|
||||
fprintf(stderr,"AS-RS Alg must not exceed %d!\n", OAUTH_AS_RS_ALG_SIZE );
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'o':
|
||||
//token-nonce
|
||||
nonce_val = (char*)base64_decode(optarg,strlen(optarg),&nonce_size);
|
||||
if (nonce_size > OAUTH_GCM_NONCE_SIZE){
|
||||
nonce_size=OAUTH_GCM_NONCE_SIZE;
|
||||
}
|
||||
strncpy(gcm_nonce,nonce_val,nonce_size);
|
||||
gcm_nonce[ nonce_size + 1 ]='\0';
|
||||
break;
|
||||
case 'p':
|
||||
//token-mac-key
|
||||
mac_key_val = (char*)base64_decode(optarg,strlen(optarg),&mac_key_size);
|
||||
if (mac_key_size > OAUTH_MAC_KEY_SIZE){
|
||||
mac_key_size=OAUTH_MAC_KEY_SIZE;
|
||||
}
|
||||
strncpy(mac_key,mac_key_val,mac_key_size);
|
||||
mac_key[mac_key_size+1]='\0';
|
||||
break;
|
||||
case 'q':
|
||||
//token-timestamp
|
||||
token_timestamp=strtoull(optarg,0,10);
|
||||
break;
|
||||
case 'r':
|
||||
//token-lifetime
|
||||
token_lifetime=atoi(optarg);
|
||||
break;
|
||||
case 't':
|
||||
if ( strlen(optarg) <= OAUTH_TOKEN_SIZE ) {
|
||||
STRCPY(base64encoded_etoken,optarg);
|
||||
} else {
|
||||
fprintf(stderr,"base64 encoded encrypted token must not exceed %d!\n", OAUTH_TOKEN_SIZE );
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
case 'u':
|
||||
//hmac-alg
|
||||
if ( strlen(optarg) <= OAUTH_HMAC_ALG_SIZE ) {
|
||||
STRCPY(hmac_alg,optarg);
|
||||
} else {
|
||||
fprintf(stderr,"STUN client HMAC Alg must not exceed %d!\n", OAUTH_HMAC_ALG_SIZE );
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
default:
|
||||
fprintf(stderr,"%s\n", Usage);
|
||||
exit(1);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = optind; i < argc; i++)
|
||||
printf ("Non-option argument %s\n", argv[i]);
|
||||
|
||||
if(optind>argc) {
|
||||
fprintf(stderr, "%s\n", Usage);
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (!(encrypt_flag || decrypt_flag)){
|
||||
fprintf(stderr, "Use either encrypt or decrypt.\nPlease use -h or --help for the detailed help\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
//check if we have required params
|
||||
//TODO: more compact warnning handling
|
||||
if (encrypt_flag || decrypt_flag){
|
||||
if (strlen(server_name) == 0) {
|
||||
fprintf(stderr, "For encode/decode --server-name/-i is mandatory \n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (strlen(kid) == 0){
|
||||
fprintf(stderr, "For encode/decode --auth-key-id/-j is mandatory \n");
|
||||
exit(-1);
|
||||
}
|
||||
if (strlen(base64encoded_ltk) == 0){
|
||||
fprintf(stderr, "For encode/decode --auth-key/-k is mandatory \n");
|
||||
exit(-1);
|
||||
}
|
||||
if (key_timestamp == 0){
|
||||
fprintf(stderr, "For encode/decode --auth-key-timestamp/-l is mandatory \n");
|
||||
exit(-1);
|
||||
}
|
||||
if (key_lifetime == 0){
|
||||
fprintf(stderr, "For encode/decode --auth-key-lifetime/-m is mandatory \n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (encrypt_flag && strlen(mac_key) == 0) {
|
||||
fprintf(stderr, "For encode --token-mac-key/-p is mandatory \n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
if (!encrypt_flag && decrypt_flag && strlen(base64encoded_etoken) == 0) {
|
||||
fprintf(stderr, "For decode --token/-t is mandatory \n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
// Expiry warnings
|
||||
if ( (unsigned long long)key_timestamp<<16 > token_timestamp +((unsigned long long)token_lifetime << 16) ) {
|
||||
fprintf(stderr,"\nWARNING: Token expiry is earlear then Auth key life time start timestamp!!\n\n");
|
||||
} else {
|
||||
if( (unsigned long long)key_timestamp<<16 > token_timestamp) {
|
||||
fprintf(stderr,"\nWARNING: Token life time start timestamp is earlier then Auth key start timestamp!!\n\n");
|
||||
}
|
||||
}
|
||||
if( (unsigned long long)( key_timestamp + key_lifetime )<<16 < token_timestamp ) {
|
||||
fprintf(stderr,"\nWARNING: Auth key will expire before token lifetime start timestamp!!\n\n");
|
||||
} else {
|
||||
if( (unsigned long long)( key_timestamp + key_lifetime)<<16 < token_timestamp + ((unsigned long long)token_lifetime << 16) ) {
|
||||
fprintf(stderr,"\nWARNING: Auth key will expire before token expiry!!\n\n");
|
||||
}
|
||||
}
|
||||
|
||||
if ( setup_ikm_key(kid, base64encoded_ltk, key_timestamp, key_lifetime, as_rs_alg, &key) == 0 ) {
|
||||
if(encrypt_flag) {
|
||||
if (encode_token(server_name, gcm_nonce, mac_key, token_timestamp, token_lifetime, key, base64encoded_etoken) == 0 ) {
|
||||
printf("{\n");
|
||||
printf(" \"access_token\":\"%s\",\n",base64encoded_etoken);
|
||||
printf(" \"token_type\":\"pop\",\n");
|
||||
printf(" \"expires_in\":%d,\n",token_lifetime);
|
||||
printf(" \"kid\":\"%s\",\n",kid);
|
||||
printf(" \"key\":\"%s\",\n",mac_key);
|
||||
printf(" \"alg\":\%s\n",hmac_alg);
|
||||
printf("}\n");
|
||||
} else {
|
||||
fprintf(stderr, "Error during token encode\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
if (decrypt_flag) {
|
||||
oauth_token dot;
|
||||
if ( validate_decode_token(server_name, key, base64encoded_etoken,&dot) == 0) {
|
||||
printf("-=Valid token!=-\n");
|
||||
if (verbose_flag) print_token_body(&dot);
|
||||
} else {
|
||||
fprintf(stderr, "Error during token validation and decoding\n");
|
||||
exit(-1);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
fprintf(stderr, "Error during key setup\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
@ -2511,6 +2511,7 @@ static int decode_oauth_token_gcm(const u08bits *server_name, const encoded_oaut
|
||||
const unsigned char *csnl = snl;
|
||||
|
||||
uint16_t nonce_len = nswap16(*((const uint16_t*)csnl));
|
||||
dtoken->enc_block.nonce_length = nonce_len;
|
||||
|
||||
size_t min_encoded_field_size = 2+4+8+nonce_len+2+OAUTH_GCM_TAG_SIZE+1;
|
||||
if(etoken->size < min_encoded_field_size) {
|
||||
@ -2521,6 +2522,7 @@ static int decode_oauth_token_gcm(const u08bits *server_name, const encoded_oaut
|
||||
const unsigned char* encoded_field = (const unsigned char*)(etoken->token + nonce_len + 2);
|
||||
unsigned int encoded_field_size = (unsigned int)etoken->size - nonce_len - 2 - OAUTH_GCM_TAG_SIZE;
|
||||
const unsigned char* nonce = ((const unsigned char*)etoken->token + 2);
|
||||
ns_bcopy(nonce,dtoken->enc_block.nonce,nonce_len);
|
||||
|
||||
unsigned char tag[OAUTH_GCM_TAG_SIZE];
|
||||
ns_bcopy(((const unsigned char*)etoken->token) + nonce_len + 2 + encoded_field_size, tag ,sizeof(tag));
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user