Skip to content

Commit

Permalink
Merge pull request #1002 from itflow-org/api-logins
Browse files Browse the repository at this point in the history
Allow decrypting logins/credentials via the API
  • Loading branch information
johnnyq authored Aug 25, 2024
2 parents 2202f31 + 24ff6f5 commit 21a31a1
Show file tree
Hide file tree
Showing 11 changed files with 379 additions and 54 deletions.
130 changes: 85 additions & 45 deletions admin_api_key_add_modal.php
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
<?php
$key = randomString(156);
$decryptPW = randomString(160);
?>
<div class="modal" id="addApiKeyModal" tabindex="-1">
<div class="modal-dialog">
Expand All @@ -13,64 +14,103 @@
<form action="post.php" method="post" autocomplete="off">
<div class="modal-body bg-white">

<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<input type="hidden" name="key" value="<?php echo $key ?>">
<ul class="nav nav-pills nav-justified mb-3">
<li class="nav-item">
<a class="nav-link active" data-toggle="pill" href="#pills-api-details">Details</a>
</li>
<li class="nav-item">
<a class="nav-link" data-toggle="pill" href="#pills-api-keys">Keys</a>
</li>
</ul>
<hr>

<div class="form-group">
<label>API Key <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
</div>
<input type="text" class="form-control" value="<?php echo $key ?>" required disabled>
<div class="input-group-append">
<button class="btn btn-default clipboardjs" type="button" data-clipboard-text="<?php echo $key; ?>"><i class="fa fa-fw fa-copy"></i></button>
<div class="tab-content">

<div class="tab-pane fade show active" id="pills-api-details">
<input type="hidden" name="csrf_token" value="<?php echo $_SESSION['csrf_token'] ?>">
<input type="hidden" name="key" value="<?php echo $key ?>">
<input type="hidden" name="password" value="<?php echo $decryptPW ?>">

<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-sticky-note"></i></span>
</div>
<input type="text" class="form-control" name="name" placeholder="Key Name" required autofocus>
</div>
</div>
</div>
</div>

<hr>
<div class="form-group">
<label>Expiration Date <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-calendar"></i></span>
</div>
<input type="date" class="form-control" name="expire" min="<?php echo date('Y-m-d')?>" max="2999-12-31" required>
</div>
</div>

<div class="form-group">
<label>Name <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-sticky-note"></i></span>
<div class="form-group">
<label>Client Access <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-user"></i></span>
</div>
<select class="form-control select2" name="client" required>
<option value="0"> ALL CLIENTS </option>
<?php
$sql = mysqli_query($mysqli, "SELECT * FROM clients ORDER BY client_name ASC");
while ($row = mysqli_fetch_array($sql)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']); ?>
<option value="<?php echo $client_id; ?>"><?php echo "$client_name (Client ID: $client_id)"; ?></option>
<?php } ?>
</select>
</div>
</div>
<input type="text" class="form-control" name="name" placeholder="Key Name" required autofocus>
</div>
</div>

<div class="form-group">
<label>Expiration Date <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-calendar"></i></span>
<div class="tab-pane fade" id="pills-api-keys">
<div class="form-group">
<label>API Key <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-key"></i></span>
</div>
<input type="text" class="form-control" value="<?php echo $key ?>" required disabled>
<div class="input-group-append">
<button class="btn btn-default clipboardjs" type="button" data-clipboard-text="<?php echo $key; ?>"><i class="fa fa-fw fa-copy"></i></button>
</div>
</div>
</div>
<input type="date" class="form-control" name="expire" min="<?php echo date('Y-m-d')?>" max="2999-12-31" required>
</div>
</div>

