libroken: Build on windows
[openafs.git] / src / WINNT / netidmgr_plugin / afsext.c
1 /*
2  * Copyright (c) 2005,2006 Secure Endpoints Inc.
3  *
4  * Permission is hereby granted, free of charge, to any person
5  * obtaining a copy of this software and associated documentation
6  * files (the "Software"), to deal in the Software without
7  * restriction, including without limitation the rights to use, copy,
8  * modify, merge, publish, distribute, sublicense, and/or sell copies
9  * of the Software, and to permit persons to whom the Software is
10  * furnished to do so, subject to the following conditions:
11  *
12  * The above copyright notice and this permission notice shall be
13  * included in all copies or substantial portions of the Software.
14  *
15  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16  * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17  * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18  * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS
19  * BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN
20  * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN
21  * CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
22  * SOFTWARE.
23  */
24
25 /* $Id$ */
26
27 #include <afsconfig.h>
28 #include <afs/param.h>
29 #include <roken.h>
30
31 #include<afscred.h>
32 #include<assert.h>
33 #include<wchar.h>
34
35 /* supported API versions */
36 #define AFS_PLUGIN_VERSION_MIN 0x00000001
37 #define AFS_PLUGIN_VERSION_MAX AFS_PLUGIN_VERSION
38
39 #define MAX_EXTENSIONS 8
40
41 afs_extension extensions[MAX_EXTENSIONS];
42 khm_size n_extensions = 0;
43 khm_int32 next_method_id = AFS_TOKEN_USER;
44
45 /* not threadsafe.  should only be called from the plugin thread */
46 khm_int32
47 afs_add_extension(afs_msg_announce * ann) {
48     size_t cbname = 0;
49     size_t cbtashort = 0;
50     size_t cbtalong = 0;
51     afs_extension * ext;
52     wchar_t * tmp;
53
54     if (ann->cbsize != sizeof(afs_msg_announce) ||
55         FAILED(StringCbLength(ann->name, KHUI_MAXCB_NAME, &cbname)) ||
56         ann->sub == NULL ||
57         (ann->provide_token_acq &&
58          ((FAILED(StringCbLength(ann->token_acq.short_desc,
59                                  KHUI_MAXCB_SHORT_DESC,
60                                  &cbtashort))) ||
61           (ann->token_acq.long_desc &&
62            FAILED(StringCbLength(ann->token_acq.long_desc,
63                                  KHUI_MAXCB_LONG_DESC,
64                                  &cbtalong))))) ||
65         ann->version < AFS_PLUGIN_VERSION_MIN ||
66         ann->version > AFS_PLUGIN_VERSION_MAX)
67
68         return KHM_ERROR_INVALID_PARAM;
69
70     if (n_extensions == MAX_EXTENSIONS)
71         return KHM_ERROR_NO_RESOURCES;
72
73     cbname += sizeof(wchar_t);
74     cbtashort += sizeof(wchar_t);
75     cbtalong += sizeof(wchar_t);
76
77     ext = &extensions[n_extensions];
78
79     *ext = *ann;
80
81     tmp = PMALLOC(cbname);
82 #ifdef DEBUG
83     assert(tmp);
84 #endif
85     StringCbCopy(tmp, cbname, ann->name);
86     ext->name = tmp;
87
88     if (ann->provide_token_acq) {
89         tmp = PMALLOC(cbtashort);
90 #ifdef DEBUG
91         assert(tmp);
92 #endif
93         StringCbCopy(tmp, cbtashort, ann->token_acq.short_desc);
94         ext->token_acq.short_desc = tmp;
95
96         if (ann->token_acq.long_desc) {
97             tmp = PMALLOC(cbtalong);
98 #ifdef DEBUG
99             assert(tmp);
100 #endif
101             StringCbCopy(tmp, cbtalong,
102                          ann->token_acq.long_desc);
103             ext->token_acq.long_desc = tmp;
104         } else {
105             ext->token_acq.long_desc = NULL;
106         }
107
108         ann->token_acq.method_id = next_method_id++;
109         ext->token_acq.method_id = ann->token_acq.method_id;
110     } else {
111         ZeroMemory(&ext->token_acq, sizeof(ext->token_acq));
112     }
113
114     n_extensions++;
115
116     return KHM_ERROR_SUCCESS;
117 }
118
119 void
120 afs_free_extension(khm_int32 idx) {
121     afs_extension * ext;
122
123 #ifdef DEBUG
124     assert(idx >= 0 && idx < (khm_int32) n_extensions);
125 #endif
126
127     ext = &extensions[idx];
128
129     if (ext->name)
130         PFREE((void *) ext->name);
131     if (ext->token_acq.short_desc)
132         PFREE((void *) ext->token_acq.short_desc);
133     if (ext->token_acq.long_desc)
134         PFREE((void *) ext->token_acq.long_desc);
135     if (ext->sub)
136         kmq_delete_subscription(ext->sub);
137
138     ZeroMemory(ext, sizeof(*ext));
139 }
140
141 /* not thread safe.  only call from plugin thread */
142 void
143 afs_remove_extension(khm_int32 idx) {
144     if (idx < 0 || idx > (khm_int32) n_extensions)
145         return;
146
147     afs_free_extension(idx);
148
149     if (idx == n_extensions-1) {
150         n_extensions--;
151     } else {
152         MoveMemory(&extensions[idx], &extensions[idx + 1],
153                    (n_extensions - (idx+1)) * sizeof(*extensions));
154     }
155 }
156
157 /* not thread safe. only call from the plugin thread */
158 afs_extension *
159 afs_find_extension(const wchar_t * name) {
160     khm_size i;
161
162     for (i=0; i < n_extensions; i++) {
163         if (extensions[i].name &&
164             !wcscmp(extensions[i].name, name))
165             return &extensions[i];
166     }
167
168     return NULL;
169 }
170
171 /* not thread safe.  only call from the plugin thread */
172 khm_boolean
173 afs_is_valid_method_id(afs_tk_method method) {
174     khm_size i;
175
176     if (method == AFS_TOKEN_AUTO ||
177         method == AFS_TOKEN_KRB5 ||
178         method == AFS_TOKEN_KRB524 ||
179         method == AFS_TOKEN_KRB4)
180         return TRUE;
181
182     for (i=0; i < n_extensions; i++) {
183         if (extensions[i].provide_token_acq &&
184             extensions[i].token_acq.method_id == method)
185             return TRUE;
186     }
187
188     return FALSE;
189 }
190
191 khm_boolean
192 afs_method_describe(afs_tk_method method, khm_int32 flags,
193                     wchar_t * wbuf, khm_size cbbuf) {
194     khm_size idx;
195
196     switch(method) {
197     case AFS_TOKEN_AUTO:
198         return LoadString(hResModule,
199                           ((flags & KCDB_TS_SHORT)? 
200                            IDS_NC_METHOD_AUTO:
201                            IDS_NC_METHODL_AUTO),
202                           wbuf, (int) cbbuf / sizeof(wchar_t));
203
204     case AFS_TOKEN_KRB5:
205         return LoadString(hResModule,
206                           ((flags & KCDB_TS_SHORT)?
207                            IDS_NC_METHOD_KRB5:
208                            IDS_NC_METHODL_KRB5),
209                           wbuf, (int) cbbuf / sizeof(wchar_t));
210
211     case AFS_TOKEN_KRB524:
212         return LoadString(hResModule,
213                           ((flags & KCDB_TS_SHORT)?
214                            IDS_NC_METHOD_KRB524:
215                            IDS_NC_METHODL_KRB524),
216                           wbuf, (int) cbbuf / sizeof(wchar_t));
217
218     case AFS_TOKEN_KRB4:
219         return LoadString(hResModule,
220                           ((flags & KCDB_TS_SHORT)?
221                            IDS_NC_METHOD_KRB4:
222                            IDS_NC_METHODL_KRB4),
223                           wbuf, (int) cbbuf / sizeof(wchar_t));
224
225     default:
226         for (idx = 0; idx < n_extensions; idx++) {
227             if(!extensions[idx].provide_token_acq ||
228                extensions[idx].token_acq.method_id != method)
229                 continue;
230
231             if ((flags & KCDB_TS_SHORT) ||
232                 extensions[idx].token_acq.long_desc == NULL)
233                 return SUCCEEDED(StringCbCopy(wbuf, cbbuf,
234                                               extensions[idx].token_acq.short_desc));
235             else
236                 return SUCCEEDED(StringCbCopy(wbuf, cbbuf,
237                                               extensions[idx].token_acq.long_desc));
238         }
239     }
240
241     return FALSE;
242 }
243
244 afs_tk_method
245 afs_get_next_method_id(afs_tk_method method) {
246     khm_size idx;
247
248     switch(method) {
249     case -1:
250         return AFS_TOKEN_AUTO;
251     case AFS_TOKEN_AUTO:
252         return AFS_TOKEN_KRB5;
253     case AFS_TOKEN_KRB5:
254         return AFS_TOKEN_KRB524;
255     case AFS_TOKEN_KRB524:
256         return AFS_TOKEN_KRB4;
257     case AFS_TOKEN_KRB4:
258         idx = 0;
259         break;
260     default:
261         for(idx = 0; idx < n_extensions; idx ++) {
262             if (extensions[idx].provide_token_acq &&
263                 extensions[idx].token_acq.method_id == method)
264                 break;
265         }
266         idx++;
267     }
268
269     for(; idx < n_extensions; idx++) {
270         if (extensions[idx].provide_token_acq)
271             return extensions[idx].token_acq.method_id;
272     }
273
274     return -1;
275 }
276
277 /* not thread safe.  only call from the plugin thread */
278 afs_extension *
279 afs_get_next_token_acq(afs_extension * f) {
280     khm_size idx;
281
282     if (f == NULL)
283         idx = 0;
284     else
285         idx = (f - extensions) + 1;
286
287     for(; idx < n_extensions; idx++) {
288         if (extensions[idx].provide_token_acq)
289             return &extensions[idx];
290     }
291
292     return NULL;
293 }
294
295 afs_extension *
296 afs_get_extension(khm_size i) {
297     if (i >= n_extensions)
298         return NULL;
299     else
300         return &extensions[i];
301 }
302
303 afs_tk_method
304 afs_get_method_id(wchar_t * name) {
305     if (!wcscmp(name, AFS_TOKENNAME_AUTO))
306         return AFS_TOKEN_AUTO;
307     else if (!wcscmp(name, AFS_TOKENNAME_KRB5))
308         return AFS_TOKEN_KRB5;
309     else if (!wcscmp(name, AFS_TOKENNAME_KRB524))
310         return AFS_TOKEN_KRB524;
311     else if (!wcscmp(name, AFS_TOKENNAME_KRB4))
312         return AFS_TOKEN_KRB4;
313     else {
314         khm_size i;
315
316         for (i=0; i < n_extensions; i++) {
317             if (!extensions[i].provide_token_acq)
318                 continue;
319
320             if (!wcscmp(extensions[i].name, name))
321                 return extensions[i].token_acq.method_id;
322         }
323     }
324
325     return AFS_TOKEN_AUTO;
326 }
327
328 khm_boolean
329 afs_get_method_name(afs_tk_method method, wchar_t * buf, khm_size cbbuf) {
330     if (method == AFS_TOKEN_AUTO)
331         return SUCCEEDED(StringCbCopy(buf, cbbuf, AFS_TOKENNAME_AUTO));
332     else if (method == AFS_TOKEN_KRB5)
333         return SUCCEEDED(StringCbCopy(buf, cbbuf, AFS_TOKENNAME_KRB5));
334     else if (method == AFS_TOKEN_KRB524)
335         return SUCCEEDED(StringCbCopy(buf, cbbuf, AFS_TOKENNAME_KRB524));
336     else if (method == AFS_TOKEN_KRB4)
337         return SUCCEEDED(StringCbCopy(buf, cbbuf, AFS_TOKENNAME_KRB4));
338     else {
339         khm_size i;
340
341         for (i=0; i < n_extensions; i++) {
342             if (!extensions[i].provide_token_acq)
343                 continue;
344             if (extensions[i].token_acq.method_id == method)
345                 return SUCCEEDED(StringCbCopy(buf, cbbuf,
346                                               extensions[i].name));
347         }
348     }
349
350     return FALSE;
351 }
352
353 /* not thread safe.  only call from the plugin thread */
354 khm_boolean
355 afs_ext_resolve_token(const wchar_t * cell,
356                       const struct ktc_token * token,
357                       const struct ktc_principal * serverp,
358                       const struct ktc_principal * clientp,
359                       khm_handle * pident,
360                       afs_tk_method * pmethod) {
361
362     afs_msg_resolve_token rt;
363     khm_size idx;
364     khm_int32 rv;
365
366     ZeroMemory(&rt, sizeof(rt));
367
368     rt.cbsize = sizeof(rt);
369
370     rt.cell = cell;
371     rt.token = token;
372     rt.serverp = serverp;
373     rt.clientp = clientp;
374     rt.method = AFS_TOKEN_AUTO;
375     rt.ident = NULL;
376
377     for (idx = 0; idx < n_extensions; idx++) {
378         if (!extensions[idx].provide_token_acq)
379             continue;
380
381         rv = kmq_send_sub_msg(extensions[idx].sub,
382                               afs_msg_type_id,
383                               AFS_MSG_RESOLVE_TOKEN,
384                               0,
385                               (void *) &rt);
386
387         if (KHM_SUCCEEDED(rv)) {
388             assert(rt.ident != NULL);
389
390             *pident = rt.ident;
391             *pmethod = rt.method;
392
393             return TRUE;
394         }
395     }
396
397     return FALSE;
398 }
399
400 /* not thread safe. only call from the plugin thread */
401 khm_boolean
402 afs_ext_klog(afs_tk_method method,
403              khm_handle   identity,
404              const char * service,
405              const char * cell,
406              const char * realm,
407              const afs_conf_cell * cell_config,
408              khm_int32    lifetime) {
409
410     khm_size idx;
411     khm_int32 rv = KHM_ERROR_GENERAL;
412     afs_msg_klog msg;
413     afs_conf_cell cellconfig;
414
415     ZeroMemory(&msg, sizeof(msg));
416     ZeroMemory(&cellconfig, sizeof(cellconfig));
417
418     msg.cbsize = sizeof(msg);
419
420     msg.identity = identity;
421     msg.service = service;
422     msg.cell = cell;
423     msg.realm = realm;
424     msg.lifetime = lifetime;
425
426     msg.cell_config = &cellconfig;
427
428     cellconfig = *cell_config;
429     cellconfig.cbsize = sizeof(cellconfig);
430
431     for (idx = 0; idx < n_extensions; idx++) {
432         if (!extensions[idx].provide_token_acq ||
433             (method != AFS_TOKEN_AUTO &&
434              extensions[idx].token_acq.method_id != method))
435             continue;
436
437         rv = kmq_send_sub_msg(extensions[idx].sub,
438                               afs_msg_type_id,
439                               AFS_MSG_KLOG,
440                               0,
441                               (void *) &msg);
442
443         if (KHM_SUCCEEDED(rv))
444             return TRUE;
445     }
446
447     return FALSE;
448 }
449
450 khm_int32 KHMAPI 
451 afs_msg_ext(khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam) {
452     switch(msg_subtype) {
453     case AFS_MSG_ANNOUNCE:
454         return afs_add_extension((afs_msg_announce *) vparam);
455     }
456
457     return KHM_ERROR_SUCCESS;
458 }