s4:heimdal: import lorikeet-heimdal-202201172009 (commit 5a0b45cd723628b3690ea848548b...
[samba.git] / source4 / heimdal / kdc / windc.c
1 /*
2  * Copyright (c) 2007 Kungliga Tekniska Högskolan
3  * (Royal Institute of Technology, Stockholm, Sweden).
4  * All rights reserved.
5  *
6  * Redistribution and use in source and binary forms, with or without
7  * modification, are permitted provided that the following conditions
8  * are met:
9  *
10  * 1. Redistributions of source code must retain the above copyright
11  *    notice, this list of conditions and the following disclaimer.
12  *
13  * 2. Redistributions in binary form must reproduce the above copyright
14  *    notice, this list of conditions and the following disclaimer in the
15  *    documentation and/or other materials provided with the distribution.
16  *
17  * 3. Neither the name of the Institute nor the names of its contributors
18  *    may be used to endorse or promote products derived from this software
19  *    without specific prior written permission.
20  *
21  * THIS SOFTWARE IS PROVIDED BY THE INSTITUTE AND CONTRIBUTORS ``AS IS'' AND
22  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
23  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
24  * ARE DISCLAIMED.  IN NO EVENT SHALL THE INSTITUTE OR CONTRIBUTORS BE LIABLE
25  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
26  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
27  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
28  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
29  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
30  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
31  * SUCH DAMAGE.
32  */
33
34 #include "kdc_locl.h"
35
36 static int have_plugin = 0;
37
38 /*
39  * Pick the first WINDC module that we find.
40  */
41
42 static const char *windc_plugin_deps[] = {
43     "kdc",
44     "krb5",
45     "hdb",
46     NULL
47 };
48
49 static struct heim_plugin_data windc_plugin_data = {
50     "krb5",
51     "windc",
52     KRB5_WINDC_PLUGIN_MINOR,
53     windc_plugin_deps,
54     kdc_get_instance
55 };
56
57 static krb5_error_code KRB5_LIB_CALL
58 load(krb5_context context, const void *plug, void *plugctx, void *userctx)
59 {
60     have_plugin = 1;
61     return KRB5_PLUGIN_NO_HANDLE;
62 }
63
64 krb5_error_code
65 krb5_kdc_windc_init(krb5_context context)
66 {
67     (void)_krb5_plugin_run_f(context, &windc_plugin_data, 0, NULL, load);
68
69     return 0;
70 }
71
72 struct generate_uc {
73     hdb_entry_ex *client;
74     hdb_entry_ex *server;
75     const krb5_keyblock *reply_key;
76     uint64_t pac_attributes;
77     krb5_pac *pac;
78 };
79
80 static krb5_error_code KRB5_LIB_CALL
81 generate(krb5_context context, const void *plug, void *plugctx, void *userctx)
82 {
83     krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug;
84     struct generate_uc *uc = (struct generate_uc *)userctx;    
85
86     if (ft->pac_generate == NULL)
87         return KRB5_PLUGIN_NO_HANDLE;
88
89     return ft->pac_generate((void *)plug, context,
90                             uc->client,
91                             uc->server,
92                             uc->reply_key,
93                             uc->pac_attributes,
94                             uc->pac);
95 }
96
97
98 krb5_error_code
99 _kdc_pac_generate(krb5_context context,
100                   hdb_entry_ex *client,
101                   hdb_entry_ex *server,
102                   const krb5_keyblock *reply_key,
103                   uint64_t pac_attributes,
104                   krb5_pac *pac)
105 {
106     krb5_error_code ret = 0;
107     struct generate_uc uc;
108
109     *pac = NULL;
110
111     if (krb5_config_get_bool_default(context, NULL, FALSE, "realms",
112                                      client->entry.principal->realm,
113                                      "disable_pac", NULL))
114         return 0;
115
116     if (have_plugin) {
117         uc.client = client;
118         uc.server = server;
119         uc.reply_key = reply_key;
120         uc.pac = pac;
121         uc.pac_attributes = pac_attributes;
122
123         ret = _krb5_plugin_run_f(context, &windc_plugin_data,
124                                  0, &uc, generate);
125         if (ret != KRB5_PLUGIN_NO_HANDLE)
126             return ret;
127         ret = 0;
128     }
129
130     if (*pac == NULL)
131         ret = krb5_pac_init(context, pac);
132
133     return ret;
134 }
135
136 struct verify_uc {
137     krb5_principal client_principal;
138     krb5_principal delegated_proxy_principal;
139     hdb_entry_ex *client;
140     hdb_entry_ex *server;
141     hdb_entry_ex *krbtgt;
142     krb5_pac *pac;
143 };
144
145 static krb5_error_code KRB5_LIB_CALL
146 verify(krb5_context context, const void *plug, void *plugctx, void *userctx)
147 {
148     krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug;
149     struct verify_uc *uc = (struct verify_uc *)userctx;
150     krb5_error_code ret;
151
152     if (ft->pac_verify == NULL)
153         return KRB5_PLUGIN_NO_HANDLE;
154
155     ret = ft->pac_verify((void *)plug, context,
156                          uc->client_principal,
157                          uc->delegated_proxy_principal,
158                          uc->client, uc->server, uc->krbtgt, uc->pac);
159     return ret;
160 }
161
162 krb5_error_code
163 _kdc_pac_verify(krb5_context context,
164                 const krb5_principal client_principal,
165                 const krb5_principal delegated_proxy_principal,
166                 hdb_entry_ex *client,
167                 hdb_entry_ex *server,
168                 hdb_entry_ex *krbtgt,
169                 krb5_pac *pac)
170 {
171     struct verify_uc uc;
172
173     if (!have_plugin)
174         return KRB5_PLUGIN_NO_HANDLE;
175
176     uc.client_principal = client_principal;
177     uc.delegated_proxy_principal = delegated_proxy_principal;
178     uc.client = client;
179     uc.server = server;
180     uc.krbtgt = krbtgt;
181     uc.pac = pac;
182
183     return _krb5_plugin_run_f(context, &windc_plugin_data,
184                              0, &uc, verify);
185 }
186
187 static krb5_error_code KRB5_LIB_CALL
188 check(krb5_context context, const void *plug, void *plugctx, void *userctx)
189 {
190     krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug;
191
192     if (ft->client_access == NULL)
193         return KRB5_PLUGIN_NO_HANDLE;
194     return ft->client_access((void *)plug, userctx);
195 }
196
197 krb5_error_code
198 _kdc_check_access(astgs_request_t r)
199 {
200     krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
201
202     if (have_plugin) {
203         ret = _krb5_plugin_run_f(r->context, &windc_plugin_data,
204                                  0, r, check);
205     }
206
207     if (ret == KRB5_PLUGIN_NO_HANDLE)
208         return kdc_check_flags(r, r->req.msg_type == krb_as_req,
209                                r->client, r->server);
210     return ret;
211 }
212
213 static krb5_error_code KRB5_LIB_CALL
214 finalize(krb5_context context, const void *plug, void *plugctx, void *userctx)
215 {
216     krb5plugin_windc_ftable *ft = (krb5plugin_windc_ftable *)plug;
217
218     if (ft->finalize_reply == NULL)
219         return KRB5_PLUGIN_NO_HANDLE;
220     return ft->finalize_reply((void *)plug, (astgs_request_t)userctx);
221 }
222
223 krb5_error_code
224 _kdc_finalize_reply(astgs_request_t r)
225 {
226     krb5_error_code ret = KRB5_PLUGIN_NO_HANDLE;
227
228     if (have_plugin)
229         ret = _krb5_plugin_run_f(r->context, &windc_plugin_data, 0, r, finalize);
230
231     if (ret == KRB5_PLUGIN_NO_HANDLE)
232         ret = 0;
233
234     return ret;
235 }
236
237 uintptr_t KRB5_CALLCONV
238 kdc_get_instance(const char *libname)
239 {
240     static const char *instance = "libkdc";
241
242     if (strcmp(libname, "kdc") == 0)
243         return (uintptr_t)instance;
244     else if (strcmp(libname, "hdb") == 0)
245         return hdb_get_instance(libname);
246     else if (strcmp(libname, "krb5") == 0)
247         return krb5_get_instance(libname);
248     else if (strcmp(libname, "gssapi") == 0)
249         return gss_get_instance(libname);
250
251     return 0;
252 }