mirror of
https://github.com/dmcxblue/ANIMO
synced 2026-08-04 16:10:26 +00:00
Native implementation of the DRS wire protocol - joins a fresh fake
device to Entra and persists the returned deviceId + X.509 device
cert. Cert-based persistence survives password reset.
- shared/DeviceCryptoHelper.{h,cpp}: pure-OpenSSL asymmetric
primitives (Qt exposes none of these).
generateRsa2048() RSA-2048 keypair, PKCS#8 PEM out.
buildCsr() PKCS#10 CSR signed with SHA-256, PEM out.
csrPemToDrsBase64() strip PEM armor for the DRS enroll body.
signJwtRS256() compact JWS serialization for cert-bound
client_assertion (used by follow-up PRT
mint; not needed for the join itself).
certSha256Thumbprint() hex uppercase, for x5t#S256 + UI display.
- shared/DeviceStore.{h,cpp}: sibling of SessionPersistence. Stores
{deviceId, tenantId, displayName, thumbprint, joinedAt,
privateKeyPem, deviceCertPem, transportKeyPem}. Private key +
cert bytes are AES-256-GCM encrypted at rest via CryptoHelper,
keyed by the same machine-derived default password. File:
data/device_certs.dat.
- client/DeviceJoinWindow.{h,cpp} (Persistence menu): inherits
EnumerationWindowBase. Operator pastes a DRS-audience token
(client-id 01cb2876-7ebd-4aa4-9cc9-d28bd4d359a9, resource
urn:ms-drs:enterpriseregistration.windows.net), fills device
details, submits. On success renders deviceId + thumbprint, adds
a row to the stored table. Per-row: export cert PEM (public),
export private key PEM (red confirm dialog), remove local record.
- Wired at Persistence menu between "Auth Methods" and "Windows
Hello Attack". No CMake changes - both new .cpp files live in
shared/ which globs *.cpp; OpenSSL is already linked PUBLIC
through shared and transitively available in client.
62 lines
2.2 KiB
C++
62 lines
2.2 KiB
C++
#ifndef DEVICESTORE_H
|
|
#define DEVICESTORE_H
|
|
|
|
#include <QByteArray>
|
|
#include <QDateTime>
|
|
#include <QList>
|
|
#include <QString>
|
|
|
|
// DeviceStore - encrypted on-disk store for registered Entra devices.
|
|
//
|
|
// Sibling of SessionPersistence (**[4.2]**) that saves the material we
|
|
// obtained from a successful DRS join: the RSA private key that signed
|
|
// the CSR, the returned device X.509 cert, the deviceId + tenantId
|
|
// they're bound to, and metadata for later PRT-mint.
|
|
//
|
|
// All fields except the metadata are encrypted at rest via CryptoHelper
|
|
// (AES-256-GCM), keyed by the same machine-derived default password
|
|
// SessionPersistence uses (overridable via setEncryptionKey).
|
|
//
|
|
// Storage lives at `data/device_certs.dat` alongside `saved_sessions.dat`.
|
|
class DeviceStore {
|
|
public:
|
|
struct Device {
|
|
QString deviceId; // Entra deviceId (returned by DRS)
|
|
QString tenantId; // TenantID the device is joined to
|
|
QString displayName; // User-provided name shown in the portal
|
|
QString certThumbprint; // SHA256 hex, UPPER (from DeviceCryptoHelper)
|
|
QDateTime joinedAt; // When the join succeeded
|
|
QByteArray privateKeyPem; // Encrypted at rest; RSA that signed the CSR
|
|
QByteArray deviceCertPem; // Encrypted at rest; signed X.509 from DRS
|
|
QByteArray transportKeyPem; // Optional: private key of the transport pair
|
|
};
|
|
|
|
static DeviceStore& instance();
|
|
|
|
// Persist / retrieve.
|
|
bool saveDevice(const Device &d);
|
|
bool removeDevice(const QString &deviceId);
|
|
QList<Device> loadDevices();
|
|
Device findByDeviceId(const QString &deviceId);
|
|
bool clearAll();
|
|
|
|
// Same encryption-key contract as SessionPersistence.
|
|
void setEncryptionKey(const QString &key);
|
|
bool hasEncryptionKey() const;
|
|
|
|
private:
|
|
DeviceStore();
|
|
~DeviceStore() = default;
|
|
|
|
QString m_encryptionKey;
|
|
QString m_storagePath;
|
|
|
|
QString encrypt(const QByteArray &plaintext) const; // base64(JSON envelope)
|
|
QByteArray decrypt(const QString &ciphertext) const; // empty on failure
|
|
|
|
bool saveToFile(const QList<Device> &devices);
|
|
QList<Device> loadFromFile();
|
|
};
|
|
|
|
#endif // DEVICESTORE_H
|