2 * Copyright (c) 2005,2006 Secure Endpoints Inc.
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:
12 * The above copyright notice and this permission notice shall be
13 * included in all copies or substantial portions of the Software.
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
27 #include <afsconfig.h>
28 #include <afs/param.h>
35 /* supported API versions */
36 #define AFS_PLUGIN_VERSION_MIN 0x00000001
37 #define AFS_PLUGIN_VERSION_MAX AFS_PLUGIN_VERSION
39 #define MAX_EXTENSIONS 8
41 afs_extension extensions[MAX_EXTENSIONS];
42 khm_size n_extensions = 0;
43 khm_int32 next_method_id = AFS_TOKEN_USER;
45 /* not threadsafe. should only be called from the plugin thread */
47 afs_add_extension(afs_msg_announce * ann) {
54 if (ann->cbsize != sizeof(afs_msg_announce) ||
55 FAILED(StringCbLength(ann->name, KHUI_MAXCB_NAME, &cbname)) ||
57 (ann->provide_token_acq &&
58 ((FAILED(StringCbLength(ann->token_acq.short_desc,
59 KHUI_MAXCB_SHORT_DESC,
61 (ann->token_acq.long_desc &&
62 FAILED(StringCbLength(ann->token_acq.long_desc,
65 ann->version < AFS_PLUGIN_VERSION_MIN ||
66 ann->version > AFS_PLUGIN_VERSION_MAX)
68 return KHM_ERROR_INVALID_PARAM;
70 if (n_extensions == MAX_EXTENSIONS)
71 return KHM_ERROR_NO_RESOURCES;
73 cbname += sizeof(wchar_t);
74 cbtashort += sizeof(wchar_t);
75 cbtalong += sizeof(wchar_t);
77 ext = &extensions[n_extensions];
81 tmp = PMALLOC(cbname);
85 StringCbCopy(tmp, cbname, ann->name);
88 if (ann->provide_token_acq) {
89 tmp = PMALLOC(cbtashort);
93 StringCbCopy(tmp, cbtashort, ann->token_acq.short_desc);
94 ext->token_acq.short_desc = tmp;
96 if (ann->token_acq.long_desc) {
97 tmp = PMALLOC(cbtalong);
101 StringCbCopy(tmp, cbtalong,
102 ann->token_acq.long_desc);
103 ext->token_acq.long_desc = tmp;
105 ext->token_acq.long_desc = NULL;
108 ann->token_acq.method_id = next_method_id++;
109 ext->token_acq.method_id = ann->token_acq.method_id;
111 ZeroMemory(&ext->token_acq, sizeof(ext->token_acq));
116 return KHM_ERROR_SUCCESS;
120 afs_free_extension(khm_int32 idx) {
124 assert(idx >= 0 && idx < (khm_int32) n_extensions);
127 ext = &extensions[idx];
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);
136 kmq_delete_subscription(ext->sub);
138 ZeroMemory(ext, sizeof(*ext));
141 /* not thread safe. only call from plugin thread */
143 afs_remove_extension(khm_int32 idx) {
144 if (idx < 0 || idx > (khm_int32) n_extensions)
147 afs_free_extension(idx);
149 if (idx == n_extensions-1) {
152 MoveMemory(&extensions[idx], &extensions[idx + 1],
153 (n_extensions - (idx+1)) * sizeof(*extensions));
157 /* not thread safe. only call from the plugin thread */
159 afs_find_extension(const wchar_t * name) {
162 for (i=0; i < n_extensions; i++) {
163 if (extensions[i].name &&
164 !wcscmp(extensions[i].name, name))
165 return &extensions[i];
171 /* not thread safe. only call from the plugin thread */
173 afs_is_valid_method_id(afs_tk_method method) {
176 if (method == AFS_TOKEN_AUTO ||
177 method == AFS_TOKEN_KRB5 ||
178 method == AFS_TOKEN_KRB524 ||
179 method == AFS_TOKEN_KRB4)
182 for (i=0; i < n_extensions; i++) {
183 if (extensions[i].provide_token_acq &&
184 extensions[i].token_acq.method_id == method)
192 afs_method_describe(afs_tk_method method, khm_int32 flags,
193 wchar_t * wbuf, khm_size cbbuf) {
198 return LoadString(hResModule,
199 ((flags & KCDB_TS_SHORT)?
201 IDS_NC_METHODL_AUTO),
202 wbuf, (int) cbbuf / sizeof(wchar_t));
205 return LoadString(hResModule,
206 ((flags & KCDB_TS_SHORT)?
208 IDS_NC_METHODL_KRB5),
209 wbuf, (int) cbbuf / sizeof(wchar_t));
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));
219 return LoadString(hResModule,
220 ((flags & KCDB_TS_SHORT)?
222 IDS_NC_METHODL_KRB4),
223 wbuf, (int) cbbuf / sizeof(wchar_t));
226 for (idx = 0; idx < n_extensions; idx++) {
227 if(!extensions[idx].provide_token_acq ||
228 extensions[idx].token_acq.method_id != method)
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));
236 return SUCCEEDED(StringCbCopy(wbuf, cbbuf,
237 extensions[idx].token_acq.long_desc));
245 afs_get_next_method_id(afs_tk_method method) {
250 return AFS_TOKEN_AUTO;
252 return AFS_TOKEN_KRB5;
254 return AFS_TOKEN_KRB524;
255 case AFS_TOKEN_KRB524:
256 return AFS_TOKEN_KRB4;
261 for(idx = 0; idx < n_extensions; idx ++) {
262 if (extensions[idx].provide_token_acq &&
263 extensions[idx].token_acq.method_id == method)
269 for(; idx < n_extensions; idx++) {
270 if (extensions[idx].provide_token_acq)
271 return extensions[idx].token_acq.method_id;
277 /* not thread safe. only call from the plugin thread */
279 afs_get_next_token_acq(afs_extension * f) {
285 idx = (f - extensions) + 1;
287 for(; idx < n_extensions; idx++) {
288 if (extensions[idx].provide_token_acq)
289 return &extensions[idx];
296 afs_get_extension(khm_size i) {
297 if (i >= n_extensions)
300 return &extensions[i];
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;
316 for (i=0; i < n_extensions; i++) {
317 if (!extensions[i].provide_token_acq)
320 if (!wcscmp(extensions[i].name, name))
321 return extensions[i].token_acq.method_id;
325 return AFS_TOKEN_AUTO;
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));
341 for (i=0; i < n_extensions; i++) {
342 if (!extensions[i].provide_token_acq)
344 if (extensions[i].token_acq.method_id == method)
345 return SUCCEEDED(StringCbCopy(buf, cbbuf,
346 extensions[i].name));
353 /* not thread safe. only call from the plugin thread */
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,
360 afs_tk_method * pmethod) {
362 afs_msg_resolve_token rt;
366 ZeroMemory(&rt, sizeof(rt));
368 rt.cbsize = sizeof(rt);
372 rt.serverp = serverp;
373 rt.clientp = clientp;
374 rt.method = AFS_TOKEN_AUTO;
377 for (idx = 0; idx < n_extensions; idx++) {
378 if (!extensions[idx].provide_token_acq)
381 rv = kmq_send_sub_msg(extensions[idx].sub,
383 AFS_MSG_RESOLVE_TOKEN,
387 if (KHM_SUCCEEDED(rv)) {
388 assert(rt.ident != NULL);
391 *pmethod = rt.method;
400 /* not thread safe. only call from the plugin thread */
402 afs_ext_klog(afs_tk_method method,
404 const char * service,
407 const afs_conf_cell * cell_config,
408 khm_int32 lifetime) {
411 khm_int32 rv = KHM_ERROR_GENERAL;
413 afs_conf_cell cellconfig;
415 ZeroMemory(&msg, sizeof(msg));
416 ZeroMemory(&cellconfig, sizeof(cellconfig));
418 msg.cbsize = sizeof(msg);
420 msg.identity = identity;
421 msg.service = service;
424 msg.lifetime = lifetime;
426 msg.cell_config = &cellconfig;
428 cellconfig = *cell_config;
429 cellconfig.cbsize = sizeof(cellconfig);
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))
437 rv = kmq_send_sub_msg(extensions[idx].sub,
443 if (KHM_SUCCEEDED(rv))
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);
457 return KHM_ERROR_SUCCESS;