Skip to content
This repository
tag: v1669
Fetching contributors…

Cannot retrieve contributors at this time

file 143 lines (128 sloc) 5.357 kb
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143
(*
Copyright © 2011 MLstate

This file is part of OPA.

OPA is free software: you can redistribute it and/or modify it under the
terms of the GNU Affero General Public License, version 3, as published by
the Free Software Foundation.

OPA is distributed in the hope that it will be useful, but WITHOUT ANY
WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS
FOR A PARTICULAR PURPOSE. See the GNU Affero General Public License for
more details.

You should have received a copy of the GNU Affero General Public License
along with OPA. If not, see <http://www.gnu.org/licenses/>.
*)
module CL = CryptoLib
module C = Cryptokit

type license_version = int
type license_id = string
type customer_info_data = string StringMap.t
type product_bool_info_data = bool StringMap.t
type product_int_info_data = int StringMap.t
type license = { (* 'a license ? *)
  license_version : license_version;
  license_id : license_id;
  customer_info_data : customer_info_data;
  product_bool_info_data : product_bool_info_data;
  product_int_info_data : product_int_info_data;
  license_signature : string;
}

exception InvalidLicense

let get_customer_info license_opt key default = try
  let license = Option.get license_opt in
  StringMap.find key license.customer_info_data
with Failure "Option.get" | Not_found -> default

let get_product_bool_info license_opt key default = try
  let license = Option.get license_opt in
  StringMap.find key license.product_bool_info_data
with Failure "Option.get" | Not_found -> default

let get_product_int_info license_opt key default = try
  let license = Option.get license_opt in
  StringMap.find key license.product_int_info_data
with Failure "Option.get" | Not_found -> default

let make_license license_version license_id customer_info_data product_bool_info_data product_int_info_data signature = {
  license_version = license_version;
  license_id = license_id;
  customer_info_data = customer_info_data;
  product_bool_info_data = product_bool_info_data;
  product_int_info_data = product_int_info_data;
  license_signature = signature;
}

let serialize_license license =
  let ci_data = StringMap.fold (
    fun k v acc ->
      Printf.sprintf "%s=%s,%s" k (CryptoLib.to_base64 v) acc
  ) license.customer_info_data "" in
  let pbi_data = StringMap.fold (
    fun k v acc ->
      Printf.sprintf "%s=%s,%s" k (string_of_bool v) acc
  ) license.product_bool_info_data "" in
  let pii_data = StringMap.fold (
    fun k v acc ->
      Printf.sprintf "%s=%s,%s" k (string_of_int v) acc
  ) license.product_int_info_data "" in
  let data = Printf.sprintf "%d;%s;%s;%s;%s" license.license_version license.license_id ci_data pbi_data pii_data in
  data

let sign_serialized_license data sym_key rsa_sig_privkey=
  let to_sign = CL.hash data in
  let signature = CL.to_hex (CL.sign rsa_sig_privkey to_sign) in
  let final = Printf.sprintf "%s\n%s" data signature in
  CL.to_base64_m (CL.symetric_encrypt (CL.from_hex sym_key) final)

let check_license_data license_data sym_key rsa_sig_pubkey = try
  let license_content = CL.symetric_decrypt (CL.from_hex sym_key) (CL.from_base64 license_data) in
  let p1, p2 =
    let l = Base.String.slice '\n' license_content in
    if List.length l = 2 then
      let p1 = List.nth l 0
      and p2 = List.nth l 1 in
      p1, p2
    else raise InvalidLicense in
  if CL.hash p1 = Base.String.ltrim ~is_space:((=) '\000') (CL.unsign rsa_sig_pubkey (CL.from_hex p2)) then Some (p1, p2)
  else None
with C.Error _ | InvalidLicense -> None

let recover_license serialized_license signature =
  let l = Base.String.slice ';' serialized_license in
  if List.length l = 5 then
    let lv = List.nth l 0
    and lid = List.nth l 1
    and ci = List.nth l 2
    and pbi = List.nth l 3
    and pii = List.nth l 4 in
    let cl = Base.String.slice ',' ci
    and pbl = Base.String.slice ',' pbi
    and pil = Base.String.slice ',' pii in
    let customer_info_data =
      List.fold_left (
        fun acc elt ->
          let kv = Base.String.slice '=' elt in
          let k = List.nth kv 0
          and v = (CryptoLib.from_base64 (List.nth kv 1)) in
          StringMap.add k v acc
      ) StringMap.empty cl
    and product_bool_info_data =
      List.fold_left (
        fun acc elt ->
          let kv = Base.String.slice '=' elt in
          let k = List.nth kv 0
          and v = List.nth kv 1 in
          StringMap.add k (bool_of_string v) acc
      ) StringMap.empty pbl
    and product_int_info_data =
      List.fold_left (
        fun acc elt ->
          let kv = Base.String.slice '=' elt in
          let k = List.nth kv 0
          and v = List.nth kv 1 in
          StringMap.add k (int_of_string v) acc
      ) StringMap.empty pil in
    make_license (int_of_string lv) lid customer_info_data product_bool_info_data product_int_info_data signature
  else raise InvalidLicense

let system_uuid () = try
  let sysprof = "/usr/sbin/system_profiler" in
  if Sys.file_exists sysprof then
    let ic = Unix.open_process_in (Printf.sprintf "%s -detailLevel full SPHardwareDataType | grep UUID" sysprof) in
    let huuid = input_line ic in
    let l = Base.String.slice ':' huuid in
    let uuid = Base.String.trim (List.nth l 1) in
    uuid
  else ""
with End_of_file | Invalid_argument "List.nth" | Failure "nth" -> ""
Something went wrong with that request. Please try again.