Update NEWS for 1.6.22
[pkg-k5-afs_openafs.git] / src / WINNT / netidmgr_plugin / afsext.c
blob58a461ec4c2a6da2d3b72a4a9eb5a173e179c621
1 /*
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
22 * SOFTWARE.
25 /* $Id$ */
27 #include<afscred.h>
28 #include<assert.h>
29 #include<wchar.h>
31 /* supported API versions */
32 #define AFS_PLUGIN_VERSION_MIN 0x00000001
33 #define AFS_PLUGIN_VERSION_MAX AFS_PLUGIN_VERSION
35 #define MAX_EXTENSIONS 8
37 afs_extension extensions[MAX_EXTENSIONS];
38 khm_size n_extensions = 0;
39 khm_int32 next_method_id = AFS_TOKEN_USER;
41 /* not threadsafe. should only be called from the plugin thread */
42 khm_int32
43 afs_add_extension(afs_msg_announce * ann) {
44 size_t cbname = 0;
45 size_t cbtashort = 0;
46 size_t cbtalong = 0;
47 afs_extension * ext;
48 wchar_t * tmp;
50 if (ann->cbsize != sizeof(afs_msg_announce) ||
51 FAILED(StringCbLength(ann->name, KHUI_MAXCB_NAME, &cbname)) ||
52 ann->sub == NULL ||
53 (ann->provide_token_acq &&
54 ((FAILED(StringCbLength(ann->token_acq.short_desc,
55 KHUI_MAXCB_SHORT_DESC,
56 &cbtashort))) ||
57 (ann->token_acq.long_desc &&
58 FAILED(StringCbLength(ann->token_acq.long_desc,
59 KHUI_MAXCB_LONG_DESC,
60 &cbtalong))))) ||
61 ann->version < AFS_PLUGIN_VERSION_MIN ||
62 ann->version > AFS_PLUGIN_VERSION_MAX)
64 return KHM_ERROR_INVALID_PARAM;
66 if (n_extensions == MAX_EXTENSIONS)
67 return KHM_ERROR_NO_RESOURCES;
69 cbname += sizeof(wchar_t);
70 cbtashort += sizeof(wchar_t);
71 cbtalong += sizeof(wchar_t);
73 ext = &extensions[n_extensions];
75 *ext = *ann;
77 tmp = PMALLOC(cbname);
78 #ifdef DEBUG
79 assert(tmp);
80 #endif
81 StringCbCopy(tmp, cbname, ann->name);
82 ext->name = tmp;
84 if (ann->provide_token_acq) {
85 tmp = PMALLOC(cbtashort);
86 #ifdef DEBUG
87 assert(tmp);
88 #endif
89 StringCbCopy(tmp, cbtashort, ann->token_acq.short_desc);
90 ext->token_acq.short_desc = tmp;
92 if (ann->token_acq.long_desc) {
93 tmp = PMALLOC(cbtalong);
94 #ifdef DEBUG
95 assert(tmp);
96 #endif
97 StringCbCopy(tmp, cbtalong,
98 ann->token_acq.long_desc);
99 ext->token_acq.long_desc = tmp;
100 } else {
101 ext->token_acq.long_desc = NULL;
104 ann->token_acq.method_id = next_method_id++;
105 ext->token_acq.method_id = ann->token_acq.method_id;
106 } else {
107 ZeroMemory(&ext->token_acq, sizeof(ext->token_acq));
110 n_extensions++;
112 return KHM_ERROR_SUCCESS;
115 void
116 afs_free_extension(khm_int32 idx) {
117 afs_extension * ext;
119 #ifdef DEBUG
120 assert(idx >= 0 && idx < (khm_int32) n_extensions);
121 #endif
123 ext = &extensions[idx];
125 if (ext->name)
126 PFREE((void *) ext->name);
127 if (ext->token_acq.short_desc)
128 PFREE((void *) ext->token_acq.short_desc);
129 if (ext->token_acq.long_desc)
130 PFREE((void *) ext->token_acq.long_desc);
131 if (ext->sub)
132 kmq_delete_subscription(ext->sub);
134 ZeroMemory(ext, sizeof(*ext));
137 /* not thread safe. only call from plugin thread */
138 void
139 afs_remove_extension(khm_int32 idx) {
140 if (idx < 0 || idx > (khm_int32) n_extensions)
141 return;
143 afs_free_extension(idx);
145 if (idx == n_extensions-1) {
146 n_extensions--;
147 } else {
148 MoveMemory(&extensions[idx], &extensions[idx + 1],
149 (n_extensions - (idx+1)) * sizeof(*extensions));
153 /* not thread safe. only call from the plugin thread */
154 afs_extension *
155 afs_find_extension(const wchar_t * name) {
156 khm_size i;
158 for (i=0; i < n_extensions; i++) {
159 if (extensions[i].name &&
160 !wcscmp(extensions[i].name, name))
161 return &extensions[i];
164 return NULL;
167 /* not thread safe. only call from the plugin thread */
168 khm_boolean
169 afs_is_valid_method_id(afs_tk_method method) {
170 khm_size i;
172 if (method == AFS_TOKEN_AUTO ||
173 method == AFS_TOKEN_KRB5 ||
174 method == AFS_TOKEN_KRB524 ||
175 method == AFS_TOKEN_KRB4)
176 return TRUE;
178 for (i=0; i < n_extensions; i++) {
179 if (extensions[i].provide_token_acq &&
180 extensions[i].token_acq.method_id == method)
181 return TRUE;
184 return FALSE;
187 khm_boolean
188 afs_method_describe(afs_tk_method method, khm_int32 flags,
189 wchar_t * wbuf, khm_size cbbuf) {
190 khm_size idx;
192 switch(method) {
193 case AFS_TOKEN_AUTO:
194 return LoadString(hResModule,
195 ((flags & KCDB_TS_SHORT)?
196 IDS_NC_METHOD_AUTO:
197 IDS_NC_METHODL_AUTO),
198 wbuf, (int) cbbuf / sizeof(wchar_t));
200 case AFS_TOKEN_KRB5:
201 return LoadString(hResModule,
202 ((flags & KCDB_TS_SHORT)?
203 IDS_NC_METHOD_KRB5:
204 IDS_NC_METHODL_KRB5),
205 wbuf, (int) cbbuf / sizeof(wchar_t));
207 case AFS_TOKEN_KRB524:
208 return LoadString(hResModule,
209 ((flags & KCDB_TS_SHORT)?
210 IDS_NC_METHOD_KRB524:
211 IDS_NC_METHODL_KRB524),
212 wbuf, (int) cbbuf / sizeof(wchar_t));
214 case AFS_TOKEN_KRB4:
215 return LoadString(hResModule,
216 ((flags & KCDB_TS_SHORT)?
217 IDS_NC_METHOD_KRB4:
218 IDS_NC_METHODL_KRB4),
219 wbuf, (int) cbbuf / sizeof(wchar_t));
221 default:
222 for (idx = 0; idx < n_extensions; idx++) {
223 if(!extensions[idx].provide_token_acq ||
224 extensions[idx].token_acq.method_id != method)
225 continue;
227 if ((flags & KCDB_TS_SHORT) ||
228 extensions[idx].token_acq.long_desc == NULL)
229 return SUCCEEDED(StringCbCopy(wbuf, cbbuf,
230 extensions[idx].token_acq.short_desc));
231 else
232 return SUCCEEDED(StringCbCopy(wbuf, cbbuf,
233 extensions[idx].token_acq.long_desc));
237 return FALSE;
240 afs_tk_method
241 afs_get_next_method_id(afs_tk_method method) {
242 khm_size idx;
244 switch(method) {
245 case -1:
246 return AFS_TOKEN_AUTO;
247 case AFS_TOKEN_AUTO:
248 return AFS_TOKEN_KRB5;
249 case AFS_TOKEN_KRB5:
250 return AFS_TOKEN_KRB524;
251 case AFS_TOKEN_KRB524:
252 return AFS_TOKEN_KRB4;
253 case AFS_TOKEN_KRB4:
254 idx = 0;
255 break;
256 default:
257 for(idx = 0; idx < n_extensions; idx ++) {
258 if (extensions[idx].provide_token_acq &&
259 extensions[idx].token_acq.method_id == method)
260 break;
262 idx++;
265 for(; idx < n_extensions; idx++) {
266 if (extensions[idx].provide_token_acq)
267 return extensions[idx].token_acq.method_id;
270 return -1;
273 /* not thread safe. only call from the plugin thread */
274 afs_extension *
275 afs_get_next_token_acq(afs_extension * f) {
276 khm_size idx;
278 if (f == NULL)
279 idx = 0;
280 else
281 idx = (f - extensions) + 1;
283 for(; idx < n_extensions; idx++) {
284 if (extensions[idx].provide_token_acq)
285 return &extensions[idx];
288 return NULL;
291 afs_extension *
292 afs_get_extension(khm_size i) {
293 if (i >= n_extensions)
294 return NULL;
295 else
296 return &extensions[i];
299 afs_tk_method
300 afs_get_method_id(wchar_t * name) {
301 if (!wcscmp(name, AFS_TOKENNAME_AUTO))
302 return AFS_TOKEN_AUTO;
303 else if (!wcscmp(name, AFS_TOKENNAME_KRB5))
304 return AFS_TOKEN_KRB5;
305 else if (!wcscmp(name, AFS_TOKENNAME_KRB524))
306 return AFS_TOKEN_KRB524;
307 else if (!wcscmp(name, AFS_TOKENNAME_KRB4))
308 return AFS_TOKEN_KRB4;
309 else {
310 khm_size i;
312 for (i=0; i < n_extensions; i++) {
313 if (!extensions[i].provide_token_acq)
314 continue;
316 if (!wcscmp(extensions[i].name, name))
317 return extensions[i].token_acq.method_id;
321 return AFS_TOKEN_AUTO;
324 khm_boolean
325 afs_get_method_name(afs_tk_method method, wchar_t * buf, khm_size cbbuf) {
326 if (method == AFS_TOKEN_AUTO)
327 return SUCCEEDED(StringCbCopy(buf, cbbuf, AFS_TOKENNAME_AUTO));
328 else if (method == AFS_TOKEN_KRB5)
329 return SUCCEEDED(StringCbCopy(buf, cbbuf, AFS_TOKENNAME_KRB5));
330 else if (method == AFS_TOKEN_KRB524)
331 return SUCCEEDED(StringCbCopy(buf, cbbuf, AFS_TOKENNAME_KRB524));
332 else if (method == AFS_TOKEN_KRB4)
333 return SUCCEEDED(StringCbCopy(buf, cbbuf, AFS_TOKENNAME_KRB4));
334 else {
335 khm_size i;
337 for (i=0; i < n_extensions; i++) {
338 if (!extensions[i].provide_token_acq)
339 continue;
340 if (extensions[i].token_acq.method_id == method)
341 return SUCCEEDED(StringCbCopy(buf, cbbuf,
342 extensions[i].name));
346 return FALSE;
349 /* not thread safe. only call from the plugin thread */
350 khm_boolean
351 afs_ext_resolve_token(const wchar_t * cell,
352 const struct ktc_token * token,
353 const struct ktc_principal * serverp,
354 const struct ktc_principal * clientp,
355 khm_handle * pident,
356 afs_tk_method * pmethod) {
358 afs_msg_resolve_token rt;
359 khm_size idx;
360 khm_int32 rv;
362 ZeroMemory(&rt, sizeof(rt));
364 rt.cbsize = sizeof(rt);
366 rt.cell = cell;
367 rt.token = token;
368 rt.serverp = serverp;
369 rt.clientp = clientp;
370 rt.method = AFS_TOKEN_AUTO;
371 rt.ident = NULL;
373 for (idx = 0; idx < n_extensions; idx++) {
374 if (!extensions[idx].provide_token_acq)
375 continue;
377 rv = kmq_send_sub_msg(extensions[idx].sub,
378 afs_msg_type_id,
379 AFS_MSG_RESOLVE_TOKEN,
381 (void *) &rt);
383 if (KHM_SUCCEEDED(rv)) {
384 assert(rt.ident != NULL);
386 *pident = rt.ident;
387 *pmethod = rt.method;
389 return TRUE;
393 return FALSE;
396 /* not thread safe. only call from the plugin thread */
397 khm_boolean
398 afs_ext_klog(afs_tk_method method,
399 khm_handle identity,
400 const char * service,
401 const char * cell,
402 const char * realm,
403 const afs_conf_cell * cell_config,
404 khm_int32 lifetime) {
406 khm_size idx;
407 khm_int32 rv = KHM_ERROR_GENERAL;
408 afs_msg_klog msg;
409 afs_conf_cell cellconfig;
411 ZeroMemory(&msg, sizeof(msg));
412 ZeroMemory(&cellconfig, sizeof(cellconfig));
414 msg.cbsize = sizeof(msg);
416 msg.identity = identity;
417 msg.service = service;
418 msg.cell = cell;
419 msg.realm = realm;
420 msg.lifetime = lifetime;
422 msg.cell_config = &cellconfig;
424 cellconfig = *cell_config;
425 cellconfig.cbsize = sizeof(cellconfig);
427 for (idx = 0; idx < n_extensions; idx++) {
428 if (!extensions[idx].provide_token_acq ||
429 (method != AFS_TOKEN_AUTO &&
430 extensions[idx].token_acq.method_id != method))
431 continue;
433 rv = kmq_send_sub_msg(extensions[idx].sub,
434 afs_msg_type_id,
435 AFS_MSG_KLOG,
437 (void *) &msg);
439 if (KHM_SUCCEEDED(rv))
440 return TRUE;
443 return FALSE;
446 khm_int32 KHMAPI
447 afs_msg_ext(khm_int32 msg_subtype, khm_ui_4 uparam, void * vparam) {
448 switch(msg_subtype) {
449 case AFS_MSG_ANNOUNCE:
450 return afs_add_extension((afs_msg_announce *) vparam);
453 return KHM_ERROR_SUCCESS;