Update NEWS for 1.6.22
[pkg-k5-afs_openafs.git] / src / WINNT / netidmgr_plugin / afsnewcreds.c
blobc8ae6746f1f0b52a540823da900b67ba5f6e44a1
1 /*
2 * Copyright (c) 2005,2006,2007,2008 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<commctrl.h>
29 #include<assert.h>
30 #include<netidmgr_version.h>
31 #include<htmlhelp.h>
32 #include<help/afsplhlp.h>
34 /* UI stuff */
36 #define WMNC_AFS_UPDATE_ROWS (WMNC_USER + 1)
38 typedef struct tag_afs_ident_token_set {
39 khm_handle ident;
40 afs_cred_list * l;
41 khm_boolean add_new;
42 khm_boolean update_info;
43 } afs_ident_token_set;
46 void
47 afs_cred_flush_rows(afs_cred_list * l) {
48 int i;
50 for(i=0; i<l->n_rows; i++) {
51 if(l->rows[i].cell)
52 PFREE(l->rows[i].cell);
53 if(l->rows[i].realm)
54 PFREE(l->rows[i].realm);
57 if(l->nc_rows) {
58 ZeroMemory(l->rows, sizeof(l->rows[0]) * l->nc_rows);
61 l->n_rows = 0;
64 void
65 afs_cred_free_rows(afs_cred_list * l) {
67 afs_cred_flush_rows(l);
69 if(l->rows)
70 PFREE(l->rows);
71 l->rows = NULL;
72 l->n_rows = 0;
73 l->nc_rows = 0;
76 void
77 afs_cred_assert_rows(afs_cred_list * l, int n) {
78 afs_cred_row * rows;
80 if(n > l->nc_rows) {
81 l->nc_rows = UBOUNDSS(n, AFS_DLG_ROW_ALLOC, AFS_DLG_ROW_ALLOC);
82 rows = PMALLOC(sizeof(afs_cred_row) * l->nc_rows);
83 ZeroMemory(rows, sizeof(afs_cred_row) * l->nc_rows);
85 if(l->rows) {
86 if(l->n_rows)
87 memcpy(rows, l->rows, sizeof(afs_cred_row) * l->n_rows);
88 PFREE(l->rows);
90 l->rows = rows;
94 void
95 afs_cred_delete_row(afs_cred_list * l, int i) {
96 if (i < 0 || i >= l->n_rows)
97 return;
99 if(i < (l->n_rows - 1)) {
100 if(l->rows[i].cell)
101 PFREE(l->rows[i].cell);
102 if(l->rows[i].realm)
103 PFREE(l->rows[i].realm);
104 memmove(&(l->rows[i]),
105 &(l->rows[i+1]),
106 ((l->n_rows - (i+1)) *
107 sizeof(l->rows[0])));
109 l->n_rows--;
112 afs_cred_row *
113 afs_cred_get_new_row(afs_cred_list * l) {
114 afs_cred_row * r;
116 afs_cred_assert_rows(l, l->n_rows + 1);
117 r = &(l->rows[l->n_rows]);
118 l->n_rows++;
120 ZeroMemory(r, sizeof(*r));
122 return r;
125 afs_cred_row *
126 afs_cred_add_row_from_cred(afs_cred_list * l,
127 khm_handle cred) {
128 khm_int32 rv;
129 afs_cred_row * row;
130 khm_size cb;
131 wchar_t cell[MAXCELLCHARS];
132 int i;
134 cb = sizeof(cell);
135 rv = kcdb_cred_get_attr(cred,
136 afs_attr_cell,
137 NULL,
138 cell,
139 &cb);
140 #ifdef DEBUG
141 assert(rv == KHM_ERROR_SUCCESS && cb != 0);
142 #endif
144 /* check if we already have the cell listed. */
145 for (i=0; i<l->n_rows; i++) {
146 if (!_wcsicmp(l->rows[i].cell, cell))
147 return &l->rows[i];
150 row = afs_cred_get_new_row(l);
152 row->cell = PMALLOC(cb);
153 StringCbCopy(row->cell, cb, cell);
155 cb = sizeof(row->method);
156 rv = kcdb_cred_get_attr(cred,
157 afs_attr_method,
158 NULL,
159 &row->method,
160 &cb);
162 if (KHM_FAILED(rv)) {
163 row->method = AFS_TOKEN_AUTO;
164 row->realm = NULL;
165 return row;
168 rv = kcdb_cred_get_attr(cred,
169 afs_attr_realm,
170 NULL,
171 NULL,
172 &cb);
174 if (rv == KHM_ERROR_TOO_LONG && cb > sizeof(wchar_t)) {
175 row->realm = PMALLOC(cb);
176 #ifdef DEBUG
177 assert(row->realm);
178 #endif
179 rv = kcdb_cred_get_attr(cred,
180 afs_attr_realm,
181 NULL,
182 row->realm,
183 &cb);
185 if (KHM_FAILED(rv)) {
186 if (row->realm)
187 PFREE(row->realm);
188 row->realm = NULL;
190 } else {
191 row->realm = NULL;
194 return row;
197 khm_int32 KHMAPI
198 afs_cred_add_cred_proc(khm_handle cred, void * rock) {
199 afs_cred_list * l = (afs_cred_list *) rock;
200 khm_int32 t;
202 if (KHM_FAILED(kcdb_cred_get_type(cred, &t)) ||
203 t != afs_credtype_id)
204 return KHM_ERROR_SUCCESS;
206 afs_cred_add_row_from_cred(l, cred);
208 return KHM_ERROR_SUCCESS;
211 void
212 afs_cred_get_context_creds(afs_cred_list *l,
213 khui_action_context * ctx) {
214 khm_handle credset = NULL;
216 if (KHM_FAILED(kcdb_credset_create(&credset)))
217 return;
219 if (KHM_FAILED(kcdb_credset_extract_filtered(credset,
220 NULL,
221 khui_context_cursor_filter,
222 (void *) ctx)))
223 goto _cleanup;
225 kcdb_credset_apply(credset,
226 afs_cred_add_cred_proc,
227 (void *) l);
229 _cleanup:
230 if (credset)
231 kcdb_credset_delete(credset);
234 khm_int32 KHMAPI
235 afs_get_id_creds_apply_proc(khm_handle cred, void * rock) {
236 khm_int32 t;
237 afs_ident_token_set * ts;
238 afs_cred_list * l;
239 khm_handle ident;
240 wchar_t cell[MAXCELLCHARS];
241 khm_size cb;
242 int i;
243 khm_int32 cflags = 0;
245 ts = (afs_ident_token_set *) rock;
246 l = ts->l;
248 kcdb_cred_get_type(cred, &t);
249 if (t != afs_credtype_id)
250 return KHM_ERROR_SUCCESS;
252 cb = sizeof(cell);
253 if (KHM_FAILED(kcdb_cred_get_attr(cred, afs_attr_cell,
254 NULL,
255 cell, &cb)))
256 return KHM_ERROR_SUCCESS;
258 kcdb_cred_get_flags(cred, &cflags);
260 kcdb_cred_get_identity(cred, &ident);
262 if (kcdb_identity_is_equal(ident, ts->ident)) {
264 for (i=0; i < l->n_rows; i++) {
265 if (!_wcsicmp(l->rows[i].cell, cell)) {
266 khm_int32 method;
268 /* if the token exists, then these are implied */
269 l->rows[i].flags =
270 DLGROW_FLAG_EXISTS |
271 DLGROW_FLAG_CHECKED |
272 DLGROW_FLAG_VALID;
274 if (cflags & KCDB_CRED_FLAG_EXPIRED)
275 l->rows[i].flags |= DLGROW_FLAG_EXPIRED;
277 if (ts->update_info) {
278 wchar_t realm[KHUI_MAXCCH_NAME];
280 cb = sizeof(method);
281 if (KHM_SUCCEEDED
282 (kcdb_cred_get_attr(cred, afs_attr_method,
283 NULL,
284 &method, &cb)) &&
285 afs_is_valid_method_id(method))
286 l->rows[i].method = method;
288 cb = sizeof(realm);
289 if (KHM_SUCCEEDED
290 (kcdb_cred_get_attr(cred, afs_attr_realm,
291 NULL,
292 realm, &cb)) &&
293 cb > sizeof(wchar_t)) {
295 if (l->rows[i].realm)
296 PFREE(l->rows[i].realm);
297 l->rows[i].realm = PMALLOC(cb);
298 StringCbCopy(l->rows[i].realm,
300 realm);
303 break;
307 /* not found? add! */
308 if (i >= l->n_rows && ts->add_new) {
309 afs_cred_row * r;
311 r = afs_cred_add_row_from_cred(l, cred);
313 r->flags = DLGROW_FLAG_VALID | DLGROW_FLAG_CHECKED |
314 DLGROW_FLAG_EXISTS;
316 if (cflags & KCDB_CRED_FLAG_EXPIRED)
317 r->flags |= DLGROW_FLAG_EXPIRED;
320 } else { /* different identities */
322 for (i=0; i < l->n_rows; i++) {
323 if (!_wcsicmp(l->rows[i].cell, cell)) {
324 l->rows[i].flags =
325 DLGROW_FLAG_NOTOWNED | DLGROW_FLAG_EXISTS |
326 DLGROW_FLAG_VALID | DLGROW_FLAG_CHECKED;
327 if (cflags & KCDB_CRED_FLAG_EXPIRED)
328 l->rows[i].flags |= DLGROW_FLAG_EXPIRED;
334 kcdb_identity_release(ident);
336 return KHM_ERROR_SUCCESS;
339 void
340 afs_remove_token_from_identities(wchar_t * cell) {
341 wchar_t * idents = NULL;
342 wchar_t * t;
343 khm_size cb_id;
344 khm_size n_id = 0;
346 do {
347 if (kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG,
348 KCDB_IDENT_FLAG_CONFIG,
349 NULL,
350 &cb_id,
351 &n_id) != KHM_ERROR_TOO_LONG ||
352 n_id == 0) {
353 if (idents)
354 PFREE(idents);
355 return;
358 if (idents)
359 PFREE(idents);
360 idents = PMALLOC(cb_id);
362 if (kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG,
363 KCDB_IDENT_FLAG_CONFIG,
364 idents,
365 &cb_id,
366 &n_id) == KHM_ERROR_SUCCESS)
367 break;
368 } while(TRUE);
370 for (t=idents;
371 t && *t;
372 t = multi_string_next(t)) {
374 khm_handle h_id = NULL;
375 khm_handle csp_ident = NULL;
376 khm_handle csp_afs = NULL;
377 khm_size cb;
378 wchar_t vbuf[1024];
379 wchar_t * tbuf = NULL;
380 khm_int32 enabled = 0;
382 kcdb_identity_create(t, 0, &h_id);
383 if (h_id == NULL) {
384 #ifdef DEBUG
385 assert(FALSE);
386 #endif
387 continue;
390 if (KHM_FAILED(kcdb_identity_get_config(h_id, 0, &csp_ident)))
391 goto _cleanup_loop;
393 if (KHM_FAILED(khc_open_space(csp_ident, CSNAME_AFSCRED,
394 0, &csp_afs)))
395 goto _cleanup_loop;
397 if (KHM_SUCCEEDED(khc_read_int32(csp_afs, L"AFSEnabled", &enabled)) &&
398 !enabled)
399 goto _cleanup_loop;
401 if (khc_read_multi_string(csp_afs, L"Cells", NULL, &cb)
402 != KHM_ERROR_TOO_LONG)
403 goto _cleanup_loop;
405 if (cb < sizeof(vbuf))
406 tbuf = vbuf;
407 else
408 tbuf = PMALLOC(cb);
410 if (khc_read_multi_string(csp_afs, L"Cells", tbuf, &cb)
411 != KHM_ERROR_SUCCESS)
412 goto _cleanup_loop;
414 if (multi_string_find(tbuf, cell, 0) == NULL)
415 goto _cleanup_loop;
417 multi_string_delete(tbuf, cell, 0);
419 khc_write_multi_string(csp_afs, L"Cells", tbuf);
421 _cleanup_loop:
422 kcdb_identity_release(h_id);
423 if (csp_ident)
424 khc_close_space(csp_ident);
425 if (csp_afs)
426 khc_close_space(csp_afs);
427 if (tbuf && tbuf != vbuf)
428 PFREE(tbuf);
431 if (idents)
432 PFREE(idents);
435 khm_boolean
436 afs_check_add_token_to_identity(wchar_t * cell, khm_handle ident,
437 khm_handle * ident_conflict) {
438 wchar_t * idents = NULL;
439 wchar_t * t;
440 khm_size cb_id;
441 khm_size n_id = 0;
442 khm_boolean ok_to_add = TRUE;
444 /* check if this cell is listed for any other identity. */
446 do {
447 if (kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG,
448 KCDB_IDENT_FLAG_CONFIG,
449 NULL,
450 &cb_id,
451 &n_id) != KHM_ERROR_TOO_LONG ||
452 n_id == 0) {
453 if (idents)
454 PFREE(idents);
455 return TRUE;
458 if (idents)
459 PFREE(idents);
460 idents = PMALLOC(cb_id);
462 if (kcdb_identity_enum(KCDB_IDENT_FLAG_CONFIG,
463 KCDB_IDENT_FLAG_CONFIG,
464 idents,
465 &cb_id,
466 &n_id) == KHM_ERROR_SUCCESS)
467 break;
468 } while(TRUE);
470 for (t=idents;
471 ok_to_add && t && *t;
472 t = multi_string_next(t)) {
474 khm_handle h_id = NULL;
475 khm_handle csp_ident = NULL;
476 khm_handle csp_afs = NULL;
477 khm_size cb;
478 wchar_t vbuf[1024];
479 wchar_t * tbuf = NULL;
480 khm_int32 enabled = 0;
482 kcdb_identity_create(t, 0, &h_id);
483 if (h_id == NULL) {
484 #ifdef DEBUG
485 assert(FALSE);
486 #endif
487 continue;
490 if (kcdb_identity_is_equal(h_id, ident)) {
491 kcdb_identity_release(h_id);
492 continue;
495 if (KHM_FAILED(kcdb_identity_get_config(h_id, 0, &csp_ident)))
496 goto _cleanup_loop;
498 if (KHM_FAILED(khc_open_space(csp_ident, CSNAME_AFSCRED,
499 0, &csp_afs)))
500 goto _cleanup_loop;
502 if (KHM_SUCCEEDED(khc_read_int32(csp_afs, L"AFSEnabled", &enabled)) &&
503 !enabled)
504 goto _cleanup_loop;
506 if (khc_read_multi_string(csp_afs, L"Cells", NULL, &cb)
507 != KHM_ERROR_TOO_LONG)
508 goto _cleanup_loop;
510 if (cb < sizeof(vbuf))
511 tbuf = vbuf;
512 else
513 tbuf = PMALLOC(cb);
515 if (khc_read_multi_string(csp_afs, L"Cells", tbuf, &cb)
516 != KHM_ERROR_SUCCESS)
517 goto _cleanup_loop;
519 if (multi_string_find(tbuf, cell, 0) == NULL)
520 goto _cleanup_loop;
522 /* we found another identity which gets tokens for the
523 same cell */
525 ok_to_add = FALSE;
527 if (ident_conflict) {
528 *ident_conflict = h_id;
529 kcdb_identity_hold(h_id);
532 _cleanup_loop:
533 kcdb_identity_release(h_id);
534 if (csp_ident)
535 khc_close_space(csp_ident);
536 if (csp_afs)
537 khc_close_space(csp_afs);
538 if (tbuf && tbuf != vbuf)
539 PFREE(tbuf);
542 if (idents)
543 PFREE(idents);
545 return ok_to_add;
548 static void
549 add_token_to_list(afs_cred_list * l,
550 khm_handle h_gcells,
551 HKEY hk_gcells,
552 const wchar_t * c_cell)
554 khm_size cb;
555 int i;
556 afs_cred_row * r;
557 khm_handle h_cell = NULL;
558 HKEY hk_cell = NULL;
559 wchar_t wbuf[MAXCELLCHARS];
560 wchar_t wmethod[KHUI_MAXCCH_NAME];
562 if (FAILED(StringCbLength(c_cell, (MAXCELLCHARS + 1) * sizeof(wchar_t),
563 &cb)))
564 return;
565 cb += sizeof(wchar_t);
567 for (i=0; i < l->n_rows; i++) {
568 if (!_wcsicmp(l->rows[i].cell, c_cell))
569 break;
572 if (i < l->n_rows)
573 return;
575 r = afs_cred_get_new_row(l);
577 r->cell = PMALLOC(cb);
578 StringCbCopy(r->cell, cb, c_cell);
580 if (h_gcells &&
581 KHM_SUCCEEDED(khc_open_space(h_gcells, c_cell, 0, &h_cell))) {
583 cb = sizeof(wmethod);
584 if (KHM_SUCCEEDED(khc_read_string(h_cell, L"MethodName",
585 wmethod, &cb))) {
587 r->method = afs_get_method_id(wmethod);
589 /* remove the deprecated value if it is present. */
590 khc_remove_value(h_cell, L"Method", 0);
592 } else if (KHM_SUCCEEDED(khc_read_int32(h_cell,
593 L"Method", &i))) {
594 /* the Method property is deprecated. We detect and
595 correct this whenever possible. */
597 if (!afs_is_valid_method_id(i))
598 i = AFS_TOKEN_AUTO;
600 r->method = i;
602 afs_get_method_name(i, wmethod, sizeof(wmethod));
604 khc_write_string(h_cell, L"MethodName", wmethod);
606 khc_remove_value(h_cell, L"Method", 0);
607 } else {
608 r->method = AFS_TOKEN_AUTO;
611 cb = sizeof(wbuf);
612 if (KHM_SUCCEEDED(khc_read_string(h_cell, L"Realm", wbuf, &cb)) &&
613 cb > sizeof(wchar_t)) {
614 r->realm = PMALLOC(cb);
615 StringCbCopy(r->realm, cb, wbuf);
616 } else {
617 r->realm = NULL;
620 khc_close_space(h_cell);
621 h_cell = NULL;
622 } else if (hk_gcells &&
623 RegOpenKeyEx(hk_gcells, c_cell, 0, KEY_READ, &hk_cell) == ERROR_SUCCESS) {
625 DWORD cbd;
627 cbd = sizeof(wmethod);
628 if (RegQueryValueEx(hk_cell, L"MethodName", NULL, NULL, (LPBYTE) wmethod, &cbd) == ERROR_SUCCESS) {
629 r->method = afs_get_method_id(wmethod);
630 } else {
631 r->method = AFS_TOKEN_AUTO;
634 cbd = sizeof(wbuf);
635 if (RegQueryValueEx(hk_cell, L"Realm", NULL, NULL, (LPBYTE) wbuf, &cbd) == ERROR_SUCCESS) {
636 cbd += sizeof(wchar_t);
637 r->realm = PMALLOC(cbd);
638 ZeroMemory(r->realm, cbd);
639 StringCbCopy(r->realm, cbd, wbuf);
640 } else {
641 r->realm = NULL;
644 RegCloseKey(hk_cell);
646 } else {
647 r->realm = NULL;
648 r->method = AFS_TOKEN_AUTO;
651 r->flags = 0;
655 void
656 afs_cred_get_identity_creds(afs_cred_list * l,
657 khm_handle ident,
658 khm_boolean * penabled) {
659 khm_handle h_id = NULL;
660 khm_handle h_afs = NULL;
661 khm_handle h_cells = NULL; /* per identity cells space */
662 khm_handle h_gcells = NULL; /* global cells space */
663 khm_boolean load_defs = TRUE;
664 khm_size cbi;
665 wchar_t * ms = NULL;
666 wchar_t * s = NULL;
667 afs_ident_token_set ts;
668 khm_int32 t;
670 if (penabled)
671 *penabled = TRUE;
673 afs_cred_flush_rows(l);
675 kcdb_identity_get_config(ident, 0, &h_id);
676 if(!h_id)
677 goto _done_config;
679 if(KHM_FAILED(khc_open_space(h_id, CSNAME_AFSCRED,
680 0, &h_afs)))
681 goto _done_config;
683 if (penabled) {
684 t = 1;
685 if (KHM_FAILED(khc_read_int32(h_afs, L"AFSEnabled", &t)))
686 khc_read_int32(csp_params, L"AFSEnabled", &t);
687 *penabled = !!t;
690 if(KHM_FAILED(khc_open_space(h_afs, L"Cells",
691 0, &h_cells)))
692 goto _done_config;
694 if(khc_read_multi_string(h_afs, L"Cells", NULL, &cbi) !=
695 KHM_ERROR_TOO_LONG)
696 goto _done_config;
698 load_defs = FALSE;
700 ms = PMALLOC(cbi);
701 ZeroMemory(ms, cbi);
703 khc_read_multi_string(h_afs, L"Cells", ms, &cbi);
705 s = ms;
706 for(s = ms; s && *s; s = multi_string_next(s)) {
707 add_token_to_list(l, h_cells, NULL, s);
710 if(ms) {
711 PFREE(ms);
712 ms = NULL;
715 _done_config:
717 if (load_defs) {
718 /* We want to load defaults */
719 char buf[MAXCELLCHARS];
720 wchar_t wbuf[MAXCELLCHARS];
721 wchar_t * defcells;
722 khm_size cb_defcells;
724 khc_open_space(csp_params, L"Cells", 0, &h_gcells);
726 if (!cm_GetRootCellName(buf) &&
727 afs_check_for_cell_realm_match(ident, buf)) {
728 AnsiStrToUnicode(wbuf, sizeof(wbuf), buf);
730 if (afs_check_add_token_to_identity(wbuf, ident, NULL)) {
731 add_token_to_list(l, h_gcells, NULL, wbuf);
735 if (khc_read_multi_string(csp_params, L"DefaultCells",
736 NULL, &cb_defcells) == KHM_ERROR_TOO_LONG &&
737 cb_defcells > sizeof(wchar_t) * 2) {
738 wchar_t * c_cell;
740 defcells = PMALLOC(cb_defcells);
741 if (defcells == NULL)
742 goto _done_defaults;
744 if (KHM_FAILED(khc_read_multi_string(csp_params, L"DefaultCells",
745 defcells, &cb_defcells))) {
746 PFREE(defcells);
747 goto _done_defaults;
750 for (c_cell = defcells;
751 c_cell && *c_cell;
752 c_cell = multi_string_next(c_cell)) {
753 char cell[MAXCELLCHARS];
755 UnicodeStrToAnsi(cell, sizeof(cell), c_cell);
757 if (!afs_check_for_cell_realm_match(ident, cell))
758 continue;
760 add_token_to_list(l, h_gcells, NULL, c_cell);
763 PFREE(defcells);
766 /* Check HKLM\Software\OpenAFS\Client\Realms\<Realm> registry key as well */
768 wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
769 wchar_t * realm;
770 wchar_t * cell=NULL;
771 khm_size cb;
772 HKEY hk_realms = NULL, hk_realm = NULL;
774 cb = sizeof(idname);
775 kcdb_identity_get_name(ident, idname, &cb);
777 realm = wcsrchr(idname, L'@');
778 if (realm == NULL || realm[1] == L'\0')
779 goto _done_realms;
781 realm++;
783 if (RegOpenKeyEx(HKEY_LOCAL_MACHINE, L"SOFTWARE\\OpenAFS\\Client\\Realms", 0, KEY_READ, &hk_realms) != ERROR_SUCCESS)
784 goto _done_realms;
786 if (RegOpenKeyEx(hk_realms, realm, 0, KEY_READ, &hk_realm) != ERROR_SUCCESS)
787 goto _done_realms;
789 if (penabled) {
790 DWORD enabled = 1;
791 DWORD cbd;
793 cbd = sizeof(enabled);
795 if (RegQueryValueEx(hk_realm, L"AFSEnabled",
796 NULL, NULL, (LPBYTE) &enabled, &cbd) == ERROR_SUCCESS) {
797 *penabled = !!enabled;
802 DWORD dwNumCells=0, dwMaxCellLen=0, dwIndex, dwCellBufSz;
804 RegQueryInfoKey( hk_realm,
805 NULL, /* lpClass */
806 NULL, /* lpcClass */
807 NULL, /* lpReserved */
808 &dwNumCells, /* lpcSubKeys */
809 &dwMaxCellLen, /* lpcMaxSubKeyLen */
810 NULL, /* lpcMaxClassLen */
811 NULL, /* lpcValues */
812 NULL, /* lpcMaxValueNameLen */
813 NULL, /* lpcMaxValueLen */
814 NULL, /* lpcbSecurityDescriptor */
815 NULL /* lpftLastWriteTime */
818 dwCellBufSz = (dwMaxCellLen + 1) * sizeof(wchar_t);
819 cell = PMALLOC(dwCellBufSz);
820 ZeroMemory(cell, dwCellBufSz);
822 for ( dwIndex=0; dwIndex < dwNumCells; dwIndex++ ) {
823 if (RegEnumKey( hk_realm, dwIndex, cell, dwCellBufSz) != ERROR_SUCCESS)
824 goto _done_realms;
826 if (afs_check_add_token_to_identity(cell, ident, NULL))
827 add_token_to_list(l, NULL, hk_realm, cell);
831 _done_realms:
833 if (hk_realm)
834 RegCloseKey(hk_realm);
836 if (hk_realms)
837 RegCloseKey(hk_realms);
839 if (cell)
840 PFREE(cell);
844 _done_defaults:
846 ts.ident = ident;
847 ts.l = l;
848 ts.add_new = TRUE;
849 ts.update_info = FALSE;
851 kcdb_credset_apply(NULL, afs_get_id_creds_apply_proc,
852 &ts);
854 if(h_id)
855 khc_close_space(h_id);
856 if(h_afs)
857 khc_close_space(h_afs);
858 if(h_cells)
859 khc_close_space(h_cells);
860 if(h_gcells)
861 khc_close_space(h_gcells);
864 void
865 nc_dlg_enable(HWND hwnd, BOOL enable) {
866 if(enable) {
867 SendDlgItemMessage(hwnd, IDC_NCAFS_OBTAIN, BM_SETCHECK,
868 BST_CHECKED, 0);
869 } else {
870 SendDlgItemMessage(hwnd, IDC_NCAFS_OBTAIN, BM_SETCHECK,
871 BST_UNCHECKED, 0);
874 EnableWindow(GetDlgItem(hwnd,IDC_NCAFS_CELL), enable);
875 EnableWindow(GetDlgItem(hwnd,IDC_NCAFS_REALM), enable);
876 EnableWindow(GetDlgItem(hwnd,IDC_NCAFS_METHOD), enable);
877 EnableWindow(GetDlgItem(hwnd,IDC_NCAFS_TOKENLIST), enable);
878 EnableWindow(GetDlgItem(hwnd,IDC_NCAFS_ADD_TOKEN), enable);
879 EnableWindow(GetDlgItem(hwnd,IDC_NCAFS_DELETE_TOKEN), enable);
882 void
883 nc_dlg_show_tooltip(HWND hwnd,
884 UINT_PTR id,
885 LPWSTR msg,
886 LPWSTR title,
887 int type,
888 int x,
889 int y)
891 afs_dlg_data * d;
892 TOOLINFO ti;
894 d = (afs_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
896 if (d == NULL)
897 return;
899 ZeroMemory(&ti, sizeof(ti));
900 ti.cbSize = sizeof(ti);
901 ti.hwnd = hwnd;
902 ti.uId = id;
903 SendMessage(d->tooltip, TTM_GETTOOLINFO, 0, (LPARAM) &ti);
905 ti.hinst = hResModule;
906 ti.lpszText = msg;
908 SendMessage(d->tooltip, TTM_SETTOOLINFO, 0, (LPARAM) &ti);
910 if(IS_INTRESOURCE(title)) {
911 wchar_t wbuf[1024];
912 UINT resid;
914 resid = (UINT)(UINT_PTR) title;
916 LoadString(hResModule, resid, wbuf, ARRAYLENGTH(wbuf));
917 SendMessage(d->tooltip, TTM_SETTITLE, type, (LPARAM) wbuf);
918 } else
919 SendMessage(d->tooltip, TTM_SETTITLE, type, (LPARAM) title);
921 SendMessage(d->tooltip, TTM_TRACKACTIVATE, TRUE, (LPARAM) &ti);
922 SendMessage(d->tooltip, TTM_TRACKPOSITION, 0, (LPARAM) MAKELONG(x,y));
924 d->tooltip_visible = TRUE;
926 SetTimer(hwnd, DLG_TOOLTIP_TIMER_ID, DLG_TOOLTIP_TIMEOUT, NULL);
929 void
930 nc_dlg_hide_tooltip(HWND hwnd, UINT_PTR id)
932 TOOLINFO ti;
933 afs_dlg_data * d;
935 d = (afs_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
937 if (d == NULL)
938 return;
940 if(!d->tooltip_visible)
941 return;
943 ZeroMemory(&ti, sizeof(ti));
944 ti.cbSize = sizeof(ti);
945 ti.hwnd = hwnd;
946 ti.uId = id;
948 SendMessage(d->tooltip, TTM_TRACKACTIVATE, FALSE, (LPARAM) &ti);
949 d->tooltip_visible = FALSE;
952 void
953 afs_dlg_update_rows(HWND hwnd, afs_dlg_data * d) {
954 HWND hwlist;
955 LVITEM lvi;
956 wchar_t wauto[256];
957 int i;
959 CheckDlgButton(hwnd, IDC_NCAFS_OBTAIN,
960 (d->afs_enabled)? BST_CHECKED: BST_UNCHECKED);
962 hwlist = GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST);
964 ListView_DeleteAllItems(hwlist);
966 if(d->creds.n_rows == 0)
967 return;
969 LoadString(hResModule, IDS_NC_AUTO, wauto, ARRAYLENGTH(wauto));
971 for(i=0; i < d->creds.n_rows; i++) {
972 wchar_t wbuf[256];
973 int flags;
975 ZeroMemory(&lvi, sizeof(lvi));
977 lvi.mask = LVIF_TEXT | LVIF_PARAM | LVIF_STATE;
978 lvi.iItem = d->creds.n_rows + 1;
980 lvi.stateMask = LVIS_STATEIMAGEMASK;
981 flags = d->creds.rows[i].flags;
982 if ((flags & DLGROW_FLAG_EXISTS) &&
983 (flags & DLGROW_FLAG_NOTOWNED)) {
984 lvi.state = INDEXTOSTATEIMAGEMASK(d->idx_bad_token);
985 } else if ((flags & DLGROW_FLAG_EXISTS)) {
986 lvi.state = INDEXTOSTATEIMAGEMASK(d->idx_existing_token);
987 } else {
988 lvi.state = INDEXTOSTATEIMAGEMASK(d->idx_new_token);
991 lvi.lParam = (LPARAM) i;
993 lvi.iSubItem = NCAFS_IDX_CELL;
994 lvi.pszText = d->creds.rows[i].cell;
996 lvi.iItem = ListView_InsertItem(hwlist, &lvi);
998 lvi.mask = LVIF_TEXT; /* subitems dislike lParam */
999 lvi.iSubItem = NCAFS_IDX_REALM;
1000 if(d->creds.rows[i].realm != NULL)
1001 lvi.pszText = d->creds.rows[i].realm;
1002 else
1003 lvi.pszText = wauto;
1004 ListView_SetItem(hwlist, &lvi);
1006 lvi.iSubItem = NCAFS_IDX_METHOD;
1007 afs_method_describe(d->creds.rows[i].method,
1008 KCDB_TS_SHORT,
1009 wbuf, sizeof(wbuf));
1010 lvi.pszText = wbuf;
1012 ListView_SetItem(hwlist, &lvi);
1016 void
1017 nc_dlg_del_token(HWND hwnd) {
1018 afs_dlg_data * d;
1019 khui_new_creds_by_type * nct;
1021 d = (afs_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
1023 if (d == NULL)
1024 return;
1026 if (d->nc)
1027 khui_cw_find_type(d->nc, afs_credtype_id, &nct);
1029 if(ListView_GetSelectedCount(GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST)) == 0) {
1030 wchar_t cell[KCDB_MAXCCH_NAME];
1031 int i;
1033 /* nothing is selected in the list view */
1034 /* we delete the row that matches the current contents of the
1035 cell edit control */
1036 cell[0] = 0;
1037 GetDlgItemText(hwnd, IDC_NCAFS_CELL, cell, ARRAYLENGTH(cell));
1038 for(i=0; i<d->creds.n_rows; i++) {
1039 if(!_wcsicmp(d->creds.rows[i].cell, cell)) {
1040 /* found it */
1041 afs_cred_delete_row(&d->creds, i);
1042 afs_dlg_update_rows(hwnd, d);
1043 d->dirty = TRUE;
1044 break;
1047 } else {
1048 /* something is selected in the token list view */
1049 /* we delete that */
1050 HWND hw;
1051 LVITEM lvi;
1052 int idx;
1053 int row;
1054 BOOL deleted = FALSE;
1056 hw = GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST);
1057 idx = -1;
1058 do {
1059 idx = ListView_GetNextItem(hw, idx, LVNI_SELECTED);
1060 if(idx >= 0) {
1061 ZeroMemory(&lvi, sizeof(lvi));
1062 lvi.iItem = idx;
1063 lvi.iSubItem = 0;
1064 lvi.mask = LVIF_PARAM;
1065 if(!ListView_GetItem(hw, &lvi))
1066 continue;
1067 row = (int) lvi.lParam;
1068 if(row >= 0 && row < d->creds.n_rows) {
1069 d->creds.rows[row].flags |= DLGROW_FLAG_DELETED;
1070 deleted = TRUE;
1073 } while(idx != -1);
1075 if(deleted) {
1076 for(idx = 0; idx < d->creds.n_rows; idx ++) {
1077 if(d->creds.rows[idx].flags & DLGROW_FLAG_DELETED) {
1078 afs_cred_delete_row(&d->creds, idx);
1079 idx--; /* we have to look at the current item again */
1083 d->dirty = TRUE;
1084 afs_dlg_update_rows(hwnd, d);
1088 if (d->nc)
1089 SendMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY,
1090 MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0);
1091 else if (d->config_dlg && d->dirty)
1092 khui_cfg_set_flags_inst(&d->cfg, KHUI_CNFLAG_MODIFIED,
1093 KHUI_CNFLAG_MODIFIED);
1096 void
1097 nc_dlg_add_token(HWND hwnd) {
1098 afs_dlg_data * d;
1099 afs_cred_row * prow;
1100 afs_cred_row trow;
1101 khui_new_creds_by_type * nct;
1102 wchar_t buf[256];
1103 int idx;
1104 size_t n;
1105 size_t cb;
1106 int i;
1107 BOOL new_row = FALSE;
1108 khm_handle ident = NULL;
1110 d = (afs_dlg_data *)(LONG_PTR) GetWindowLongPtr(hwnd, DWLP_USER);
1112 if (d == NULL)
1113 return;
1115 if (d->nc)
1116 khui_cw_find_type(d->nc, afs_credtype_id, &nct);
1117 else
1118 nct = NULL;
1120 if((n = SendDlgItemMessage(hwnd, IDC_NCAFS_CELL, WM_GETTEXT,
1121 (WPARAM) ARRAYLENGTH(buf), (LPARAM) buf))
1122 == 0)
1124 /* probably should indicate that user should type something */
1125 RECT r;
1126 GetWindowRect(GetDlgItem(hwnd, IDC_NCAFS_CELL), &r);
1127 nc_dlg_show_tooltip(hwnd,
1129 MAKEINTRESOURCE(IDS_NC_TT_NO_CELL),
1130 MAKEINTRESOURCE(IDS_NC_TT_CANT_ADD),
1131 2, (r.left + r.right)/ 2, r.bottom);
1132 return;
1135 if(n != wcsspn(buf, AFS_VALID_CELL_CHARS)) {
1136 RECT r;
1137 GetWindowRect(GetDlgItem(hwnd, IDC_NCAFS_CELL), &r);
1138 nc_dlg_show_tooltip(hwnd,
1140 MAKEINTRESOURCE(IDS_NC_TT_MALFORMED_CELL),
1141 MAKEINTRESOURCE(IDS_NC_TT_CANT_ADD),
1142 2, (r.left + r.right)/2, r.bottom);
1143 return;
1146 /* check if this is already listed */
1147 for(i=0;i<d->creds.n_rows;i++) {
1148 if(!_wcsicmp(buf, d->creds.rows[i].cell))
1149 break;
1152 if(i < d->creds.n_rows) {
1153 new_row = FALSE;
1155 prow = &(d->creds.rows[i]);
1156 } else {
1157 new_row = TRUE;
1158 prow = NULL;
1161 ZeroMemory(&trow, sizeof(trow));
1163 cb = (n+1) * sizeof(wchar_t);
1164 trow.cell = PMALLOC(cb);
1165 StringCbCopy(trow.cell, cb, buf);
1167 /* now for the realm */
1168 do {
1169 idx = (int) SendDlgItemMessage(hwnd, IDC_NCAFS_REALM,
1170 CB_GETCURSEL, 0, 0);
1171 if(idx != CB_ERR) {
1172 int lp;
1173 lp = (int) SendDlgItemMessage(hwnd, IDC_NCAFS_REALM,
1174 CB_GETITEMDATA, idx, 0);
1175 if(lp != CB_ERR && lp) /* this is the 'determine realm
1176 automatically' item */
1178 trow.realm = NULL;
1179 break;
1183 if((n = SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, WM_GETTEXT,
1184 ARRAYLENGTH(buf), (LPARAM) buf)) == 0) {
1185 RECT r;
1186 GetWindowRect(GetDlgItem(hwnd, IDC_NCAFS_REALM), &r);
1187 nc_dlg_show_tooltip(hwnd,
1189 MAKEINTRESOURCE(IDS_NC_TT_NO_REALM),
1190 MAKEINTRESOURCE((new_row)?
1191 IDS_NC_TT_CANT_ADD:
1192 IDS_NC_TT_CANT_UPDATE),
1193 2, (r.left + r.right)/2, r.bottom);
1194 goto _error_exit;
1197 if(n != wcsspn(buf, AFS_VALID_REALM_CHARS)) {
1198 RECT r;
1199 GetWindowRect(GetDlgItem(hwnd, IDC_NCAFS_REALM), &r);
1200 nc_dlg_show_tooltip(hwnd,
1202 MAKEINTRESOURCE(IDS_NC_TT_MALFORMED_REALM),
1203 MAKEINTRESOURCE((new_row)?
1204 IDS_NC_TT_CANT_ADD:
1205 IDS_NC_TT_CANT_UPDATE),
1206 2, (r.left + r.right)/2, r.bottom);
1207 goto _error_exit;
1210 cb = (n+1) * sizeof(wchar_t);
1211 trow.realm = PMALLOC(cb);
1212 StringCbCopy(trow.realm, cb, buf);
1214 } while(FALSE);
1216 idx = (int)SendDlgItemMessage(hwnd, IDC_NCAFS_METHOD,
1217 CB_GETCURSEL, 0, 0);
1218 if (idx != CB_ERR) {
1219 trow.method = (afs_tk_method)
1220 SendDlgItemMessage(hwnd, IDC_NCAFS_METHOD, CB_GETITEMDATA,
1221 idx, 0);
1222 } else {
1223 trow.method = AFS_TOKEN_AUTO;
1226 if (d->nc &&
1227 d->nc->n_identities > 0 &&
1228 d->nc->identities[0]) {
1230 ident = d->nc->identities[0];
1232 } else if (d->ident) {
1234 ident = d->ident;
1238 if(new_row) {
1239 khm_boolean ok_to_add = TRUE;
1241 if (ident) {
1242 khm_handle id_conf = NULL;
1244 ok_to_add =
1245 afs_check_add_token_to_identity(trow.cell,
1246 ident,
1247 &id_conf);
1249 if (!ok_to_add) {
1250 #if KH_VERSION_API >= 5
1251 khui_alert * a;
1252 wchar_t wbuf[512];
1253 wchar_t wfmt[128];
1254 wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
1255 khm_size cb;
1257 #ifdef DEBUG
1258 assert(id_conf);
1259 #endif
1260 khui_alert_create_empty(&a);
1262 cb = sizeof(widname);
1263 kcdb_identity_get_name(id_conf, widname, &cb);
1265 LoadString(hResModule, IDS_NC_TT_CONFLICT,
1266 wfmt, ARRAYLENGTH(wfmt));
1267 StringCbPrintf(wbuf, sizeof(wbuf),
1268 wfmt, trow.cell, widname);
1269 khui_alert_set_message(a, wbuf);
1271 LoadString(hResModule, IDS_NC_TT_PROBLEM,
1272 wbuf, ARRAYLENGTH(wbuf));
1273 khui_alert_set_title(a, wbuf);
1275 khui_alert_add_command(a, KHUI_PACTION_KEEP);
1276 khui_alert_add_command(a, KHUI_PACTION_REMOVE);
1277 khui_alert_add_command(a, KHUI_PACTION_CANCEL);
1279 khui_alert_set_severity(a, KHERR_INFO);
1281 khui_alert_show_modal(a);
1283 ok_to_add = TRUE;
1285 if (a->response == KHUI_PACTION_REMOVE) {
1286 afs_remove_token_from_identities(trow.cell);
1287 } else if (a->response == KHUI_PACTION_CANCEL) {
1288 ok_to_add = FALSE;
1291 khui_alert_release(a);
1292 #else
1293 wchar_t widname[KCDB_IDENT_MAXCCH_NAME];
1294 wchar_t wtitle[64];
1295 wchar_t wmsg[512];
1296 wchar_t wfmt[128];
1297 khm_size cb;
1298 int r;
1300 #ifdef DEBUG
1301 assert(id_conf);
1302 #endif
1304 cb = sizeof(widname);
1305 kcdb_identity_get_name(id_conf, widname, &cb);
1306 LoadString(hResModule, IDS_NC_TT_PROBLEM,
1307 wtitle, ARRAYLENGTH(wtitle));
1308 LoadString(hResModule, IDS_NC_TT_CONFLICTM,
1309 wfmt, ARRAYLENGTH(wfmt));
1310 StringCbPrintf(wmsg, sizeof(wmsg), wfmt,
1311 trow.cell, widname);
1312 r = MessageBox(NULL, wmsg, wtitle,
1313 MB_YESNOCANCEL | MB_ICONWARNING |
1314 MB_APPLMODAL);
1316 ok_to_add = TRUE;
1317 if (r == IDNO) {
1318 afs_remove_token_from_identities(trow.cell);
1319 } else if (r == IDCANCEL) {
1320 ok_to_add = FALSE;
1322 #endif
1324 kcdb_identity_release(id_conf);
1327 if (!ok_to_add)
1328 goto _error_exit;
1331 prow = afs_cred_get_new_row(&d->creds);
1332 } else {
1333 if (prow->cell)
1334 PFREE(prow->cell);
1336 if(prow->realm)
1337 PFREE(prow->realm);
1339 ZeroMemory(prow, sizeof(*prow));
1342 *prow = trow;
1344 if (ident) {
1345 afs_ident_token_set ts;
1347 ts.ident = ident;
1348 ts.l = &d->creds;
1349 ts.add_new = FALSE;
1350 ts.update_info = FALSE;
1352 kcdb_credset_apply(NULL, afs_get_id_creds_apply_proc,
1353 &ts);
1356 afs_dlg_update_rows(hwnd, d);
1358 d->dirty = TRUE;
1360 if (d->nc)
1361 SendMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY,
1362 MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0);
1363 else if (d->config_dlg) {
1364 khui_cfg_set_flags_inst(&d->cfg,
1365 KHUI_CNFLAG_MODIFIED,
1366 KHUI_CNFLAG_MODIFIED);
1369 return;
1371 _error_exit:
1372 if(trow.realm)
1373 PFREE(trow.realm);
1374 if(trow.cell)
1375 PFREE(trow.cell);
1378 /* this is shared between the new credentials window and the AFS per
1379 identity configuration dialog. */
1380 INT_PTR CALLBACK
1381 afs_dlg_proc(HWND hwnd,
1382 UINT uMsg,
1383 WPARAM wParam,
1384 LPARAM lParam)
1386 switch(uMsg) {
1387 case WM_INITDIALOG:
1389 HWND hw;
1390 HIMAGELIST hw_ilist;
1391 afs_dlg_data * d;
1392 khui_new_creds_by_type * nct = NULL;
1393 RECT r;
1395 d = PMALLOC(sizeof(*d));
1396 ZeroMemory(d, sizeof(*d));
1398 InitializeCriticalSection(&d->cs);
1400 /* lParam is a pointer to a khui_new_creds structure */
1401 d->nc = (khui_new_creds *) lParam;
1403 if (d->nc)
1404 khui_cw_find_type(d->nc, afs_credtype_id, &nct);
1406 #pragma warning(push)
1407 #pragma warning(disable: 4244)
1408 SetWindowLongPtr(hwnd, DWLP_USER, (LPARAM) d);
1409 #pragma warning(pop)
1411 EnterCriticalSection(&d->cs);
1413 if (nct)
1414 nct->aux = (LPARAM) d;
1416 /* create the tooltip window */
1417 d->tooltip =
1418 CreateWindowEx(WS_EX_TOPMOST,
1419 TOOLTIPS_CLASS,
1420 NULL,
1421 WS_POPUP | TTS_BALLOON | TTS_ALWAYSTIP,
1422 CW_USEDEFAULT, CW_USEDEFAULT,
1423 CW_USEDEFAULT, CW_USEDEFAULT,
1424 hwnd, /* make this an owned window, so
1425 we don't have to worry about
1426 destroying it */
1427 NULL,
1428 hInstance,
1429 NULL);
1431 SetWindowPos(d->tooltip,
1432 HWND_TOPMOST,
1437 SWP_NOMOVE | SWP_NOSIZE | SWP_NOACTIVATE);
1440 TOOLINFO ti;
1442 ZeroMemory(&ti, sizeof(ti));
1443 ti.cbSize = sizeof(ti);
1444 ti.uFlags = TTF_TRACK;
1445 ti.hwnd = hwnd;
1446 ti.uId = 0;
1447 ti.hinst = hResModule;
1448 ti.lpszText = L"";
1449 GetClientRect(hwnd, &(ti.rect));
1451 SendMessage(d->tooltip, TTM_ADDTOOL, 0, (LPARAM) &ti);
1454 /* we only initialize the constant bits here. */
1455 hw = GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST);
1457 GetClientRect(hw, &r);
1459 /* set the list view status icons */
1460 hw_ilist = ImageList_Create(GetSystemMetrics(SM_CXSMICON),
1461 GetSystemMetrics(SM_CYSMICON),
1462 ILC_COLOR8 | ILC_MASK,
1463 4, 4);
1464 #ifdef DEBUG
1465 assert(hw_ilist);
1466 #endif
1468 HICON hi;
1470 hi = LoadImage(hResModule, MAKEINTRESOURCE(IDI_NC_NEW),
1471 IMAGE_ICON,
1472 GetSystemMetrics(SM_CXSMICON),
1473 GetSystemMetrics(SM_CYSMICON),
1474 LR_DEFAULTCOLOR);
1476 d->idx_new_token = ImageList_AddIcon(hw_ilist, hi) + 1;
1478 DestroyIcon(hi);
1480 hi = LoadImage(hResModule, MAKEINTRESOURCE(IDI_NC_EXIST),
1481 IMAGE_ICON,
1482 GetSystemMetrics(SM_CXSMICON),
1483 GetSystemMetrics(SM_CYSMICON),
1484 LR_DEFAULTCOLOR);
1485 d->idx_existing_token = ImageList_AddIcon(hw_ilist, hi) + 1;
1487 DestroyIcon(hi);
1489 hi = LoadImage(hResModule,
1490 MAKEINTRESOURCE(IDI_NC_NOTOWNED),
1491 IMAGE_ICON,
1492 GetSystemMetrics(SM_CXSMICON),
1493 GetSystemMetrics(SM_CYSMICON),
1494 LR_DEFAULTCOLOR);
1495 d->idx_bad_token = ImageList_AddIcon(hw_ilist, hi) + 1 ;
1497 DestroyIcon(hi);
1500 ListView_SetImageList(hw, hw_ilist, LVSIL_STATE);
1502 ListView_DeleteAllItems(hw);
1504 /* set the columns */
1506 LVCOLUMN lc;
1507 wchar_t wbuf[256];
1509 lc.mask = LVCF_FMT | LVCF_WIDTH | LVCF_TEXT;
1510 lc.fmt = LVCFMT_LEFT;
1511 lc.cx = ((r.right - r.left) * 2) / 5;
1512 LoadString(hResModule, IDS_NCAFS_COL_CELL,
1513 wbuf, ARRAYLENGTH(wbuf));
1514 lc.pszText = wbuf;
1516 ListView_InsertColumn(hw, 0, &lc);
1518 lc.mask |= LVCF_SUBITEM;
1519 //lc.cx is the same as above
1520 lc.iSubItem = NCAFS_IDX_REALM;
1521 LoadString(hResModule, IDS_NCAFS_COL_REALM,
1522 wbuf, ARRAYLENGTH(wbuf));
1524 ListView_InsertColumn(hw, 1, &lc);
1526 lc.cx = ((r.right - r.left) * 1) / 5;
1527 lc.iSubItem = NCAFS_IDX_METHOD;
1528 LoadString(hResModule, IDS_NCAFS_COL_METHOD,
1529 wbuf, ARRAYLENGTH(wbuf));
1531 ListView_InsertColumn(hw, 2, &lc);
1534 /* Set the items for the 'method' combo box */
1535 hw = GetDlgItem(hwnd, IDC_NCAFS_METHOD);
1538 wchar_t wbuf[KHUI_MAXCB_SHORT_DESC];
1539 afs_tk_method method = -1;
1540 int idx;
1542 SendMessage(hw, CB_RESETCONTENT, 0, 0);
1544 while((method = afs_get_next_method_id(method)) >= 0) {
1545 afs_method_describe(method, KCDB_TS_SHORT,
1546 wbuf, sizeof(wbuf));
1547 idx = (int)SendMessage(hw, CB_INSERTSTRING,
1548 (WPARAM) -1, (LPARAM) wbuf);
1549 #ifdef DEBUG
1550 assert(idx != CB_ERR);
1551 #endif
1552 SendMessage(hw, CB_SETITEMDATA, (WPARAM) idx,
1553 (LPARAM) method);
1556 /* finally, set the current selection to auto, which
1557 is the first method returned by
1558 afs_get_next_method_id() */
1559 SendMessage(hw, CB_SETCURSEL, 0, 0);
1562 d->afs_enabled = TRUE;
1563 SendDlgItemMessage(hwnd, IDC_NCAFS_OBTAIN,
1564 BM_SETCHECK, BST_CHECKED, 0);
1566 SendDlgItemMessage(hwnd, IDC_NCAFS_CELL, CB_LIMITTEXT, MAXCELLCHARS-1, 0);
1567 SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, CB_LIMITTEXT, MAXKTCREALMLEN-1, 0);
1568 SendDlgItemMessage(hwnd, IDC_NCAFS_METHOD, CB_LIMITTEXT, KCDB_MAXCCH_NAME-1, 0);
1570 LeaveCriticalSection(&d->cs);
1572 /* the cells and realms combo boxes need to be filled
1573 in the plugin thread since that requires making
1574 potentially blocking and non-thread safe calls */
1576 return TRUE;
1578 case WM_DESTROY:
1580 afs_dlg_data * d;
1581 khui_new_creds_by_type * nct;
1583 d = (afs_dlg_data *)(LONG_PTR)
1584 GetWindowLongPtr(hwnd, DWLP_USER);
1586 if (d == NULL)
1587 return TRUE;
1589 EnterCriticalSection(&d->cs);
1591 if (d->nc) {
1592 khui_cw_find_type(d->nc, afs_credtype_id, &nct);
1594 nct->aux = (LPARAM) NULL;
1597 afs_cred_free_rows(&d->creds);
1599 LeaveCriticalSection(&d->cs);
1600 DeleteCriticalSection(&d->cs);
1602 PFREE(d);
1604 SetWindowLongPtr(hwnd, DWLP_USER, 0);
1606 return TRUE;
1608 case WM_COMMAND:
1610 afs_dlg_data * d;
1611 khui_new_creds_by_type * nct;
1613 d = (afs_dlg_data *)(LONG_PTR)
1614 GetWindowLongPtr(hwnd, DWLP_USER);
1616 if (d == NULL)
1617 return FALSE;
1619 EnterCriticalSection(&d->cs);
1621 if (d->nc)
1622 khui_cw_find_type(d->nc, afs_credtype_id, &nct);
1623 else
1624 nct = NULL;
1626 nc_dlg_hide_tooltip(hwnd, 0);
1628 /* Handle WM_COMMAND */
1629 switch(wParam) {
1630 case MAKEWPARAM(IDC_NCAFS_OBTAIN, BN_CLICKED):
1632 BOOL c;
1633 c = (SendDlgItemMessage(hwnd, IDC_NCAFS_OBTAIN,
1634 BM_GETCHECK, 0, 0)
1635 == BST_CHECKED);
1636 d->afs_enabled = c;
1637 d->dirty = TRUE;
1638 if (d->nc)
1639 khui_cw_enable_type(d->nc, afs_credtype_id, c);
1640 else if (d->config_dlg)
1641 khui_cfg_set_flags_inst(&d->cfg,
1642 KHUI_CNFLAG_MODIFIED,
1643 KHUI_CNFLAG_MODIFIED);
1644 nc_dlg_enable(hwnd, c);
1646 break;
1648 case MAKEWPARAM(IDC_NCAFS_ADD_TOKEN, BN_CLICKED):
1650 nc_dlg_add_token(hwnd);
1652 break;
1654 case MAKEWPARAM(IDC_NCAFS_DELETE_TOKEN, BN_CLICKED):
1656 nc_dlg_del_token(hwnd);
1658 break;
1661 LeaveCriticalSection(&d->cs);
1663 return TRUE;
1665 case KHUI_WM_NC_NOTIFY:
1667 afs_dlg_data * d;
1668 khui_new_creds_by_type * nct;
1670 d = (afs_dlg_data *)(LONG_PTR)
1671 GetWindowLongPtr(hwnd, DWLP_USER);
1673 if (d == NULL)
1674 return TRUE;
1676 EnterCriticalSection(&d->cs);
1678 if (d->nc)
1679 khui_cw_find_type(d->nc, afs_credtype_id, &nct);
1680 else
1681 nct = NULL;
1683 switch(HIWORD(wParam)) {
1684 case WMNC_DIALOG_SETUP:
1686 SendDlgItemMessage(hwnd, IDC_NCAFS_CELL,
1687 CB_RESETCONTENT, 0, 0);
1689 /* load the LRU cells */
1691 wchar_t * buf;
1692 wchar_t *s;
1693 khm_size cbbuf;
1695 if(khc_read_multi_string(csp_params, L"LRUCells",
1696 NULL, &cbbuf) ==
1697 KHM_ERROR_TOO_LONG) {
1698 buf = PMALLOC(cbbuf);
1699 khc_read_multi_string(csp_params, L"LRUCells",
1700 buf, &cbbuf);
1701 s = buf;
1702 while(*s) {
1703 SendDlgItemMessage(hwnd, IDC_NCAFS_CELL,
1704 CB_ADDSTRING, 0, (LPARAM) s);
1705 s += wcslen(s) + 1;
1707 PFREE(buf);
1711 /* now, if the root cell is not in the LRU, add it */
1713 char buf[256];
1714 wchar_t wbuf[256];
1716 if(!cm_GetRootCellName(buf)) {
1717 AnsiStrToUnicode(wbuf, sizeof(wbuf), buf);
1718 if(SendDlgItemMessage(hwnd,
1719 IDC_NCAFS_CELL,
1720 CB_FINDSTRINGEXACT,
1721 (WPARAM) -1,
1722 (LPARAM) wbuf) == CB_ERR) {
1723 SendDlgItemMessage(hwnd, IDC_NCAFS_CELL,
1724 CB_ADDSTRING,
1725 0, (LPARAM) wbuf);
1727 SendDlgItemMessage(hwnd, IDC_NCAFS_CELL,
1728 CB_SELECTSTRING,
1729 (WPARAM)-1, (LPARAM) wbuf);
1733 SendDlgItemMessage(hwnd, IDC_NCAFS_REALM,
1734 CB_RESETCONTENT, 0, 0);
1736 /* as for the realms, we have a special one here */
1738 wchar_t wbuf[256];
1739 int idx;
1741 LoadString(hResModule, IDS_NC_REALM_AUTO, wbuf,
1742 (int) ARRAYLENGTH(wbuf));
1743 idx = (int) SendDlgItemMessage(hwnd, IDC_NCAFS_REALM,
1744 CB_ADDSTRING, 0,
1745 (LPARAM) wbuf);
1746 /* item data for the realm strings is the
1747 answer to the question, "is this the
1748 'determine realm automatically' item?" */
1749 SendDlgItemMessage(hwnd, IDC_NCAFS_REALM,
1750 CB_SETITEMDATA, idx, TRUE);
1751 SendDlgItemMessage(hwnd, IDC_NCAFS_REALM,
1752 CB_SELECTSTRING,
1753 (WPARAM)-1, (LPARAM) wbuf);
1756 /* load the LRU realms */
1758 wchar_t * buf;
1759 wchar_t *s;
1760 int idx;
1761 khm_size cbbuf;
1763 if(khc_read_multi_string(csp_params, L"LRURealms",
1764 NULL, &cbbuf) ==
1765 KHM_ERROR_TOO_LONG) {
1766 buf = PMALLOC(cbbuf);
1767 khc_read_multi_string(csp_params, L"LRURealms",
1768 buf, &cbbuf);
1769 s = buf;
1770 while(*s) {
1771 if(SendDlgItemMessage(hwnd, IDC_NCAFS_REALM,
1772 CB_FINDSTRINGEXACT,
1773 (WPARAM)-1,
1774 (LPARAM) s) == CB_ERR) {
1775 idx =
1776 (int)
1777 SendDlgItemMessage(hwnd,
1778 IDC_NCAFS_REALM,
1779 CB_ADDSTRING,
1780 0, (LPARAM) s);
1781 SendDlgItemMessage(hwnd, IDC_NCAFS_REALM,
1782 CB_SETITEMDATA,
1783 idx, FALSE);
1786 s += wcslen(s) + 1;
1788 PFREE(buf);
1792 if (d->nc)
1793 khui_cw_enable_type(d->nc, afs_credtype_id,
1794 d->afs_enabled);
1796 nc_dlg_enable(hwnd, d->afs_enabled);
1798 afs_dlg_update_rows(hwnd, d);
1800 break;
1802 case WMNC_UPDATE_CREDTEXT:
1804 wchar_t wformat[256];
1805 wchar_t wstr[2048];
1806 khm_int32 flags;
1808 if(nct->credtext) {
1809 PFREE(nct->credtext);
1810 nct->credtext = NULL;
1813 #ifdef DEBUG
1814 assert(d->nc);
1815 #endif
1817 if (d->nc->n_identities == 0 ||
1818 KHM_FAILED(kcdb_identity_get_flags(d->nc->identities[0],
1819 &flags)) ||
1820 !(flags & KCDB_IDENT_FLAG_VALID))
1821 /* in this case, we don't show any credential text */
1822 break;
1824 wstr[0] = 0;
1826 if(!d->afs_enabled) {
1827 LoadString(hResModule, IDS_AFS_CREDTEXT_DIS,
1828 wstr, ARRAYLENGTH(wstr));
1829 } else {
1830 if(d->creds.n_rows == 0) {
1831 LoadString(hResModule, IDS_AFS_CREDTEXT_0,
1832 wstr, ARRAYLENGTH(wstr));
1833 } else if(d->creds.n_rows == 1) {
1834 LoadString(hResModule, IDS_AFS_CREDTEXT_1,
1835 wformat, ARRAYLENGTH(wformat));
1836 StringCbPrintf(wstr, sizeof(wstr), wformat,
1837 d->creds.rows[0].cell);
1838 } else {
1839 int i;
1840 wchar_t wcells[1024];
1842 LoadString(hResModule, IDS_AFS_CREDTEXT_N,
1843 wformat, ARRAYLENGTH(wformat));
1844 wcells[0] = 0;
1845 for(i=0; i<d->creds.n_rows; i++) {
1846 if(i > 0)
1847 StringCbCat(wcells, sizeof(wcells),
1848 L", ");
1849 if(FAILED(StringCbCat(wcells,
1850 sizeof(wcells),
1851 d->creds.rows[i].cell))) {
1852 size_t cch;
1853 /* looks like we overflowed */
1854 /* add an ellipsis at the end */
1855 StringCchLength(wcells, ARRAYLENGTH(wcells), &cch);
1856 cch = min(ARRAYLENGTH(wcells) - 4, cch);
1857 StringCchCopy(wcells + cch, 4, L"...");
1859 break;
1863 StringCbPrintf(wstr, sizeof(wstr), wformat, wcells);
1867 if(wstr[0] != 0) {
1868 size_t cbs;
1869 StringCbLength(wstr, sizeof(wstr), &cbs);
1870 cbs += sizeof(wchar_t);
1871 assert(nct->credtext == NULL);
1872 nct->credtext = PMALLOC(cbs);
1873 StringCbCopy(nct->credtext, cbs, wstr);
1874 } else {
1875 /* something went wrong */
1876 nct->credtext = NULL;
1879 break;
1881 case WMNC_CREDTEXT_LINK:
1883 khui_htwnd_link * l;
1884 wchar_t wid[KHUI_MAXCCH_HTLINK_FIELD];
1885 wchar_t * wids;
1887 l = (khui_htwnd_link *) lParam;
1889 StringCchCopyN(wid, ARRAYLENGTH(wid), l->id, l->id_len);
1890 wids = wcschr(wid, L':');
1892 if(!wids)
1893 break;
1894 else
1895 wids++;
1897 #ifdef DEBUG
1898 assert(d->nc);
1899 #endif
1901 if(!wcscmp(wids, L"Enable")) {
1902 SendDlgItemMessage(hwnd, IDC_NCAFS_OBTAIN,
1903 BM_SETCHECK, BST_CHECKED, 0);
1904 d->afs_enabled = TRUE;
1905 khui_cw_enable_type(d->nc, afs_credtype_id, TRUE);
1906 nc_dlg_enable(hwnd, TRUE);
1909 break;
1911 case WMNC_IDENTITY_CHANGE:
1912 kmq_post_sub_msg(afs_sub, KMSG_CRED,
1913 KMSG_CRED_DIALOG_NEW_IDENTITY, 0,
1914 (void *) d->nc);
1915 break;
1917 case WMNC_AFS_UPDATE_ROWS:
1918 afs_dlg_update_rows(hwnd, d);
1920 #ifdef DEBUG
1921 assert(d->nc);
1922 #endif
1924 PostMessage(d->nc->hwnd, KHUI_WM_NC_NOTIFY,
1925 MAKEWPARAM(0, WMNC_UPDATE_CREDTEXT), 0);
1926 break;
1929 LeaveCriticalSection(&d->cs);
1931 return TRUE;
1933 case WM_NOTIFY:
1934 if(wParam == IDC_NCAFS_TOKENLIST) {
1935 LPNMHDR lpnmh = (LPNMHDR) lParam;
1937 if(lpnmh->code == LVN_ITEMCHANGED) {
1938 /* when an item in the list view is clicked, we
1939 load the corresponding values into the edit and
1940 combo boxes */
1941 NMLISTVIEW *lpnmlv = (NMLISTVIEW *) lpnmh;
1942 LVITEM lvi;
1943 HWND hw;
1944 int idx;
1945 int row;
1946 afs_dlg_data * d;
1948 if (!(lpnmlv->uChanged & LVIF_STATE) ||
1949 !(lpnmlv->uNewState & LVIS_SELECTED) ||
1950 (lpnmlv->iItem == -1))
1952 return TRUE;
1954 d = (afs_dlg_data *)(LONG_PTR)
1955 GetWindowLongPtr(hwnd, DWLP_USER);
1957 if (d == NULL)
1958 return FALSE;
1960 EnterCriticalSection(&d->cs);
1962 hw = GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST);
1964 idx = lpnmlv->iItem;
1966 ZeroMemory(&lvi, sizeof(lvi));
1967 lvi.iItem = idx;
1968 lvi.iSubItem = 0;
1969 lvi.mask = LVIF_PARAM;
1971 if(!ListView_GetItem(hw, &lvi))
1972 goto _done_notify_select;
1974 /* ok, now lvi.lParam should be the row of the token */
1975 row = (int) lvi.lParam;
1976 if(row < 0 || row >= d->creds.n_rows)
1977 goto _done_notify_select;
1979 SetDlgItemText(hwnd, IDC_NCAFS_CELL,
1980 d->creds.rows[row].cell);
1981 if(d->creds.rows[row].realm != NULL) {
1982 SetDlgItemText(hwnd, IDC_NCAFS_REALM,
1983 d->creds.rows[row].realm);
1984 } else {
1985 wchar_t wbuf[256];
1986 int idx;
1988 LoadString(hResModule, IDS_NC_REALM_AUTO, wbuf,
1989 ARRAYLENGTH(wbuf));
1990 idx = (int) SendDlgItemMessage(hwnd, IDC_NCAFS_REALM,
1991 CB_FINDSTRINGEXACT,
1992 (WPARAM) -1,
1993 (LPARAM) wbuf);
1994 SendDlgItemMessage(hwnd, IDC_NCAFS_REALM, CB_SETCURSEL,
1995 idx, 0);
1997 SendDlgItemMessage(hwnd, IDC_NCAFS_METHOD, CB_SETCURSEL,
1998 d->creds.rows[row].method, 0);
1999 _done_notify_select:
2000 LeaveCriticalSection(&d->cs);
2002 } else if (lpnmh->code == NM_DBLCLK) {
2004 LPNMITEMACTIVATE pnmi;
2005 LVITEM lvi;
2006 HWND hw;
2007 afs_dlg_data * d;
2008 int row;
2009 int x,y;
2010 RECT r;
2012 d = (afs_dlg_data *)(LONG_PTR)
2013 GetWindowLongPtr(hwnd, DWLP_USER);
2015 if (d == NULL)
2016 return FALSE;
2018 EnterCriticalSection(&d->cs);
2020 pnmi = (LPNMITEMACTIVATE) lpnmh;
2022 hw = GetDlgItem(hwnd, IDC_NCAFS_TOKENLIST);
2024 ZeroMemory(&lvi, sizeof(lvi));
2025 lvi.iItem = pnmi->iItem;
2026 lvi.iSubItem = 0;
2027 lvi.mask = LVIF_PARAM;
2029 if (!ListView_GetItem(hw, &lvi))
2030 goto _done_notify_click;
2032 row = (int) lvi.lParam;
2033 if(row < 0 || row >= d->creds.n_rows)
2034 goto _done_notify_click;
2036 ListView_GetItemRect(hw, pnmi->iItem, &r, LVIR_SELECTBOUNDS);
2037 x = (r.left + r.right) / 2;
2038 y = (r.bottom);
2040 GetWindowRect(hw, &r);
2041 y += r.top;
2042 x += r.left;
2044 if (d->creds.rows[row].flags & DLGROW_FLAG_NOTOWNED) {
2045 nc_dlg_show_tooltip(hwnd, 0,
2046 MAKEINTRESOURCE(IDS_NC_TT_CONFLICTD),
2047 MAKEINTRESOURCE(IDS_NC_TT_PROBLEM),
2049 x,y);
2050 } else if (d->creds.rows[row].flags &
2051 DLGROW_FLAG_EXPIRED) {
2052 nc_dlg_show_tooltip(hwnd, 0,
2053 MAKEINTRESOURCE(IDS_NC_TT_EXPIRED),
2054 MAKEINTRESOURCE(IDS_NC_TT_DETAILS),
2056 x, y);
2057 } else if (d->creds.rows[row].flags &
2058 DLGROW_FLAG_EXISTS) {
2059 nc_dlg_show_tooltip(hwnd, 0,
2060 MAKEINTRESOURCE(IDS_NC_TT_EXISTS),
2061 MAKEINTRESOURCE(IDS_NC_TT_DETAILS),
2062 1, x, y);
2063 } else {
2064 nc_dlg_show_tooltip(hwnd, 0,
2065 MAKEINTRESOURCE(IDS_NC_TT_NEW),
2066 MAKEINTRESOURCE(IDS_NC_TT_DETAILS),
2067 1, x, y);
2070 _done_notify_click:
2071 LeaveCriticalSection(&d->cs);
2074 return TRUE;
2076 case WM_TIMER:
2078 if(wParam == DLG_TOOLTIP_TIMER_ID) {
2079 KillTimer(hwnd, DLG_TOOLTIP_TIMER_ID);
2080 nc_dlg_hide_tooltip(hwnd, 0);
2083 return TRUE;
2085 case WM_HELP:
2087 static const DWORD ctx_help[] = {
2088 IDC_NCAFS_OBTAIN, IDH_OBTAIN,
2089 IDC_NCAFS_CELL, IDH_CELL,
2090 IDC_NCAFS_REALM, IDH_REALM,
2091 IDC_NCAFS_METHOD, IDH_METHOD,
2092 IDC_NCAFS_ADD_TOKEN, IDH_ADD,
2093 IDC_NCAFS_DELETE_TOKEN, IDH_DELETE,
2094 IDC_NCAFS_TOKENLIST, IDH_TOKENLIST,
2098 LPHELPINFO hlp;
2100 hlp = (LPHELPINFO) lParam;
2102 if (hlp->iContextType != HELPINFO_WINDOW)
2103 break;
2105 afs_html_help(hlp->hItemHandle, L"::/popups_newcred.txt",
2106 HH_TP_HELP_WM_HELP, (DWORD_PTR) ctx_help);
2108 return TRUE;
2109 } /* switch(uMsg) */
2111 return FALSE;
2115 /* passed in to kcdb_credset_apply along with the afs_credset to adjust
2116 newly acquired credentials to include informatino derived from the
2117 new creds operation */
2118 khm_int32 KHMAPI
2119 afs_adjust_token_ident_proc(khm_handle cred, void * vd)
2121 wchar_t cell[MAXCELLCHARS];
2122 afs_ident_token_set * b = (afs_ident_token_set *) vd;
2123 afs_cred_list * l;
2124 khm_size cbbuf;
2125 int i;
2127 l = b->l;
2129 /* ASSUMPTION: for each user, there can be tokens for only one
2130 cell */
2132 cbbuf = sizeof(cell);
2134 if(KHM_FAILED(kcdb_cred_get_attr(cred, afs_attr_cell, NULL, cell, &cbbuf)))
2135 return KHM_ERROR_SUCCESS; /* remember, kcdb doesn't care if
2136 this run succeeded or not. all
2137 it wants to know if whether or
2138 not we want to continue the
2139 search */
2141 for(i=0; i<l->n_rows; i++) {
2142 if((l->rows[i].flags & DLGROW_FLAG_DONE) &&
2143 !_wcsicmp(cell, l->rows[i].cell)) {
2144 khm_int32 method;
2146 kcdb_cred_set_identity(cred, b->ident);
2147 if(l->rows[i].realm)
2148 kcdb_cred_set_attr(cred, afs_attr_realm, l->rows[i].realm,
2149 (khm_size)KCDB_CBSIZE_AUTO);
2150 else
2151 kcdb_cred_set_attr(cred, afs_attr_realm, NULL, 0);
2153 method = l->rows[i].method;
2154 kcdb_cred_set_attr(cred, afs_attr_method, &method,
2155 (khm_size)KCDB_CBSIZE_AUTO);
2157 break;
2161 return KHM_ERROR_SUCCESS;
2164 void
2165 afs_cred_write_ident_data(afs_dlg_data * d) {
2166 wchar_t * lru_cell = NULL;
2167 wchar_t * lru_realm = NULL;
2168 wchar_t * id_cell = NULL;
2169 khm_size cbidcell;
2170 khm_size cbcell;
2171 khm_size cbrealm;
2172 khm_size cbt;
2173 size_t cbz;
2174 khm_handle h_idc = NULL;
2175 khm_handle h_afs = NULL;
2176 khm_handle h_acells = NULL;
2177 khm_handle h_cellmap = NULL;
2178 wchar_t idname[KCDB_IDENT_MAXCCH_NAME];
2179 khm_handle ident = NULL;
2180 afs_cred_list * l;
2181 int i;
2183 l = &d->creds;
2185 if (d->nc &&
2186 d->nc->n_identities > 0 &&
2187 d->nc->identities[0])
2189 ident = d->nc->identities[0];
2191 else if (d->config_dlg)
2193 ident = d->ident;
2195 if (!ident)
2196 return;
2198 cbt = sizeof(idname);
2199 kcdb_identity_get_name(ident, idname, &cbt);
2201 khc_open_space(csp_afscred, L"Cells", 0, &h_cellmap);
2203 if(ident) {
2204 if(KHM_SUCCEEDED(kcdb_identity_get_config(ident,
2205 KHM_FLAG_CREATE,
2206 &h_idc))) {
2207 khc_open_space(h_idc, CSNAME_AFSCRED,
2208 KHM_FLAG_CREATE, &h_afs);
2211 if(h_afs) {
2212 khc_open_space(h_afs, L"Cells", KHM_FLAG_CREATE,
2213 &h_acells);
2217 if (h_afs && d) {
2218 khc_write_int32(h_afs, L"AFSEnabled",
2219 !!d->afs_enabled);
2222 if(khc_read_multi_string(csp_params,
2223 L"LRUCells",
2224 NULL,
2225 &cbcell) == KHM_ERROR_TOO_LONG) {
2226 cbcell += MAXCELLCHARS * sizeof(wchar_t) *
2227 l->n_rows;
2228 lru_cell = PMALLOC(cbcell);
2229 ZeroMemory(lru_cell, cbcell);
2230 cbt = cbcell;
2232 khc_read_multi_string(csp_params,
2233 L"LRUCells",
2234 lru_cell,
2235 &cbt);
2236 } else {
2237 cbcell = MAXCELLCHARS * sizeof(wchar_t) * l->n_rows + sizeof(wchar_t);
2238 if (l->n_rows > 0) {
2239 lru_cell = PMALLOC(cbcell);
2240 ZeroMemory(lru_cell, cbcell);
2241 } else {
2242 lru_cell = NULL;
2243 cbcell = 0;
2247 if(khc_read_multi_string(csp_params,
2248 L"LRURealms",
2249 NULL,
2250 &cbrealm) == KHM_ERROR_TOO_LONG) {
2251 cbrealm += MAXCELLCHARS * sizeof(wchar_t) * l->n_rows;
2252 lru_realm = PMALLOC(cbrealm);
2253 ZeroMemory(lru_realm, cbrealm);
2254 cbt = cbrealm;
2256 khc_read_multi_string(csp_params,
2257 L"LRURealms",
2258 lru_realm,
2259 &cbt);
2260 } else {
2261 cbrealm = MAXCELLCHARS * sizeof(wchar_t) * l->n_rows + sizeof(wchar_t);
2262 if (l->n_rows > 0) {
2263 lru_realm = PMALLOC(cbrealm);
2264 ZeroMemory(lru_realm, cbrealm);
2265 } else {
2266 lru_cell = NULL;
2267 cbrealm = 0;
2271 cbidcell = MAXCELLCHARS * sizeof(wchar_t) * l->n_rows + sizeof(wchar_t);
2272 if (l->n_rows > 0) {
2273 id_cell = PMALLOC(cbidcell);
2274 ZeroMemory(id_cell, cbidcell);
2275 } else {
2276 id_cell = NULL;
2277 cbidcell = 0;
2280 for(i=0; i < l->n_rows; i++)
2281 if(!(l->rows[i].flags & DLGROW_FLAG_DELETED)) {
2282 khm_handle h_acell = NULL;
2284 if(!multi_string_find(lru_cell,
2285 l->rows[i].cell, 0)) {
2286 cbz = cbcell;
2287 multi_string_append(lru_cell, &cbz,
2288 l->rows[i].cell);
2291 if(l->rows[i].realm &&
2292 !multi_string_find(lru_realm,
2293 l->rows[i].realm, 0)) {
2294 cbz = cbrealm;
2295 multi_string_append(lru_realm, &cbz,
2296 l->rows[i].realm);
2299 cbz = cbidcell;
2300 multi_string_append(id_cell, &cbz,
2301 l->rows[i].cell);
2303 if(h_acells &&
2304 KHM_SUCCEEDED(khc_open_space(h_acells,
2305 l->rows[i].cell,
2306 KHM_FLAG_CREATE,
2307 &h_acell))) {
2308 wchar_t methodname[KHUI_MAXCCH_NAME];
2310 afs_get_method_name(l->rows[i].method,
2311 methodname,
2312 sizeof(methodname));
2314 khc_write_string(h_acell, L"MethodName",
2315 methodname);
2317 if(l->rows[i].realm)
2318 khc_write_string(h_acell, L"Realm",
2319 l->rows[i].realm);
2320 else
2321 khc_write_string(h_acell, L"Realm", L"");
2322 khc_close_space(h_acell);
2325 if (l->rows[i].flags & DLGROW_FLAG_DONE) {
2326 if (h_cellmap) {
2327 khc_write_string(h_cellmap,
2328 l->rows[i].cell,
2329 idname);
2334 if (lru_cell)
2335 khc_write_multi_string(csp_params,
2336 L"LRUCells", lru_cell);
2337 if (lru_realm)
2338 khc_write_multi_string(csp_params,
2339 L"LRURealms", lru_realm);
2340 if (id_cell)
2341 khc_write_multi_string(h_afs, L"Cells",
2342 id_cell);
2343 else
2344 khc_write_multi_string(h_afs, L"Cells", L"\0");
2346 if (d->config_dlg) {
2347 if (d->dirty)
2348 khui_cfg_set_flags_inst(&d->cfg, KHUI_CNFLAG_APPLIED,
2349 KHUI_CNFLAG_APPLIED |
2350 KHUI_CNFLAG_MODIFIED);
2351 else
2352 khui_cfg_set_flags_inst(&d->cfg, 0,
2353 KHUI_CNFLAG_MODIFIED);
2356 d->dirty = FALSE;
2358 if(h_cellmap)
2359 khc_close_space(h_cellmap);
2360 if(h_idc)
2361 khc_close_space(h_idc);
2362 if(h_afs)
2363 khc_close_space(h_afs);
2364 if(h_acells)
2365 khc_close_space(h_acells);
2366 if(id_cell)
2367 PFREE(id_cell);
2368 if(lru_cell)
2369 PFREE(lru_cell);
2370 if(lru_realm)
2371 PFREE(lru_realm);
2374 khm_int32
2375 afs_msg_newcred(khm_int32 msg_subtype,
2376 khm_ui_4 uparam,
2377 void * vparam) {
2379 switch(msg_subtype) {
2380 case KMSG_CRED_NEW_CREDS:
2382 khui_new_creds * nc;
2383 khui_new_creds_by_type * nct;
2384 wchar_t wbuf[256];
2385 size_t cbsize;
2387 nc = (khui_new_creds *) vparam;
2389 nct = PMALLOC(sizeof(*nct));
2390 ZeroMemory(nct, sizeof(*nct));
2392 nct->type = afs_credtype_id;
2393 nct->ordinal = 3;
2395 LoadString(hResModule, IDS_AFS_NAME, wbuf, ARRAYLENGTH(wbuf));
2396 StringCbLength(wbuf, sizeof(wbuf), &cbsize);
2397 cbsize += sizeof(wchar_t);
2399 nct->name = PMALLOC(cbsize);
2400 StringCbCopy(nct->name, cbsize, wbuf);
2402 nct->h_module = hResModule;
2403 nct->dlg_proc = afs_dlg_proc;
2404 nct->dlg_template = MAKEINTRESOURCE(IDD_NC_AFS);
2405 nct->type_deps[nct->n_type_deps++] = krb5_credtype_id;
2407 if (krb4_credtype_id < 0) {
2408 kcdb_credtype_get_id(KRB4_CREDTYPE_NAME,
2409 &krb4_credtype_id);
2411 if (krb4_credtype_id >= 0) {
2412 nct->type_deps[nct->n_type_deps++] =
2413 krb4_credtype_id;
2416 khui_cw_add_type(nc, nct);
2418 break;
2420 case KMSG_CRED_RENEW_CREDS:
2422 khui_new_creds * nc;
2423 khui_new_creds_by_type * nct;
2425 nc = (khui_new_creds *) vparam;
2427 nct = PMALLOC(sizeof(*nct));
2428 ZeroMemory(nct, sizeof(*nct));
2430 nct->type = afs_credtype_id;
2431 nct->type_deps[nct->n_type_deps++] = krb5_credtype_id;
2432 if (krb4_credtype_id < 0) {
2433 kcdb_credtype_get_id(KRB4_CREDTYPE_NAME,
2434 &krb4_credtype_id);
2436 if (krb4_credtype_id >= 0) {
2437 nct->type_deps[nct->n_type_deps++] =
2438 krb4_credtype_id;
2441 khui_cw_add_type(nc, nct);
2443 break;
2445 case KMSG_CRED_DIALOG_PRESTART:
2447 khui_new_creds * nc;
2448 khui_new_creds_by_type * nct = NULL;
2449 HWND hwnd;
2451 nc = (khui_new_creds *) vparam;
2452 khui_cw_find_type(nc, afs_credtype_id, &nct);
2454 if(!nct)
2455 break;
2457 hwnd = nct->hwnd_panel;
2458 if (!hwnd)
2459 break;
2461 PostMessage(hwnd, KHUI_WM_NC_NOTIFY,
2462 MAKEWPARAM(0,WMNC_DIALOG_SETUP), 0);
2464 break;
2466 case KMSG_CRED_DIALOG_NEW_IDENTITY:
2468 khui_new_creds * nc;
2469 khui_new_creds_by_type * nct = NULL;
2470 afs_dlg_data * d;
2472 nc = (khui_new_creds *) vparam;
2473 khui_cw_find_type(nc, afs_credtype_id, &nct);
2475 if(nct == NULL)
2476 break;
2478 d = (afs_dlg_data *) nct->aux;
2480 if(d == NULL)
2481 break;
2483 EnterCriticalSection(&d->cs);
2485 if (nct->aux == 0) {
2486 LeaveCriticalSection(&d->cs);
2487 break;
2490 /* we should load up the selected tokens for this
2491 identity */
2492 if(nc->n_identities == 0) {
2493 LeaveCriticalSection(&d->cs);
2494 /* no identities selected. nothing to do */
2495 break;
2498 afs_cred_get_identity_creds(&d->creds, nc->identities[0],
2499 &d->afs_enabled);
2501 LeaveCriticalSection(&d->cs);
2503 PostMessage(nct->hwnd_panel, KHUI_WM_NC_NOTIFY,
2504 MAKEWPARAM(0, WMNC_AFS_UPDATE_ROWS), 0);
2506 break;
2508 case KMSG_CRED_PROCESS:
2510 khui_new_creds * nc;
2511 khui_new_creds_by_type * nct = NULL;
2512 afs_cred_list tlist;
2513 afs_cred_list * l;
2514 int i;
2515 BOOL failed = FALSE; /* one or more cells failed */
2516 BOOL succeeded = FALSE; /* one or more cells succeeded */
2517 BOOL free_tlist = FALSE;
2518 khm_handle ident = NULL;
2519 afs_dlg_data * d = NULL;
2520 BOOL get_tokens = TRUE;
2521 BOOL ident_renew_triggered = TRUE;
2522 khm_handle csp_afscred = NULL;
2523 khm_handle csp_cells = NULL;
2525 nc = (khui_new_creds *) vparam;
2526 khui_cw_find_type(nc, afs_credtype_id, &nct);
2528 if(!nct)
2529 break;
2531 _begin_task(0);
2532 _report_cs0(KHERR_INFO,
2533 L"Getting AFS tokens...");
2534 _describe();
2536 if(nc->result != KHUI_NC_RESULT_PROCESS &&
2537 nc->subtype != KMSG_CRED_RENEW_CREDS) {
2538 /* nothing to do */
2539 khui_cw_set_response(nc, afs_credtype_id,
2540 KHUI_NC_RESPONSE_SUCCESS);
2542 _report_cs0(KHERR_INFO,
2543 L"Cancelling");
2544 _end_task();
2545 break;
2548 /* we can't proceed if Kerberos 5 has failed */
2549 if(!khui_cw_type_succeeded(nc, krb5_credtype_id)) {
2550 khui_cw_set_response(nc, afs_credtype_id,
2551 KHUI_NC_RESPONSE_FAILED);
2553 _report_cs0(KHERR_INFO,
2554 L"Kerberos 5 plugin failed to process credentials request. Aborting");
2555 _end_task();
2556 break;
2559 if (nc->subtype == KMSG_CRED_RENEW_CREDS) {
2561 if (nc->ctx.scope == KHUI_SCOPE_IDENT ||
2563 (nc->ctx.scope == KHUI_SCOPE_CREDTYPE &&
2564 nc->ctx.cred_type == afs_credtype_id) ||
2566 (nc->ctx.scope == KHUI_SCOPE_CRED &&
2567 nc->ctx.cred_type == afs_credtype_id)) {
2569 _report_cs1(KHERR_INFO,
2570 L"AFS Renew Creds :: ident %1!p!",
2571 _cptr(nc->ctx.identity));
2573 } else {
2575 _report_cs0(KHERR_INFO,
2576 L"Renew request not applicable to AFS");
2577 _end_task();
2578 break;
2582 if (nc->ctx.identity != NULL) {
2583 ident = nc->ctx.identity;
2584 } else {
2585 khui_cw_set_response(nc, afs_credtype_id,
2586 KHUI_NC_RESPONSE_FAILED);
2588 _report_cs0(KHERR_INFO,
2589 L"No identity specified. Aborting");
2590 _end_task();
2591 break;
2594 ZeroMemory(&tlist, sizeof(tlist));
2595 l = &tlist;
2596 free_tlist = TRUE;
2598 afs_cred_get_identity_creds(l, ident, NULL);
2600 /* if the identity has any tokens associated with it
2601 that aren't persistent, we should renew those as
2602 well. */
2603 afs_cred_get_context_creds(l, &nc->ctx);
2605 if (nc->ctx.scope == KHUI_SCOPE_CREDTYPE ||
2606 nc->ctx.scope == KHUI_SCOPE_CRED) {
2608 ident_renew_triggered = FALSE;
2612 } else {
2613 _report_cs1(KHERR_INFO,
2614 L"AFS New Creds :: ident %1!p!",
2615 _cptr(nc->identities[0]));
2617 d = (afs_dlg_data *) nct->aux;
2618 if(!d) {
2619 _report_cs0(KHERR_INFO,
2620 L"No dialog data found. Aborting");
2622 khui_cw_set_response(nc, afs_credtype_id,
2623 KHUI_NC_RESPONSE_FAILED);
2624 _end_task();
2625 break;
2628 EnterCriticalSection(&d->cs);
2630 l = &d->creds;
2632 ident = nc->identities[0];
2633 if (!ident) {
2634 LeaveCriticalSection(&d->cs);
2636 _report_cs0(KHERR_INFO,
2637 L"No identity specified. Aborting");
2639 khui_cw_set_response(nc, afs_credtype_id,
2640 KHUI_NC_RESPONSE_FAILED);
2642 _end_task();
2643 break;
2646 get_tokens = d->afs_enabled;
2649 if (!get_tokens)
2650 goto _skip_tokens;
2652 if (KHM_SUCCEEDED(kmm_get_plugin_config(AFS_PLUGIN_NAME, 0,
2653 &csp_afscred)))
2654 khc_open_space(csp_afscred, L"Cells", 0, &csp_cells);
2656 /* looks like k5 worked. Now see about getting those
2657 tokens */
2658 for(i=0; i<l->n_rows; i++) {
2659 int code;
2660 char cell[MAXCELLCHARS];
2661 char realm[MAXKTCREALMLEN];
2662 char linkedCell[MAXCELLCHARS]="";
2663 khm_handle ctoken;
2664 FILETIME ft_old;
2665 FILETIME ft_new;
2666 time_t new_exp = 0;
2667 khm_size cb;
2668 khm_int32 method = AFS_TOKEN_AUTO;
2669 khm_handle csp_cell = NULL;
2670 BOOL bgetLinked = 0;
2672 _progress(i, l->n_rows);
2674 if (l->rows[i].flags &
2675 (DLGROW_FLAG_DONE | DLGROW_FLAG_DELETED))
2677 continue;
2679 ZeroMemory(cell, sizeof(cell));
2680 ZeroMemory(realm, sizeof(realm));
2682 UnicodeStrToAnsi(cell, sizeof(cell), l->rows[i].cell);
2683 if (l->rows[i].realm != NULL)
2684 UnicodeStrToAnsi(realm, sizeof(realm),
2685 l->rows[i].realm);
2687 ZeroMemory(&ft_old, sizeof(ft_old));
2689 if (!ident_renew_triggered &&
2690 (ctoken = afs_find_token(NULL, l->rows[i].cell))) {
2692 cb = sizeof(ft_old);
2693 kcdb_cred_get_attr(ctoken, KCDB_ATTR_EXPIRE,
2694 NULL, &ft_old, &cb);
2696 kcdb_cred_release(ctoken);
2699 if (l->rows[i].method == AFS_TOKEN_AUTO && csp_cells &&
2700 KHM_SUCCEEDED(khc_open_space(csp_cells,
2701 l->rows[i].cell, 0,
2702 &csp_cell))) {
2704 if (KHM_FAILED(khc_read_int32(csp_cell, L"Method", &method))) {
2705 method = l->rows[i].method;
2706 } else {
2707 _report_cs3(KHERR_INFO,
2708 L"Overriding method %1!d! with global default %2!d! for cell %3!s!",
2709 _int32(l->rows[i].method),
2710 _int32(method),
2711 _cstr(l->rows[i].cell));
2712 _resolve();
2715 khc_close_space(csp_cell);
2716 } else {
2717 method = l->rows[i].method;
2720 getLinked:
2721 _report_cs3(KHERR_INFO,
2722 L"Getting tokens for cell %1!S! with realm %2!S! using method %3!d!",
2723 _cstr((bgetLinked ? linkedCell: cell)),
2724 _cstr(realm),
2725 _int32(method));
2726 _resolve();
2728 /* make the call */
2729 code = afs_klog(ident, "",
2730 bgetLinked ? linkedCell : cell,
2731 realm, 0,
2732 method, &new_exp,
2733 bgetLinked ? NULL :linkedCell);
2735 _report_cs1(KHERR_INFO,
2736 L"klog returns code %1!d!",
2737 _int32(code));
2739 if(code) {
2740 failed = TRUE;
2741 l->rows[i].flags &= ~DLGROW_FLAG_DONE;
2743 if (!kherr_is_error()) {
2744 /* failed to get tokens, but no error was reported */
2745 _report_sr1(KHERR_ERROR, IDS_ERR_GENERAL,
2746 _cptr(cell));
2747 _resolve();
2750 } else {
2751 l->rows[i].flags |= DLGROW_FLAG_DONE;
2752 succeeded = TRUE;
2754 if (new_exp &&
2755 !ident_renew_triggered) {
2756 TimetToFileTime(new_exp, &ft_new);
2758 if (CompareFileTime(&ft_old, &ft_new) >= 0) {
2759 /* getting a new token didn't improve the
2760 situation much. We only get here if we
2761 were trying to renew tokens. So we try
2762 to trigger an identity renewal. Doing
2763 so should get us new initial tickets
2764 which will allow us to get a better
2765 token. */
2767 khui_action_context ctx;
2769 _reportf(L"Renewal of AFS tokens for cell %s failed to get a longer token. Triggering identity renewal", l->rows[i].cell);
2771 khui_context_create(&ctx,
2772 KHUI_SCOPE_IDENT,
2773 nc->ctx.identity,
2774 KCDB_CREDTYPE_INVALID,
2775 NULL);
2776 khui_action_trigger(KHUI_ACTION_RENEW_CRED,
2777 &ctx);
2779 khui_context_release(&ctx);
2781 ident_renew_triggered = TRUE;
2785 if ( !bgetLinked && linkedCell[0] ) {
2786 bgetLinked = TRUE;
2787 goto getLinked;
2792 _progress(1,1);
2794 _skip_tokens:
2796 if(failed) {
2797 /* we should indicate errors if anything went wrong */
2798 khui_cw_set_response(nc, afs_credtype_id,
2799 KHUI_NC_RESPONSE_FAILED);
2800 } else {
2801 khui_cw_set_response(nc, afs_credtype_id,
2802 KHUI_NC_RESPONSE_SUCCESS);
2805 if (succeeded && nc->subtype == KMSG_CRED_RENEW_CREDS) {
2806 afs_ident_token_set b;
2808 afs_list_tokens_internal();
2810 /* the tokens that we just acquired need adjusting to
2811 include the realm, method and identity information
2812 derived from the new creds operation. this is done
2813 in afs_adjust_token_ident_proc */
2814 b.ident = ident;
2815 b.l = l;
2816 b.add_new = FALSE;
2817 b.update_info = FALSE;
2819 kcdb_credset_apply(afs_credset, afs_adjust_token_ident_proc,
2820 (void *) &b);
2822 kcdb_credset_collect(NULL, afs_credset, NULL,
2823 afs_credtype_id, NULL);
2825 } else if (nc->subtype == KMSG_CRED_NEW_CREDS) {
2826 afs_ident_token_set b;
2828 afs_list_tokens_internal();
2830 /* the tokens that we just acquired need adjusting to
2831 include the realm, method and identity information
2832 derived from the new creds operation. this is done
2833 in afs_adjust_token_ident_proc */
2834 b.ident = ident;
2835 b.l = l;
2836 b.add_new = FALSE;
2837 b.update_info = FALSE;
2839 kcdb_credset_apply(afs_credset, afs_adjust_token_ident_proc,
2840 (void *) &b);
2842 kcdb_credset_collect(NULL, afs_credset, NULL,
2843 afs_credtype_id, NULL);
2845 afs_cred_write_ident_data(d);
2848 if (d)
2849 LeaveCriticalSection(&d->cs);
2851 if (free_tlist) {
2852 afs_cred_free_rows(&tlist);
2855 if (csp_afscred)
2856 khc_close_space(csp_afscred);
2858 if (csp_cells)
2859 khc_close_space(csp_cells);
2861 _end_task();
2863 break;
2865 case KMSG_CRED_END:
2867 khui_new_creds * nc;
2868 khui_new_creds_by_type * nct;
2870 nc = (khui_new_creds *) vparam;
2871 khui_cw_find_type(nc, afs_credtype_id, &nct);
2873 if(!nct)
2874 break;
2876 khui_cw_del_type(nc, afs_credtype_id);
2878 if (nct->name)
2879 PFREE(nct->name);
2880 if (nct->credtext)
2881 PFREE(nct->credtext);
2883 PFREE(nct);
2885 break;
2888 return KHM_ERROR_SUCCESS;