open Asn1PTypes
open Asn1Engine
open Padata
open KerberosTypes


(* NOT USED *)
enum padata_type (8, UnknownVal UnknownPreAuthenticationType) =
  | 1 -> PA_TGS_REQ
  | 2 -> PA_ENC_TIMESTAMP
  NOT   !
  | 11 -> PA_ETYPE_INFO
  | 16 -> PA_PK_AS_REQ
  | 17 -> PA_PK_AS_REP
  | 18 -> PA_ETYPE_INFO_UNUSUED
  | 19 -> PA_ETYPE_INFO2

(*
asn1_alias padata_value
*)

  Tentative pour utiliser l'enum padata_type

 let parse_asn1_enum parse_fun input = 
   let v = parse_der_integer input in 
   let new_input = input_of_string " asn1_enum " v in 
   parse_fun new_input 

 let dump_asn1_enum _ dump_fun _ buf _ enum = raise ( ParsingException ( NotImplemented " dump_asn1_enum " , [ ] ) ) 

let parse_asn1_enum parse_fun input =
  let v = parse_der_integer input in
  let new_input = input_of_string "asn1_enum" v in
  parse_fun new_input

let dump_asn1_enum _dump_fun _buf _enum = raise (ParsingException (NotImplemented "dump_asn1_enum", []))
*)

struct padata_content =
{

   padata_type : cspe [ 1 ] of asn1 [ ( C_Universal , false , T_Integer ) ] of padata_type ; ( * WRONG because type may be > 128
  padata_type : cspe [1] of asn1 [(C_Universal, false, T_Integer)] of padata_type; (* WRONG because type may be > 128 *)
  WRONG because it is 4 bytes long
  *)
  (* We stick with der_smallint for now *)
  padata_type : cspe [1] of der_smallint;
  optional padata_value : cspe [2] of octetstring_container of padata_value(padata_type, true)
}
asn1_alias padata
asn1_alias padatas = seq_of padata

struct err_padata_content =
{
  (* We stick with der_smallint for now *)
  padata_type :  cspe[1] of der_smallint;
  (* Passing "false" to discriminate the error_msg case where padata_value will be NULL *)
  optional padata_value : cspe [2] of octetstring_container of padata_value(padata_type, false)
}
asn1_alias err_padata
asn1_alias err_padatas = seq_of err_padata

(* FIXME !!
asn1_alias etypes = seq_of asn1 [(C_Universal, false, T_Integer)] of etype_type
*)
asn1_alias etypes = seq_of der_integer

struct req_body_content =
{
  kdc_options: 		cspe [0] of der_enumerated_bitstring[kdc_options_values];
  PrincipalName , Used only in AS - REQ
  realm : 		cspe [2] of der_kerberos_string; 	(* Realm *)
  PrincipalName OPTIONAL ,
  KerberosTime OPTIONAL ,
  KerberosTime
  KerberosTime OPTIONAL ,
  UInt32
  SEQUENCE OF Int32   -- EncryptionType
  HostAddresses OPTIONAL ,
  EncryptedData OPTIONAL
  optional additional_tickets: 		cspe [11] of der_object		(* SEQUENCE OF Ticket OPTIONAL *)
}
asn1_alias req_body

asn1_struct enc_kdc_rep_part = {
  key : 		cspe [0] of encryption_key;
  last_req : 		cspe [1] of binstring;
  nonce : 		cspe [2] of der_smallint;
  optional key_expiration : 	cspe [3] of der_kerberos_time;
  flags : 		cspe [4] of binstring;
  authtime: 		cspe [5] of der_kerberos_time;
  optional starttime : 	cspe [6] of der_kerberos_time;
  endtime : 		cspe [7] of der_kerberos_time;
  optional renew_till :	cspe [8] of der_kerberos_time;
  srealm : 		cspe [9] of der_kerberos_string;
  sname : 		cspe [10] of sname;
  optional caddr :      cspe [11] of binstring;
  reste_FIXME : cspe [12] of binstring
(*
*)
}

(* AP_REQ *)
  defined in PADATA , because it can be used in 

(* AP_REP *)
asn1_struct ap_rep =
{
  pvno : 	cspe [0] of asn1 [(C_Universal, false, T_Integer)] of pvno;
  msg_type : 	cspe [1] of asn1 [(C_Universal, false, T_Integer)] of msg_type;
  enc_part : 	cspe [2] of encrypted_data (0; None);
}

  
asn1_struct as_req =
{
  pvno : 	cspe [1] of asn1 [(C_Universal, false, T_Integer)] of pvno;
  msg_type : 	cspe [2] of asn1 [(C_Universal, false, T_Integer)] of msg_type;
  optional padata : cspe [3] of padatas;
  req_body : 	cspe [4] of req_body;
}

