1
0
mirror of https://github.com/coturn/coturn.git synced 2025-10-24 04:20:59 +02:00

Merge pull request #48 from misi/oauth

OAuth utility
This commit is contained in:
misi 2016-09-07 15:40:36 +02:00 committed by GitHub
commit eacb77740b
11 changed files with 716 additions and 7 deletions

View File

@ -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':

View File

@ -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

View File

@ -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
View 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

View File

@ -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 ../..

View File

@ -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

View File

@ -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

View File

@ -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
View File

@ -0,0 +1 @@
turnutils.1

482
src/apps/oauth/oauth.c Normal file
View 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(&current_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;
}

View File

@ -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));