1+ <?php
2+ namespace APITools ;
3+ require_once ("apiresp.inc " );
4+ require_once ("php-jwt/src/JWT.php " );
5+ require_once ("php-jwt/src/ExpiredException.php " );
6+ require_once ("php-jwt/src/SignatureInvalidException.php " );
7+ require_once ("php-jwt/src/BeforeValidException.php " );
8+ require_once ("config.inc " );
9+ require_once ("util.inc " );
10+ require_once ("interfaces.inc " );
11+ require_once ("interfaces_fast.inc " );
12+ require_once ("service-utils.inc " );
13+ require_once ("filter.inc " );
14+ require_once ("shaper.inc " );
15+ require_once ("auth.inc " );
16+ require_once ("functions.inc " );
17+ use Firebase \JWT \JWT ;
18+ use Firebase \JWT \ExpiredException ;
19+ use Firebase \JWT \SignatureInvalidException ;
20+ use Firebase \JWT \BeforeValidException ;
21+
22+ # Gathers our URL form encoded data or JSON body data from our request and places them in a single array
23+ function get_request_data () {
24+ $ data = $ _GET ; // Accept HTTP requests in URL encoded format
25+ // Check if our URL encoded parameters are empty, if so try JSON encoded parameters
26+ if (empty ($ data )) {
27+ $ data = json_decode (file_get_contents ('php://input ' ), true );
28+ }
29+ return $ data ;
30+ }
31+
32+ # Locates our API configuration from pfSense's XML configuration. Returns
33+ function get_api_config () {
34+ global $ config ;
35+ $ api_pkg_name = "API " ;
36+ $ pkg_conf = $ config ["installedpackages " ]["package " ];
37+ // Check that our configuration is an array
38+ if (is_array ($ pkg_conf )) {
39+ // Loop through our packages and find our API package config
40+ foreach ($ pkg_conf as $ id => $ pkg ) {
41+ if ($ pkg ["name " ] === $ api_pkg_name ) {
42+ return array ($ id , $ pkg ["conf " ]);
43+ }
44+ }
45+ }
46+ }
47+
48+ # Checks if a specified user is disabled
49+ function is_user_disabled ($ username ) {
50+ global $ config ;
51+ $ users = index_users ();
52+ if (array_key_exists ("disabled " , $ config ["system " ]["user " ][$ users [$ username ]])) {
53+ return true ;
54+ }
55+ return false ;
56+ }
57+
58+ # Creates JWT server key if one does not exist, or optionally allows rotation of the JWT server key
59+ function create_jwt_server_key ($ rotate =false ) {
60+ global $ config ;
61+ $ pkg_index = get_api_configuration ()[0 ]; // Save our current API configs pkg index
62+ $ api_config = get_api_configuration ()[1 ]; // Save our current API config
63+ # Create a new server key if one is not set
64+ if (empty ($ api_config ["server_key " ]) or $ rotate === true ) {
65+ $ config ["installedpackages " ]["package " ][$ pkg_index ]["conf " ]["server_key " ] = bin2hex (random_bytes (32 ));
66+ write_config ();
67+ }
68+ }
69+
70+ # Creates a JWT to use for JWT authentication
71+ function create_jwt ($ data ) {
72+ global $ config ;
73+ $ api_config = get_api_config ()[1 ]; // Save our current API config
74+ $ token_exp = $ api_config ["jwt_exp " ]; // Expire token in one hours
75+ create_jwt_server_key (); // Ensure we have a JWT server key
76+ $ payload = array (
77+ "iss " => $ config ["system " ]["hostname " ],
78+ "exp " => time () + $ token_exp ,
79+ "nbf " => time (),
80+ "data " => $ data
81+ );
82+ return JWT ::encode ($ payload , $ api_config ["server_key " ]);
83+ }
84+
85+ # Decodes a JWT using our store server key
86+ function decode_jwt ($ token ) {
87+ $ key = get_api_config ()[1 ]["server_key " ]; // Save our current server key
88+ try {
89+ $ decoded = (array ) JWT ::decode ($ token , $ key , array ('HS256 ' ));
90+ } catch (Exception $ e ) {
91+ $ decoded = false ;
92+ }
93+ return $ decoded ;
94+ }
95+
96+ # Get our API tokens for a given username
97+ function get_existing_tokens ($ username ) {
98+ // Local variables
99+ $ api_config = get_api_config ()[1 ];
100+ $ key_user = bin2hex ($ username ); // Save our user's dedicated API client-ID
101+ $ user_keys = [];
102+ foreach ($ api_config ["keys " ]["key " ] as $ id => $ key ) {
103+ if ($ key ["client_id " ] === $ key_user ) {
104+ $ user_keys [$ id ] = array ("client_token " => $ key ["client_token " ], "algo " => $ key ["algo " ]);
105+ }
106+ }
107+ return $ user_keys ;
108+ }
109+
110+ # Authenticate using an API token
111+ function authenticate_token ($ cid , $ ctoken ) {
112+ $ authenticated = false ;
113+ $ hex_to_user = pack ("H* " , $ cid );
114+ // First check if our hex decoded user exists
115+ if (in_array ($ hex_to_user , index_users ())) {
116+ // Loop through each of our users API tokens and check if key matches
117+ foreach (get_existing_tokens ($ hex_to_user ) as $ id => $ data ) {
118+ $ hash_input_key = hash ($ data ["algo " ], $ ctoken ); // Hash our key using our configured algos
119+ if ($ hash_input_key === $ data ["client_token " ]) {
120+ $ authenticated = true ;
121+ break ;
122+ }
123+ }
124+ }
125+ return $ authenticated ;
126+ }
0 commit comments