<div class="form-group">
<label>Client Access <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-user"></i></span>
<div class="form-group">
<label>Login credential decryption password <strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<span class="input-group-text"><i class="fa fa-fw fa-unlock-alt"></i></span>
</div>
<input type="text" class="form-control" value="<?php echo $decryptPW ?>" required disabled>
<div class="input-group-append">
<button class="btn btn-default clipboardjs" type="button" data-clipboard-text="<?php echo $decryptPW; ?>"><i class="fa fa-fw fa-copy"></i></button>
</div>
</div>
</div>
<br>
<div class="form-group">
<label>I have made a copy of the key(s)<strong class="text-danger">*</strong></label>
<div class="input-group">
<div class="input-group-prepend">
<input type="checkbox" name="ack" value="1" required>
</div>
</div>
</div>
<select class="form-control select2" name="client" required>
<option value="0"> ALL CLIENTS </option>
<?php
$sql = mysqli_query($mysqli, "SELECT * FROM clients ORDER BY client_name ASC");
while ($row = mysqli_fetch_array($sql)) {
$client_id = intval($row['client_id']);
$client_name = nullable_htmlentities($row['client_name']); ?>
<option value="<?php echo $client_id; ?>"><?php echo "$client_name (Client ID: $client_id)"; ?></option>
<?php } ?>
</select>
</div>

</div>

</div>
</div>
<div class="modal-footer bg-white">
<button type="submit" name="add_api_key" class="btn btn-primary text-bold"><i class="fa fa-check mr-2"></i>Create</button>
<button type="button" class="btn btn-light" data-dismiss="modal"><i class="fas fa-times mr-2"></i>Cancel</button>
Expand Down
30 changes: 30 additions & 0 deletions api/v1/credentials/create.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
<?php

require_once '../validate_api_key.php';

require_once '../require_post_method.php';

// Parse info
require_once 'credential_model.php';

// Default
$insert_id = false;

if (!empty($api_key_decrypt_password) && !empty($name) && !(empty($password))) {

// Add credential
$insert_sql = mysqli_query($mysqli,"INSERT INTO logins SET login_name = '$name', login_description = '$description', login_uri = '$uri', login_uri_2 = '$uri_2', login_username = '$username', login_password = '$password', login_otp_secret = '$otp_secret', login_note = '$note', login_important = $important, login_contact_id = $contact_id, login_vendor_id = $vendor_id, login_asset_id = $asset_id, login_software_id = $software_id, login_client_id = $client_id");

// Check insert & get insert ID
if ($insert_sql) {
$insert_id = mysqli_insert_id($mysqli);

//Logging
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'Credential', log_action = 'Create', log_description = '$name via API ($api_key_name)', log_ip = '$ip', log_user_agent = '$user_agent', log_client_id = $client_id");
mysqli_query($mysqli, "INSERT INTO logs SET log_type = 'API', log_action = 'Success', log_description = 'Created credential $name via API ($api_key_name)', log_ip = '$ip', log_user_agent = '$user_agent', log_client_id = $client_id");
}

}

// Output
require_once '../create_output.php';
120 changes: 120 additions & 0 deletions api/v1/credentials/credential_model.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
<?php


// Variable assignment from POST (or: blank/from DB is updating)

$api_key_decrypt_password = '';
if (isset($_POST['api_key_decrypt_password'])) {
$api_key_decrypt_password = $_POST['api_key_decrypt_password']; // No sanitization
}

if (isset($_POST['login_name'])) {
$name = sanitizeInput($_POST['login_name']);
} elseif (isset($credential_row) && isset($credential_row['login_name'])) {
$name = $credential_row['login_name'];
} else {
$name = '';
}

if (isset($_POST['login_description'])) {
$description = sanitizeInput($_POST['login_description']);
} elseif (isset($credential_row) && isset($credential_row['login_description'])) {
$description = $credential_row['login_description'];
} else {
$description = '';
}

if (isset($_POST['login_uri'])) {
$uri = sanitizeInput($_POST['login_uri']);
} elseif (isset($credential_row) && isset($credential_row['login_uri'])) {
$uri = $credential_row['login_uri'];
} else {
$uri = '';
}

if (isset($_POST['login_uri_2'])) {
$uri_2 = sanitizeInput($_POST['login_uri_2']);
} elseif (isset($credential_row) && isset($credential_row['login_uri_2'])) {
$uri_2 = $credential_row['login_uri_2'];
} else {
$uri_2 = '';
}

if (isset($_POST['login_username'])) {
$username = $_POST['login_username'];
$username = apiEncryptLoginEntry($username, $api_key_decrypt_hash, $api_key_decrypt_password);
} elseif (isset($credential_row) && isset($credential_row['login_username'])) {
$username = $credential_row['login_username'];
} else {
$username = '';
}