(* AS_REP *)
asn1_struct as_rep =
{
  pvno : 	cspe [0] of asn1 [(C_Universal, false, T_Integer)] of pvno;
  msg_type : 	cspe [1] of asn1 [(C_Universal, false, T_Integer)] of msg_type;
  optional padata : cspe [2] of padatas;
  crealm : 	cspe [3] of der_kerberos_string;
  cname : 	cspe [4] of cname;
  ticket : 	cspe [5] of asn1 [(C_Application, true, T_Unknown 1)] of ticket (None);
  enc_part : 	cspe [6] of encrypted_data_container (3; !KerberosTypes.global_session_key) of asn1 [(C_Application, true, T_Unknown 26)] of enc_kdc_rep_part;
}

(* KRB_ERR *)
asn1_struct krb_error = {
  pvno : 	cspe [0] of asn1 [(C_Universal, false, T_Integer)] of pvno;
  msg_type : 	cspe [1] of asn1 [(C_Universal, false, T_Integer)] of msg_type;
  optional ctime : 	cspe [2] of der_kerberos_time;
  optional cusec : 	cspe [3] of binstring;
  stime : 	cspe [4] of der_kerberos_time;
  optional susec : 	cspe [5] of binstring;
  error_code : 	cspe [6] of der_smallint;
  optional crealm : 	cspe [7] of der_kerberos_string;
  optional cname : 	cspe [8] of cname;
  realm : 	cspe [9] of der_kerberos_string;
  sname : 	cspe [10] of sname;
  optional e_text : 	cspe [11] of der_kerberos_string;
  optional e_data : 	cspe [12] of octetstring_container of err_padatas
}

asn1_union kerberos_msg_type [enrich] (UnparsedKerberosMessage ) =
  | (C_Application, true, T_Unknown 10) -> AS_REQ of as_req
  | (C_Application, true, T_Unknown 11) -> AS_REP of as_rep
  | (C_Application, true, T_Unknown 12) -> TGS_REQ of as_req
  | (C_Application, true, T_Unknown 13) -> TGS_REP of as_rep
  | (C_Application, true, T_Unknown 14) -> AP_REQ of ap_req(11) (* 11 is the classic krb5_keyusage value *)
  | (C_Application, true, T_Unknown 15) -> AP_REP of ap_rep
  | (C_Application, true, T_Unknown 30) -> KRB_ERR of krb_error

struct kerberos_msg = 
{
  record_mark : binstring(4);
  msg_content : kerberos_msg_type;
}

alias kerberos_udp_msg = kerberos_msg_type

 NOT USED 

asn1_alias padata_value

 WRONG because type may be > 128 
 We stick with der_smallint for now 
 We stick with der_smallint for now 
 Passing "false" to discriminate the error_msg case where padata_value will be NULL 
 FIXME !!
asn1_alias etypes = seq_of asn1 [(C_Universal, false, T_Integer)] of etype_type

 Realm 
 SEQUENCE OF Ticket OPTIONAL 


 AP_REQ 
 AP_REP 
 AS_REP 
 KRB_ERR 
 11 is the classic krb5_keyusage value 
open Asn1PTypes
open Asn1Engine
open Padata
open KerberosTypes


enum padata_type (8, UnknownVal UnknownPreAuthenticationType) =
  | 1 -> PA_TGS_REQ
  | 2 -> PA_ENC_TIMESTAMP
  NOT   !
  | 11 -> PA_ETYPE_INFO
  | 16 -> PA_PK_AS_REQ
  | 17 -> PA_PK_AS_REP
  | 18 -> PA_ETYPE_INFO_UNUSUED
  | 19 -> PA_ETYPE_INFO2


  Tentative pour utiliser l'enum padata_type

 let parse_asn1_enum parse_fun input = 
   let v = parse_der_integer input in 
   let new_input = input_of_string " asn1_enum " v in 
   parse_fun new_input 

 let dump_asn1_enum _ dump_fun _ buf _ enum = raise ( ParsingException ( NotImplemented " dump_asn1_enum " , [ ] ) ) 

let parse_asn1_enum parse_fun input =
  let v = parse_der_integer input in
  let new_input = input_of_string "asn1_enum" v in
  parse_fun new_input

let dump_asn1_enum _dump_fun _buf _enum = raise (ParsingException (NotImplemented "dump_asn1_enum", []))
*)

struct padata_content =
{

   padata_type : cspe [ 1 ] of asn1 [ ( C_Universal , false , T_Integer ) ] of padata_type ; ( * WRONG because type may be > 128
  WRONG because it is 4 bytes long
  *)
  padata_type : cspe [1] of der_smallint;
  optional padata_value : cspe [2] of octetstring_container of padata_value(padata_type, true)
}
asn1_alias padata
asn1_alias padatas = seq_of padata

