package krb

  1. Overview
  2. Docs
A library for using Kerberos for both Rpc and Tcp communication

Install

Dune Dependency

Authors

Maintainers

Sources

krb-v0.15.0.tar.gz
sha256=d0b4b946f4e53dff9091d2d02a235e861ab5ad9d64638b17ba1834dedfb4f53d

doc/src/krb.internal/config_gen.ml.html

Source file config_gen.ml

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
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
open! Core
include Config_gen_intf

module Shared = struct
  type t =
    { pre_v5_assumed_realm : string option [@sexp.option]
    ; host_keytab_path : string option [@sexp.option]
    ; user_keytab_dir_template : string option [@sexp.option]
    ; default_domain : string option option [@sexp.option]
    ; debug_log_config : Debug_log_config.Stable.V1.t option [@sexp.option]
    ; verbose_errors : bool option [@sexp.option]
    ; am_sandboxed : bool option [@sexp.option]
    }
  [@@deriving fields, sexp]

  let environment_variable = "OCAML_KRB_CONFIG"
  let username_template = "%{username}"
end

include Shared

module type S = S with type t = t

let make ~default ~help_message =
  (module struct
    include Shared

    let field_descriptions () =
      let field to_sexp description ac field =
        let sexp =
          Option.value_map
            ~default:(Sexp.Atom "<unspecified>")
            (Field.get field default)
            ~f:to_sexp
        in
        (Field.name field, sexp, description) :: ac
      in
      let fields =
        Fields.fold
          ~init:[]
          ~pre_v5_assumed_realm:
            (field
               [%sexp_of: string]
               [ "\n\
                  When using Protocol V4 and below, clients don't know the realm of \
                  their peer and assume they are in [pre_v5_assumed_realm]. Protocol V5 \
                  added support for cross-realm authentication and started sending the \
                  realm as part of the handshake."
               ])
          ~host_keytab_path:
            (field
               [%sexp_of: string]
               [ "\n  The path of a keytab specified by [Keytab.Path.Host].\n" ])
          ~user_keytab_dir_template:
            (field
               [%sexp_of: string]
               [ sprintf
                   "\n\
                   \  The path of a keytab specified by [Keytab.Path.User] is determined \
                    by\n\
                   \  [filled in user_keytab_dir_template]/$USER.keytab.\n\
                   \  This must be an absolute path with the substring %s, which will be\n\
                   \  be filled in with the currently running user.\n"
                   username_template
               ])
          ~default_domain:
            (field
               [%sexp_of: string option]
               [ "\n\
                 \  The default domain name of hosts in this realm. This value will be \
                  used to fully qualify hostnames when constructing service principals.\n\n"
               ])
          ~debug_log_config:
            (field
               [%sexp_of: Debug_log_config.Stable.V1.t]
               [ sprintf
                   "\n\
                   \  Print library debugging information to the outputs specified. The \
                    following\n\
                   \  are some example configs:\n\
                   \  %s\n\
                   \ "
                   (List.map
                      Debug_log_config.examples
                      ~f:Debug_log_config.Stable.V1.sexp_of_t
                    |> List.map ~f:Sexp.to_string
                    |> String.concat ~sep:"\n  ")
               ])
          ~verbose_errors:
            (field [%sexp_of: bool] [ "\n  Whether error messages should be verbose.\n" ])
          (* Purposefully undocumented; this should only be set by the kerberos sandbox. *)
          ~am_sandboxed:(fun acc _ -> acc)
      in
      String.concat
        (List.map
           (List.sort fields ~compare:(fun (name1, _, _) (name2, _, _) ->
              String.compare name1 name2))
           ~f:(fun (name, default, description) ->
             String.concat
               ("\n"
                :: name
                :: " (default "
                :: Sexp.to_string default
                :: ")"
                :: description)))
    ;;

    let help_message () =
      let field_descriptions = field_descriptions () in
      help_message ~default ~environment_variable ~field_descriptions
    ;;

    let usage () =
      eprintf "%s%!" (help_message ());
      exit 1
    ;;

    let t =
      match Sys.getenv environment_variable with
      | None -> default
      | Some "" -> usage ()
      | Some string ->
        (match Result.try_with (fun () -> t_of_sexp (Sexp.of_string string)) with
         | Ok t -> t
         | Error exn ->
           eprintf
             "%s\n\n"
             (Sexp.to_string_hum
                (Error.sexp_of_t
                   (Error.create
                      (sprintf
                         "invalid value for %s environment variable"
                         environment_variable)
                      exn
                      [%sexp_of: exn])));
           usage ())
    ;;

    let get_with_default field =
      match Option.first_some (Field.get field t) (Field.get field default) with
      | None ->
        failwithf
          "The Kerberos configuration is missing a required field (%s).\n\
           Pass the environment variable as described or modify the Config module.\n\n\
           ===============================================================\n\n\
           %s"
          (Field.name field)
          (help_message ())
          ()
      | Some value -> value
    ;;

    let validate_user_keytab_dir_template x =
      let template_occurences =
        List.length
          (String.substr_index_all x ~may_overlap:false ~pattern:username_template)
      in
      if not (template_occurences = 1 && Filename.is_absolute x)
      then
        failwithf
          "[user_keytab_dir_template] must be an absolute path with the template %s"
          username_template
          ()
    ;;

    let pre_v5_assumed_realm = get_with_default Fields.pre_v5_assumed_realm
    let host_keytab_path = get_with_default Fields.host_keytab_path

    let user_keytab_dir_template =
      let x = get_with_default Fields.user_keytab_dir_template in
      validate_user_keytab_dir_template x;
      x
    ;;

    let user_keytab_dir ~username =
      String.substr_replace_all
        user_keytab_dir_template
        ~pattern:username_template
        ~with_:username
    ;;

    let default_domain = get_with_default Fields.default_domain
    let debug_log_config = get_with_default Fields.debug_log_config
    let verbose_errors = get_with_default Fields.verbose_errors
    let am_sandboxed = get_with_default Fields.am_sandboxed
    let print_debug_messages = List.length debug_log_config > 0

    let t =
      { pre_v5_assumed_realm = Some pre_v5_assumed_realm
      ; host_keytab_path = Some host_keytab_path
      ; user_keytab_dir_template = Some user_keytab_dir_template
      ; default_domain = Some default_domain
      ; debug_log_config = Some debug_log_config
      ; verbose_errors = Some verbose_errors
      ; am_sandboxed = Some am_sandboxed
      }
    ;;
  end : S)
;;
OCaml

Innovation. Community. Security.