if (isset($_POST['login_password'])) {
$password = $_POST['login_password'];
$password = apiEncryptLoginEntry($password, $api_key_decrypt_hash, $api_key_decrypt_password);
$password_changed = true;
} elseif (isset($credential_row) && isset($credential_row['login_password'])) {
$password = $credential_row['login_password'];
$password_changed = false;
} else {
$password = '';
$password_changed = false;
}



if (isset($_POST['login_otp_secret'])) {
$otp_secret = sanitizeInput($_POST['login_otp_secret']);
} elseif (isset($credential_row) && isset($credential_row['login_otp_secret'])) {
$otp_secret = $credential_row['login_otp_secret'];
} else {
$otp_secret = '';
}

if (isset($_POST['login_note'])) {
$note = sanitizeInput($_POST['login_note']);
} elseif (isset($credential_row) && isset($credential_row['login_note'])) {
$note = $credential_row['login_note'];
} else {
$note = '';
}

if (isset($_POST['login_important'])) {
$important = intval($_POST['login_important']);
} elseif (isset($credential_row) && isset($credential_row['login_important'])) {
$important = $credential_row['login_important'];
} else {
$important = '';
}

if (isset($_POST['login_contact_id'])) {
$contact_id = intval($_POST['login_contact_id']);
} elseif (isset($credential_row) && isset($credential_row['login_contact_id'])) {
$contact_id = $credential_row['login_contact_id'];
} else {
$contact_id = '';
}

if (isset($_POST['login_vendor_id'])) {
$vendor_id = intval($_POST['login_vendor_id']);
} elseif (isset($credential_row) && isset($credential_row['login_vendor_id'])) {
$vendor_id = $credential_row['login_vendor_id'];
} else {
$vendor_id = '';
}

if (isset($_POST['login_asset_id'])) {
$asset_id = intval($_POST['login_asset_id']);
} elseif (isset($credential_row) && isset($credential_row['login_asset_id'])) {
$asset_id = $credential_row['login_asset_id'];
} else {
$asset_id = '';
}

if (isset($_POST['login_software_id'])) {
$software_id = intval($_POST['login_software_id']);
} elseif (isset($credential_row) && isset($credential_row['login_software_id'])) {
$software_id = $credential_row['login_software_id'];
} else {
$software_id = '';
}
60 changes: 60 additions & 0 deletions api/v1/credentials/read.php
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
<?php

require_once '../validate_api_key.php';

require_once '../require_get_method.php';

// Defaults
$sql = false;

$api_key_decrypt_password = '';
if (isset($_GET['api_key_decrypt_password'])) {
$api_key_decrypt_password = $_GET['api_key_decrypt_password']; // No sanitization
}

// Specific credential/login via ID (single)
if (isset($_GET['login_id']) && !empty($api_key_decrypt_password)) {

$id = intval($_GET['login_id']);

$sql = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_id = '$id' AND login_client_id LIKE '$client_id' LIMIT 1");


} elseif (!empty($api_key_decrypt_password)) {
// All credentials ("logins")
$api_key_decrypt_password = $_GET['api_key_decrypt_password']; // No sanitization

$sql = mysqli_query($mysqli, "SELECT * FROM logins WHERE login_client_id LIKE '$client_id' ORDER BY login_id LIMIT $limit OFFSET $offset");

}

// Output - Not using the standard API read_output.php
// Usually we just output what is in the database, but credentials need to be decrypted first.

if ($sql && mysqli_num_rows($sql) > 0) {

$return_arr['success'] = "True";
$return_arr['count'] = mysqli_num_rows($sql);

$row = array();
while ($row = mysqli_fetch_array($sql)) {
$row['login_username'] = apiDecryptLoginEntry($row['login_username'], $api_key_decrypt_hash, $api_key_decrypt_password);
$row['login_password'] = apiDecryptLoginEntry($row['login_password'], $api_key_decrypt_hash, $api_key_decrypt_password);
$return_arr['data'][] = $row;
}

echo json_encode($return_arr);
exit();
}
else {
$return_arr['success'] = "False";
$return_arr['message'] = "No resource (for this client and company) with the specified parameter(s).";

// Log any database/schema related errors to the PHP Error log
if (mysqli_error($mysqli)) {
error_log("API Database Error: " . mysqli_error($mysqli));
}

echo json_encode($return_arr);
exit();
}
Loading

0 comments on commit 21a31a1

Please sign in to comment.