#pragma once // ── İmzalı lisans dosyası (.fkl) — Dalga 2 ────────────────────────────────── // Satır tabanlı "anahtar=değer" metni; SON satır imza. İmzalanan gövde = "imza=" // satırı HARİÇ tüm metin (CR temizlenmiş). Doğrulama ECDSA P-256 (fiko::kripto). // Politika LisansSistemi'ne aktarılır — gate mantığı ORADA, burada yalnız veri. // // Node-lock TOLERANSLI: lisansta N adet "makine=" satırı (SMBIOS/disk/CPU/ // MachineGuid gibi bağımsız alanların hash'i); yerelde hesaplananlarla en az // `makineTolerans` tanesi eşleşirse geçer. Böylece RAM/disk değişimi müşteriyi // kilitlemez (destek yükünün en büyük kalemi). #include #include #include #include #include "fiko/cekirdek/lisans.hpp" namespace fiko { // ---- Kota dönemi: sayaç ne zaman sıfırlanır ---- // Toplam = ömür boyu (sıfırlanmaz). Diğerleri takvim penceresi: pencere değişince // sayaç sıfırlanır ve kullanıcı hakkını yeniden kazanır — ama paket/lisans bitişi // geldiyse hak zaten kapanmıştır (kota bitişi AŞAMAZ). enum class KotaDonem : u8 { Toplam = 0, Gun, Hafta, Ay, Yil }; const char* kotaDonemAdi(KotaDonem d); KotaDonem kotaDonemCoz(std::string_view s); // "gun"/"hafta"/"ay"/"yil"/"" → enum // ---- Serbest periyot ---- // Sabit dönem enum'u yetmez: "5 saatte 5 kullanım" gibi kısa pencereler ve // "haftada 30" gibi uzun pencereler AYNI komuta aynı anda uygulanabilmeli // (birden çok kota kuralı → hepsi ayrı kova, hepsi sağlanmalı). // // Metin: "" — birim: sn|dk|saat|gun|hafta|ay|yil (sayı yoksa 1). // "5saat" → 18000 · "30dk" → 1800 · "hafta" → 604800 · "" / "toplam" → 0 (ömür boyu) // Pencere ANKRAJLIDIR: ilk kullanımda başlar, periyot dolunca sıfırlanır // (takvim bloğu değil — kullanıcının beklediği "kullanmaya başlayınca sayaç işler"). u32 kotaPeriyotCoz(std::string_view s); std::string kotaPeriyotMetni(u32 saniye); // 18000 → "5 saat", 0 → "ömür boyu" struct LisansKota { std::string kimlik; // komut kimliği veya joker ("cam.gkod", "cam.*") u64 limit = 0; // 0 = sınırsız u32 periyot = 0; // saniye; 0 = ömür boyu toplam }; // Satış paketi: komut kümesi + kendi bitişi + kendi kotaları. Aynı lisansta farklı // bitişli/kotalı paketler yaşayabilir (ör. "Modelleme yıllık" + "CAM 100 çıktı/ay"). struct LisansPaket { std::string kimlik, ad; i64 bitis = 0; // 0 = paket süresiz (lisans geneli `bitis` yine geçerlidir) std::vector komutlar; std::vector kotalar; }; struct LisansBilgi { std::string musteri, seri, urun, seviye; std::vector gruplar, featureler, workbenchler; // Komut-bazlı satış: satın alınan komut kimlikleri ("geometri.kutu", "cam.*", "*"). // Boş = komut gate'i uygulanmaz (paket/grup bazlı eski lisanslar çalışmaya devam eder). std::vector komutlar; std::vector kotalar; // paketsiz (global) kotalar std::vector paketler; // satış paketleri std::vector makineHashleri; // node-lock adayları (boş = kontrol yok) int makineTolerans = 3; i64 bitis = 0; // unix saniye; 0 = süresiz bool kisitli = true; // LisansSistemi::Kip::Kisitli // Yapı kilidi: dolu ise çalışan exe'nin sha256'sı buna eşit olmalı (yamalı exe // reddedilir). Boş = sürümden bağımsız lisans (güncelleme sonrası da çalışır). std::string yapiHash; }; enum class LisansDurum : u8 { Gecerli = 0, Bos, // dosya boş/okunamadı Bicim, // zorunlu alan eksik / bozuk satır ImzaYok, // imza satırı yok ImzaGecersiz, // imza doğrulanamadı (kurcalanmış) UrunFarkli, // başka ürünün lisansı SuresiDolmus, MakineUyusmaz, YapiUyusmaz, // exe sha256'sı lisanstaki `yapi=` ile tutmuyor (yamalı ikili) UzaktanEngellendi // satıcının imzalı uzak politikası bu seriyi engelliyor — enum SONU }; const char* lisansDurumMetni(LisansDurum d); // İmzalanan KANONİK gövde: UTF-8 BOM atılır, satırlar kırpılır, yorum (#) ve boş // satırlar düşer, "imza=" satırı dışlanır, her alan "anahtar=deger\n" olarak yazılır. // İmzalayan araç ile doğrulayan uygulama AYNI dizgeyi görsün diye tek merkez — // müşterinin dosyayı Notepad'de açıp CRLF/BOM eklemesi imzayı bozmaz. std::string lisansKanonikGovde(std::string_view metin); // ── Zarf (gizlilik) katmanı ───────────────────────────────────────────────── // .fkl içeriği İMZALI ama düz metindi: müşteri Notepad'de açıp hangi komutları // aldığını, kotalarını, makine hash'lerini okuyabiliyordu. Zarf bunu gizler. // Biçim: "FKLE1\n" satırı + base64(AES-256-GCM zarfı) — tamamı ASCII, e-posta ile // gönderilebilir. GİZLİLİK katmanıdır, GÜVENLİK değil: güven ECDSA imzasından gelir. std::string lisansZarfla(std::string_view duzGovdeVeImza, const u8 anahtar[32]); // Zarfı açar. İçerik "FKLE1" ile BAŞLAMIYORSA olduğu gibi döner → eski düz metin // lisanslar çalışmaya devam eder (geriye uyum). Zarflı ama çözülemiyorsa "" döner // (bozuk/yanlış anahtar; çağıran LisansDurum::Bos görür). std::string lisansZarfCoz(std::string_view dosyaIcerigi, const u8 anahtar[32]); // Ortak simetrik anahtar türeticisi (üretici CLI ve uygulama AYNI anahtarı görsün). void lisansZarfAnahtari(u8 out[32]); // Metni ayrıştır + imzayı doğrula. Süre/makine kontrolü YAPILMAZ (bunlar // lisansUygula/LisansSistemi'nin işi) — burada yalnız bütünlük + biçim. LisansDurum lisansCoz(std::string_view metin, std::string_view acikAnahtarHex, LisansBilgi& out, std::string& hata); // Politikayı LisansSistemi'ne aktar. yerelMakineHashleri boşsa node-lock uygulanmaz. // Dönüş: Gecerli / SuresiDolmus / MakineUyusmaz (uygulama yine de yapılır; gate reddeder). // birlestir=true → politika SIFIRLANMAZ, mevcut hakların ÜSTÜNE eklenir (çoklu lisans: // müşteri sonradan paket alınca ikinci .fkl dosyası ilkini bozmaz). Birleştirmede // GENİŞ olan kazanır: herhangi biri serbest kipse serbest, bitiş süresizse süresiz. LisansDurum lisansUygula(const LisansBilgi& l, LisansSistemi& sis, const std::vector& yerelMakineHashleri, i64 suan, bool birlestir = false); // Fiyatlandırma kataloğu: kayıtlı TÜM komutlar → CSV (kimlik;grup;ad;workbench;altGrup;fiyat). // `fiyat` sütunu boş üretilir — sen doldurursun, lisans üretici bu tablodan `komut=` satırı // kurar. Kimliksiz komutlar "Grup/Ad" fallback'i ile listelenir (kimlik vermen için uyarı). std::string lisansKatalogCsv(const MenuKaydi& menuler); } // namespace fiko