struct err_padata_content =
{
  padata_type :  cspe[1] of der_smallint;
  optional padata_value : cspe [2] of octetstring_container of padata_value(padata_type, false)
}
asn1_alias err_padata
asn1_alias err_padatas = seq_of err_padata

asn1_alias etypes = seq_of der_integer

struct req_body_content =
{
  kdc_options: 		cspe [0] of der_enumerated_bitstring[kdc_options_values];
  PrincipalName , Used only in AS - REQ
  PrincipalName OPTIONAL ,
  KerberosTime OPTIONAL ,
  KerberosTime
  KerberosTime OPTIONAL ,
  UInt32
  SEQUENCE OF Int32   -- EncryptionType
  HostAddresses OPTIONAL ,
  EncryptedData OPTIONAL
}
asn1_alias req_body

asn1_struct enc_kdc_rep_part = {
  key : 		cspe [0] of encryption_key;
  last_req : 		cspe [1] of binstring;
  nonce : 		cspe [2] of der_smallint;
  optional key_expiration : 	cspe [3] of der_kerberos_time;
  flags : 		cspe [4] of binstring;
  authtime: 		cspe [5] of der_kerberos_time;
  optional starttime : 	cspe [6] of der_kerberos_time;
  endtime : 		cspe [7] of der_kerberos_time;
  optional renew_till :	cspe [8] of der_kerberos_time;
  srealm : 		cspe [9] of der_kerberos_string;
  sname : 		cspe [10] of sname;
  optional caddr :      cspe [11] of binstring;
  reste_FIXME : cspe [12] of binstring
}

  defined in PADATA , because it can be used in 

asn1_struct ap_rep =
{
  pvno : 	cspe [0] of asn1 [(C_Universal, false, T_Integer)] of pvno;
  msg_type : 	cspe [1] of asn1 [(C_Universal, false, T_Integer)] of msg_type;
  enc_part : 	cspe [2] of encrypted_data (0; None);
}

  
asn1_struct as_req =
{
  pvno : 	cspe [1] of asn1 [(C_Universal, false, T_Integer)] of pvno;
  msg_type : 	cspe [2] of asn1 [(C_Universal, false, T_Integer)] of msg_type;
  optional padata : cspe [3] of padatas;
  req_body : 	cspe [4] of req_body;
}

asn1_struct as_rep =
{
  pvno : 	cspe [0] of asn1 [(C_Universal, false, T_Integer)] of pvno;
  msg_type : 	cspe [1] of asn1 [(C_Universal, false, T_Integer)] of msg_type;
  optional padata : cspe [2] of padatas;
  crealm : 	cspe [3] of der_kerberos_string;
  cname : 	cspe [4] of cname;
  ticket : 	cspe [5] of asn1 [(C_Application, true, T_Unknown 1)] of ticket (None);
  enc_part : 	cspe [6] of encrypted_data_container (3; !KerberosTypes.global_session_key) of asn1 [(C_Application, true, T_Unknown 26)] of enc_kdc_rep_part;
}

asn1_struct krb_error = {
  pvno : 	cspe [0] of asn1 [(C_Universal, false, T_Integer)] of pvno;
  msg_type : 	cspe [1] of asn1 [(C_Universal, false, T_Integer)] of msg_type;
  optional ctime : 	cspe [2] of der_kerberos_time;
  optional cusec : 	cspe [3] of binstring;
  stime : 	cspe [4] of der_kerberos_time;
  optional susec : 	cspe [5] of binstring;
  error_code : 	cspe [6] of der_smallint;
  optional crealm : 	cspe [7] of der_kerberos_string;
  optional cname : 	cspe [8] of cname;
  realm : 	cspe [9] of der_kerberos_string;
  sname : 	cspe [10] of sname;
  optional e_text : 	cspe [11] of der_kerberos_string;
  optional e_data : 	cspe [12] of octetstring_container of err_padatas
}

asn1_union kerberos_msg_type [enrich] (UnparsedKerberosMessage ) =
  | (C_Application, true, T_Unknown 10) -> AS_REQ of as_req
  | (C_Application, true, T_Unknown 11) -> AS_REP of as_rep
  | (C_Application, true, T_Unknown 12) -> TGS_REQ of as_req
  | (C_Application, true, T_Unknown 13) -> TGS_REP of as_rep
  | (C_Application, true, T_Unknown 15) -> AP_REP of ap_rep
  | (C_Application, true, T_Unknown 30) -> KRB_ERR of krb_error

struct kerberos_msg = 
{
  record_mark : binstring(4);
  msg_content : kerberos_msg_type;
}

alias kerberos_udp_msg = kerberos_msg_type
