I think I have a problem with the cURL handshake... #197
-
I've based my code solution from the auth_guest_with_note, though currently the note part is commented out as I am unable to simply auth a client. The client device is still in its box (Amazon echo dot; IoT device) and I'm just trying to manually pre-authorize it. I wasn't originally getting any errors returned from the standard authorization method (authorize_guest), but it unfortunately also wasn't returning a value. After enabling debugging, I notice that there are two login attempts being printed to webpage output, with responses in json encoded strings, but no further debug output is provided. <pre>
-----------LOGIN-------------
Array
(
[url] => https://192.168.3.10/api/auth/login
[content_type] => application/json; charset=utf-8
[http_code] => 200
[header_size] => 911
[request_size] => 189
[filetime] => -1
[ssl_verify_result] => 18
[redirect_count] => 0
[total_time] => 0.67413
[namelookup_time] => 3.7E-5
[connect_time] => 3.8E-5
[pretransfer_time] => 0.00016
[size_upload] => 48
[size_download] => 3045
[speed_download] => 4517
[speed_upload] => 71
[download_content_length] => 3045
[upload_content_length] => 48
[starttransfer_time] => 0.000164
[redirect_time] => 0
[redirect_url] =>
[primary_ip] => 192.168.3.10
[certinfo] => Array
(
)
[primary_port] => 443
[local_ip] => 172.16.238.10
[local_port] => 51396
[http_version] => 3
[protocol] => 2
[ssl_verifyresult] => 0
[scheme] => HTTPS
[appconnect_time_us] => 38
[connect_time_us] => 38
[namelookup_time_us] => 37
[pretransfer_time_us] => 160
[redirect_time_us] => 0
[starttransfer_time_us] => 164
[total_time_us] => 674130
)
----------RESPONSE-----------
{"unique_id":"19c5c146-8a60-4687-aab5-39027b303e0b","first_name":"ssplbob","last_name":" ","alias":"","full_name":"ssplbob ","email":"","email_status":"UNVERIFIED","email_is_null":true,"phone":"","avatar_relative_path":"","avatar_rpath2":"","status":"ACTIVE","employee_number":"","create_time":1690404426,"login_time":1690472099,"extras":{},"username":"ssplbob","local_account_exist":true,"password_revision":1690404701,"sso_account":"","sso_uuid":"","sso_username":"","sso_picture":"","uid_sso_id":"","uid_sso_account":"","uid_account_status":"","groups":[{"unique_id":"9f811dc7-53cb-4a5b-b434-ac11d7d97805","name":"Cloud-Key-Gen2-Plus","up_id":"","up_ids":[],"system_name":"Cloud-Key-Gen2-Plus","create_time":"2023-06-06T14:20:59-04:00"}],"roles":[{"unique_id":"c33597bc-1029-4244-838b-3ce2301ad04c","name":"role_private_1690404699","system_role":false,"system_key":"custom_administrator_9583a5c3-13dd-4fde-abbc-f76364fa10d0","level":5,"create_time":"2023-07-26T16:47:04-04:00","update_time":"2023-07-26T16:51:39-04:00"}],"permissions":{"network.management":["admin"],"system.management.user":["admin"]},"scopes":["view:user","view:settings","view:role","view:permission","view:os-menu:user","view:os-menu:system-log","view:os-menu:storage","view:os-menu:settings","view:os-menu:notify-settings","view:os-menu:map","view:os-menu:devices","view:os-menu:about","view:group","view:controller:network","view:app:users","view:app:settings","systemlog:user","notify:user","manage:controller:network","edit:user","edit:unifi-os:user","edit:settings","edit:role","edit:os-settings:update_install","edit:os-settings:support_file","edit:os-settings:ssh","edit:os-settings:send_diagnostics","edit:os-settings:restart","edit:os-settings:raid","edit:os-settings:poweroff","edit:os-settings:notify","edit:os-settings:hotspare","edit:os-settings:general","edit:os-settings:client_network","edit:os-settings:auto_update","assign:role"],"cloud_access_granted":false,"only_local_account":true,"update_time":1690404426,"avatar":null,"nfc_token":"","nfc_display_id":"","nfc_card_type":"","nfc_card_status":"","role":"custom","id":"19c5c146-8a60-4687-aab5-39027b303e0b","isOwner":false,"isSuperAdmin":false,"isMember":false,"ucorePermission":{"hasViewUserPermission":true,"hasEditUserPermission":true,"hasViewSettingsPermission":true,"hasUpdateChannelPermission":false,"hasGeneralSettingsPermission":true,"hasUpdateAndInstallPermission":true,"hasAutoUpdatePermission":true,"hasNotificationPermission":true,"hasRemoteAccessPermission":false,"hasBackupPermission":false,"hasRestartConsolePermission":true,"hasPoweroffConsolePermission":true,"hasResetConsolePermission":false,"hasTransferOwnerPermission":false,"hasSSHPermission":true,"hasSupportFilePermission":true},"maskedEmail":"","deviceToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2NjAzNjg0YS1lYTEyLTRjZGMtODY2MS1jMTQ3ZDc1NjE4MDgiLCJpYXQiOjE2OTExNzU2ODYsImlzcyI6IlVMUC1HTyIsInVzZXJfaWQiOiIxOWM1YzE0Ni04YTYwLTQ2ODctYWFiNS0zOTAyN2IzMDNlMGIifQ.4NlPKEBfWH-qC7iU0hO3kxUQnLjA7VdFKtqKVmpyPn8","ssoAuth":{}}
-----------------------------
</pre>
<pre>
-----------LOGIN-------------
Array
(
[url] => https://192.168.3.10/api/auth/login
[content_type] => application/json; charset=utf-8
[http_code] => 200
[header_size] => 911
[request_size] => 189
[filetime] => -1
[ssl_verify_result] => 18
[redirect_count] => 0
[total_time] => 0.624345
[namelookup_time] => 5.4E-5
[connect_time] => 5.4E-5
[pretransfer_time] => 0.000236
[size_upload] => 48
[size_download] => 3045
[speed_download] => 4879
[speed_upload] => 76
[download_content_length] => 3045
[upload_content_length] => 48
[starttransfer_time] => 0.00024
[redirect_time] => 0
[redirect_url] =>
[primary_ip] => 192.168.3.10
[certinfo] => Array
(
)
[primary_port] => 443
[local_ip] => 172.16.238.10
[local_port] => 60278
[http_version] => 3
[protocol] => 2
[ssl_verifyresult] => 0
[scheme] => HTTPS
[appconnect_time_us] => 55
[connect_time_us] => 54
[namelookup_time_us] => 54
[pretransfer_time_us] => 236
[redirect_time_us] => 0
[starttransfer_time_us] => 240
[total_time_us] => 624345
)
----------RESPONSE-----------
{"unique_id":"19c5c146-8a60-4687-aab5-39027b303e0b","first_name":"ssplbob","last_name":" ","alias":"","full_name":"ssplbob ","email":"","email_status":"UNVERIFIED","email_is_null":true,"phone":"","avatar_relative_path":"","avatar_rpath2":"","status":"ACTIVE","employee_number":"","create_time":1690404426,"login_time":1690472099,"extras":{},"username":"ssplbob","local_account_exist":true,"password_revision":1690404701,"sso_account":"","sso_uuid":"","sso_username":"","sso_picture":"","uid_sso_id":"","uid_sso_account":"","uid_account_status":"","groups":[{"unique_id":"9f811dc7-53cb-4a5b-b434-ac11d7d97805","name":"Cloud-Key-Gen2-Plus","up_id":"","up_ids":[],"system_name":"Cloud-Key-Gen2-Plus","create_time":"2023-06-06T14:20:59-04:00"}],"roles":[{"unique_id":"c33597bc-1029-4244-838b-3ce2301ad04c","name":"role_private_1690404699","system_role":false,"system_key":"custom_administrator_9583a5c3-13dd-4fde-abbc-f76364fa10d0","level":5,"create_time":"2023-07-26T16:47:04-04:00","update_time":"2023-07-26T16:51:39-04:00"}],"permissions":{"network.management":["admin"],"system.management.user":["admin"]},"scopes":["view:user","view:settings","view:role","view:permission","view:os-menu:user","view:os-menu:system-log","view:os-menu:storage","view:os-menu:settings","view:os-menu:notify-settings","view:os-menu:map","view:os-menu:devices","view:os-menu:about","view:group","view:controller:network","view:app:users","view:app:settings","systemlog:user","notify:user","manage:controller:network","edit:user","edit:unifi-os:user","edit:settings","edit:role","edit:os-settings:update_install","edit:os-settings:support_file","edit:os-settings:ssh","edit:os-settings:send_diagnostics","edit:os-settings:restart","edit:os-settings:raid","edit:os-settings:poweroff","edit:os-settings:notify","edit:os-settings:hotspare","edit:os-settings:general","edit:os-settings:client_network","edit:os-settings:auto_update","assign:role"],"cloud_access_granted":false,"only_local_account":true,"update_time":1690404426,"avatar":null,"nfc_token":"","nfc_display_id":"","nfc_card_type":"","nfc_card_status":"","role":"custom","id":"19c5c146-8a60-4687-aab5-39027b303e0b","isOwner":false,"isSuperAdmin":false,"isMember":false,"ucorePermission":{"hasViewUserPermission":true,"hasEditUserPermission":true,"hasViewSettingsPermission":true,"hasUpdateChannelPermission":false,"hasGeneralSettingsPermission":true,"hasUpdateAndInstallPermission":true,"hasAutoUpdatePermission":true,"hasNotificationPermission":true,"hasRemoteAccessPermission":false,"hasBackupPermission":false,"hasRestartConsolePermission":true,"hasPoweroffConsolePermission":true,"hasResetConsolePermission":false,"hasTransferOwnerPermission":false,"hasSSHPermission":true,"hasSupportFilePermission":true},"maskedEmail":"","deviceToken":"eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2NTE4MmE1ZS04YjhhLTRkMjQtODA1My1jZGI2ZTdlNDNkZmEiLCJpYXQiOjE2OTExNzU2ODcsImlzcyI6IlVMUC1HTyIsInVzZXJfaWQiOiIxOWM1YzE0Ni04YTYwLTQ2ODctYWFiNS0zOTAyN2IzMDNlMGIifQ.ms3iE1fQ-Y_OVizRohlhVobqAJgUCBtOf4CfMfX0wXw","ssoAuth":{}}
-----------------------------
</pre> It seems to be successful it making connection (200 HTTP response), but doesn't appear to retain the connection. The local administrative account being used was created just yesterday with default administrative settings. The UCK G2 Plus system logs show that the particular user defined in the API settings had logged in via console's IP. The PHP error log shows quite a few warnings when debug is true, which seems to indicate a looping black hole.
I can provide the PHP code, but in terms of functionality, it's nearly identical to the example code. Here's the call to authorize the guest, at least: define('DOWNLOAD', 10000); // simple Mb -> Kb conversion (10 Mbps)
define('UPLOAD', 2000); // simple Mb -> Kb conversion (2 Mbps)
// ...
$auth_result = $unifi_connection->authorize_guest($mac, $duration, DOWNLOAD, UPLOAD); What I have done differently, is that I've moved the Client.php, config.php, and calling script (renamed to index.php) to the root of a single folder, and only included those files. Could this cause such a problem? For config, our controller seems to only work with port 443 set, or no port (since HTTPS is port 443). UCK G2 Plus: v3.1.14 |
Beta Was this translation helpful? Give feedback.
Replies: 10 comments 3 replies
-
Please also share the PHP code together with the sanitized parameter values. |
Beta Was this translation helpful? Give feedback.
-
<?php
define('CSV_FILE', './client_data.csv');
// initialize
$auth_result = $getid_result = $user_id = $note_result = null;
if (isset($_POST['remove']) && is_numeric($_POST['remove'])):
// Adjust to 0 based index for the file; 1 based index for passed value
$row = abs(--$_POST['remove']);
$file_str = file(CSV_FILE); // Read the whole file into an array
unset($file_str[$row]);
file_put_contents(CSV_FILE, implode("", $file_str));
elseif (isset($_POST['mac_address']) && $_POST['mac_address']):
// handle stuff...
define('DOWNLOAD', 10000); // simple Mb -> Kb conversion (10 Mbps)
define('UPLOAD', 2000); // simple Mb -> Kb conversion (2 Mbps)
require_once 'Client.php';
require_once 'config.php';
// API variables
$mac = $_POST['mac_address']; // if known, can speed up association
$duration = 2000; // the duration to authorize the device for in minutes
$site_id = 'Default'; //The site to authorize the device with
$note = 'BYPASS: ' . strip_tags($_POST['client_note']); // the note to attach to the device
/**
* initialize the UniFi API connection class and log in to the controller
*/
$unifi_connection = new UniFi_API\Client($controlleruser, $controllerpassword, $controllerurl, $site_id, $controllerversion);
$set_debug_mode = $unifi_connection->set_debug($debug);
$loginresults = $unifi_connection->login();
/**
* we authorize the device for the requested duration and attach the note to it's object
*/
// * @param string $mac client MAC address
// * @param int $minutes minutes (from now) until authorization expires
// * @param int $up optional, upload speed limit in kbps
// * @param int $down optional, download speed limit in kbps
// * @param int $megabytes optional, total data transfer limit in MB
$auth_result = $unifi_connection->authorize_guest($mac, $duration, DOWNLOAD, UPLOAD);
if ($auth_result !=== false) {
$file = fopen(CSV_FILE, 'a');
fputcsv($file, [time(), $mac, $note]);
fclose($file);
}
endif;
?><!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>UniFi Device Bypass</title>
<link href="https://cdn.jsdelivr.net/npm/[email protected]/dist/css/bootstrap.min.css" rel="stylesheet" integrity="sha384-4bw+/aepP/YC94hEpVNVgiZdgIC5+VKNBQNGCHeKRQN+PtmoHDEXuppvnDJzQIu9" crossorigin="anonymous">
</head>
<body>
<div class="container-fluid">
<div class="row gx-2">
<div class="col-1 py-1 bg-dark text-white fs-5 fw-bold text-center">Index</div>
<div class="col-2 py-1 bg-dark text-white fs-5 fw-bold text-center">Added</div>
<div class="col-3 py-1 bg-dark text-white fs-5 fw-bold text-center">MAC Address</div>
<div class="col-5 py-1 bg-dark text-white fs-5 fw-bold text-center">Note</div>
<div class="col-1 py-1 bg-dark text-white fs-5 fw-bold text-center"></div>
</div>
<?php
if ($auth_result || $getid_result || $user_id || $note_result) {
echo '<div class="row"><div class="col-12 bg-success">';
echo 'Auth: ' . $auth_result . '<br>';
echo 'ID: ' . $getid_result . '<br>';
echo 'User: ' . $user_id . '<br>';
echo 'Note: ' . $note_result . '<br>';
echo '</div></div>';
}
?>
<form action="" method="post" name="form" id="form" class="row gx-2 py-1">
<div class="col-1"></div>
<div class="col-2"></div>
<div class="col-3">
<label class="visually-hidden" for="mac_address">MAC Address</label>
<input type="text" class="form-control text-center" name="mac_address" id="mac_address" placeholder="00:00:00:00:00:00">
</div>
<div class="col-5">
<label class="visually-hidden" for="client_note">Note</label>
<input type="text" class="form-control" id="client_note" name="client_note" placeholder="">
</div>
<div class="col-1 text-center">
<button type="submit" class="btn btn-success">+</button>
</div>
</form>
<?php
if (file_exists(CSV_FILE)) {
$row = 1;
if (($handle = fopen(CSV_FILE, "r")) !== FALSE) {
while (($data = fgetcsv($handle, 1000, ",")) !== FALSE) {
// index 0: timestamp
// index 1: mac address
// index 2: note
?>
<div class="row gx-2 py-1">
<div class="col-1 text-center"><?= $row ?></div>
<div class="col-2 text-center"><time datetime="<?= date('c', $data[0]) ?>" title="<?= date('g:ia', $data[0]) ?>"><?= date('M j, Y', $data[0]) ?></time></div>
<div class="col-3 text-center"><?= $data[1] ?></div>
<div class="col-5 text-center"><?= str_replace('BYPASS: ', '', $data[2]) ?></div>
<div class="col-1 text-center"><button type="submit" name="remove" form="form" value="<?= $row ?>" class="btn btn-danger">×</button></div>
</div>
<?php
$row++;
}
}
}
?>
</div>
</body>
<script src="https://cdn.jsdelivr.net/npm/[email protected]/dist/js/bootstrap.bundle.min.js" integrity="sha384-HwwvtgBNo3bZJJLYd8oVXjrBZt8cqVSpeBNS5n7C8IVInixGAoxmnlMuBnhbgrkm" crossorigin="anonymous"></script>
</html> client_data.csv:
config.php (values adjusted): $controlleruser = 'bob';
$controllerpassword = 'supersecretpassword-edited';
$controllerurl = 'https://192.168.1.10';
$controllerversion = '7.4.162';
$debug = true; |
Beta Was this translation helpful? Give feedback.
-
Hmm, the code that interacts with the API client looks fine as long as the passed parameters are correct. I would implement more validation/sanitization logic when processing user input. That being said, I do see one error in the code: if ($auth_result !=== false) {
$file = fopen(CSV_FILE, 'a');
fputcsv($file, [time(), $mac, $note]);
fclose($file);
} That comparison operator does not exist in PHP: |
Beta Was this translation helpful? Give feedback.
-
To troubleshoot this, I would trim down the code to the bare minimum with some hard-coded values instead of capturing user input, then expand until the code breaks. |
Beta Was this translation helpful? Give feedback.
-
Assuming I still receive the same symptoms when culling it down to the absolute minimum - any thoughts? The improper equivalence operator was added while I was copy/pasting and cleaning up some things. Apologies for that. (The script writes to the file regardless of success.) In terms of sanitization, you're correct - but as of right now I'm still developing it and just working to get it working, so I'm the only one using it. Thanks for the feedback thus far! |
Beta Was this translation helpful? Give feedback.
-
We use that same function/method in all our captive portal and have nu issues whatsoever across all current controller types and versions. What we do see is that it’s important to pass all parameters (mac, duration, upload, download and data transfer limits) especially with controller version 7.4.x. We don’t see the same symptoms you are experiencing so either your environment, or controller is affecting things. Not sure why though… |
Beta Was this translation helpful? Give feedback.
-
One thing to check is whether the local user account you’re using has full permissions for access to the Network Application. It must not be an account with remote access. |
Beta Was this translation helpful? Give feedback.
-
We made that mistake earlier when trying to connect the API-browser, initially (remote access account instead of local). Definitely a local account, now. I'm not the account owner, so I've been told it has full permissions, and based on results from the API browser it does appear to be the case. I tried to check the API browser for Clients/users --> stat authorizations, the JSON load seemingly hung. I don't know if that's related or not. I wasn't passing in a data transfer limit, so perhaps that's an issue. I'm leaning more towards environmental or controller, but I wouldn't know where to test outside of that, aside from placing simple code on a different device on the network (environment). I'll double-check that the user account is not set to read-only, as we originally only set it up for gathering statistics (we'd purchased the WAN and Client Usage Reporting tool). Thanks again for your feedback and thoughts! |
Beta Was this translation helpful? Give feedback.
-
I was hoping it was a user permissions issue, but that doesn't seem to be the case. Network: Full Management and OS Setting: Full Management. Now it appears to be environmental. The unfortunate part is that other tools (our licensed WAN and Client Usage Reporting tool, and the Unifi-API-browser) appear to connect and work completely fine. I'm getting the same result with a completely simplified version (where it uses the same config file), even attempting to include the AP MAC, just in case (I also tried without): <?php
require_once 'Client.php';
require_once 'config.php';
$mac = 'c0:91:b9:62:58:79';
$duration = 2000;
$site_id = 'Default';
$debug = true;
$unifi_connection = new UniFi_API\Client($controlleruser, $controllerpassword, $controllerurl, $site_id, $controllerversion);
$set_debug_mode = $unifi_connection->set_debug($debug);
$loginresults = $unifi_connection->login();
$auth_result = $unifi_connection->authorize_guest($mac, $duration, 2000, 2000, 20000, 'AC:8B:A9:42:17:2D');
echo json_encode($auth_result, JSON_PRETTY_PRINT); Is there a possible compatibility with this particular method call and controller version 7.4.162, and/or UnifiOS v3.1.14? For reference, I tried running this code on the microserver that we're using to run the WAN and Client Usage Reporting tool (a wired client instead of a personal laptop running on wireless) and it had the same result. If other tools work as expected, would this still potentially be a firewall issue? |
Beta Was this translation helpful? Give feedback.
-
Okay. I feel dumb. $site_id is not Site name, and it is case-sensitive. It now works. I honestly didn't realize there was a difference... @malle-pietje - thank you so much for trying to offer suggestions on where to look, I really appreciate it - sorry it was such a mundane little thing. It often is though, right? I'll backtrack and make sure it now works with the added functionality that I created in my original code (which did have a lowercase 'default' site_id value.) |
Beta Was this translation helpful? Give feedback.
Okay. I feel dumb. $site_id is not Site name, and it is case-sensitive.
$site_id = 'Default';
$site_id = 'default';
It now works. I honestly didn't realize there was a difference... @malle-pietje - thank you so much for trying to offer suggestions on where to look, I really appreciate it - sorry it was such a mundane little thing. It often is though, right?
I'll backtrack and make sure it now works with the added functionality that I created in my original code (which did have a lowercase 'default' site_id value.)