4b7baef14b0c5984ed01cfe50d31313fe8c223b1
[openafs.git] / src / WINNT / afssvrmgr / svr_security.cpp
1 /*
2  * Copyright 2000, International Business Machines Corporation and others.
3  * All Rights Reserved.
4  *
5  * This software has been released under the terms of the IBM Public
6  * License.  For details, see the LICENSE file in the top-level source
7  * directory or online at http://www.openafs.org/dl/license10.html
8  */
9
10 #include <winsock2.h>
11 #include <ws2tcpip.h>
12
13 extern "C" {
14 #include <afs/param.h>
15 #include <afs/stds.h>
16 }
17
18 #include "svrmgr.h"
19 #include "svr_security.h"
20 #include "propcache.h"
21 #include "display.h"
22
23
24 /*
25  * DEFINITIONS ________________________________________________________________
26  *
27  */
28
29 #define ISKEYINUSE(_pkey) ((_pkey)->keyInfo.timeLastModification.wYear != 0)
30
31 typedef struct
32    {
33    LONG cRef;
34    LPIDENT lpiServer;
35    LPADMINLIST lpAdmList;
36    LPKEYLIST lpKeyList;
37    } SVR_SECURITY_PARAMS, *LPSVR_SECURITY_PARAMS;
38
39
40 /*
41  * PROTOTYPES _________________________________________________________________
42  *
43  */
44
45 void Server_Security_Free (LPSVR_SECURITY_PARAMS lpp);
46
47 BOOL CALLBACK Server_Lists_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
48
49 void Server_Lists_OnInitDialog (HWND hDlg, LPSVR_SECURITY_PARAMS lpp);
50 void Server_Lists_OnEndTask_ListOpen (HWND hDlg, LPSVR_SECURITY_PARAMS lpp, LPTASKPACKET ptp);
51 void Server_Lists_OnApply (HWND hDlg, LPSVR_SECURITY_PARAMS lpp);
52 void Server_Lists_OnSelect (HWND hDlg, LPSVR_SECURITY_PARAMS lpp);
53 void Server_Lists_OnAddEntry (HWND hDlg, LPSVR_SECURITY_PARAMS lpp);
54 void Server_Lists_OnDelEntry (HWND hDlg, LPSVR_SECURITY_PARAMS lpp);
55
56 BOOL CALLBACK Server_Keys_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
57 void Server_Keys_OnInitDialog (HWND hDlg, LPSVR_SECURITY_PARAMS lpp);
58 void Server_Keys_OnEndTask_ListOpen (HWND hDlg, LPSVR_SECURITY_PARAMS lpp, LPTASKPACKET ptp);
59 void Server_Keys_OnEndTask_CreateKey (HWND hDlg, LPSVR_SECURITY_PARAMS lpp, LPTASKPACKET ptp);
60 void Server_Keys_OnEndTask_DeleteKey (HWND hDlg, LPSVR_SECURITY_PARAMS lpp, LPTASKPACKET ptp);
61 void Server_Keys_OnSelect (HWND hDlg, LPSVR_SECURITY_PARAMS lpp);
62 void Server_Keys_OnAddKey (HWND hDlg, LPSVR_SECURITY_PARAMS lpp);
63 void Server_Keys_OnDelKey (HWND hDlg, LPSVR_SECURITY_PARAMS lpp);
64
65 void FormatServerKey (LPTSTR psz, LPENCRYPTIONKEY pKey);
66 BOOL ScanServerKey (LPENCRYPTIONKEY pKey, LPTSTR psz);
67
68 BOOL CALLBACK CreateKey_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp);
69 void CreateKey_OnInitDialog (HWND hDlg, LPKEY_CREATE_PARAMS lpp);
70 void CreateKey_OnSelect (HWND hDlg);
71 void CreateKey_OnType (HWND hDlg);
72 void CreateKey_OnRandom (HWND hDlg, LPKEY_CREATE_PARAMS lpp);
73 BOOL CreateKey_OnOK (HWND hDlg, LPKEY_CREATE_PARAMS lpp);
74 void CreateKey_OnEndTask_Random (HWND hDlg, LPTASKPACKET ptp);
75
76
77 /*
78  * SERVER-KEY COLUMNS _________________________________________________________
79  *
80  */
81
82 void Server_Key_SetDefaultView (LPVIEWINFO lpvi)
83 {
84    lpvi->lvsView = FLS_VIEW_LIST;
85    lpvi->nColsAvail = nSERVERKEYCOLUMNS;
86
87    for (size_t iCol = 0; iCol < nSERVERKEYCOLUMNS; ++iCol)
88       {
89       lpvi->cxColumns[ iCol ]  = SERVERKEYCOLUMNS[ iCol ].cxWidth;
90       lpvi->idsColumns[ iCol ] = SERVERKEYCOLUMNS[ iCol ].idsColumn;
91       }
92
93    lpvi->iSort = svrkeyVERSION;
94
95    lpvi->nColsShown = 3;
96    lpvi->aColumns[0] = (int)svrkeyVERSION;
97    lpvi->aColumns[1] = (int)svrkeyDATA;
98    lpvi->aColumns[2] = (int)svrkeyCHECKSUM;
99 }
100
101
102 /*
103  * ROUTINES ___________________________________________________________________
104  *
105  */
106
107 void Server_Security (LPIDENT lpiServer, BOOL fJumpToKeys)
108 {
109    HWND hCurrent;
110    if ((hCurrent = PropCache_Search (pcSVR_SECURITY, lpiServer)) != NULL)
111       {
112       SetFocus (hCurrent);
113
114       if (fJumpToKeys)
115          {
116          HWND hTab;
117          if ((hTab = GetDlgItem (hCurrent, IDC_PROPSHEET_TABCTRL)) != NULL)
118             {
119             int nTabs = TabCtrl_GetItemCount (hTab);
120             TabCtrl_SetCurSel (hTab, nTabs-1);
121
122             NMHDR nm;
123             nm.hwndFrom = hTab;
124             nm.idFrom = IDC_PROPSHEET_TABCTRL;
125             nm.code = TCN_SELCHANGE;
126             SendMessage (hCurrent, WM_NOTIFY, 0, (LPARAM)&nm);
127             }
128          }
129       }
130    else
131       {
132       LPSVR_SECURITY_PARAMS lpp = New (SVR_SECURITY_PARAMS);
133       memset (lpp, 0x00, sizeof(SVR_SECURITY_PARAMS));
134       lpp->lpiServer = lpiServer;
135
136       TCHAR szServer[ cchNAME ];
137       lpiServer->GetServerName (szServer);
138       LPTSTR pszTitle = FormatString (IDS_SVR_SECURITY_TITLE, TEXT("%s"), szServer);
139       LPPROPSHEET psh = PropSheet_Create (pszTitle, FALSE);
140       PropSheet_AddTab (psh, IDS_SVR_LIST_TAB, IDD_SVR_LISTS, (DLGPROC)Server_Lists_DlgProc, (LONG_PTR)lpp, TRUE, !fJumpToKeys);
141       PropSheet_AddTab (psh, IDS_SVR_KEY_TAB,  IDD_SVR_KEYS,  (DLGPROC)Server_Keys_DlgProc,  (LONG_PTR)lpp, TRUE,  fJumpToKeys);
142       PropSheet_ShowModeless (psh);
143       FreeString (pszTitle);
144       }
145 }
146
147
148 void Server_Security_Free (LPSVR_SECURITY_PARAMS lpp)
149 {
150    if (lpp->lpAdmList)
151       AfsClass_AdminList_Free (lpp->lpAdmList);
152    if (lpp->lpKeyList)
153       AfsClass_KeyList_Free (lpp->lpKeyList);
154    Delete (lpp);
155 }
156
157
158 BOOL CALLBACK Server_Lists_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
159 {
160    if (AfsAppLib_HandleHelp (IDD_SVR_LISTS, hDlg, msg, wp, lp))
161       return TRUE;
162
163    LPSVR_SECURITY_PARAMS lpp;
164    if ((msg == WM_INITDIALOG_SHEET) || (msg == WM_DESTROY_SHEET))
165       lpp = (LPSVR_SECURITY_PARAMS)lp;
166    else
167       lpp = (LPSVR_SECURITY_PARAMS)PropSheet_FindTabParam (hDlg);
168
169    switch (msg)
170       {
171       case WM_INITDIALOG_SHEET:
172          InterlockedIncrement (&lpp->cRef);
173          PropCache_Add (pcSVR_SECURITY, lpp->lpiServer, hDlg);
174          break;
175
176       case WM_DESTROY_SHEET:
177          PropCache_Delete (hDlg);
178          if ((InterlockedDecrement (&lpp->cRef)) == 0)
179             Server_Security_Free (lpp);
180          break;
181
182       case WM_INITDIALOG:
183          Server_Lists_OnInitDialog (hDlg, lpp);
184          break;
185
186       case WM_ENDTASK:
187          LPTASKPACKET ptp;
188          if ((ptp = (LPTASKPACKET)lp) != NULL)
189             {
190             if (ptp->idTask == taskSVR_ADMLIST_OPEN)
191                Server_Lists_OnEndTask_ListOpen (hDlg, lpp, ptp);
192             FreeTaskPacket (ptp);
193             }
194          break;
195
196       case WM_COMMAND:
197          switch (LOWORD(wp))
198             {
199             case IDAPPLY:
200                Server_Lists_OnApply (hDlg, lpp);
201                break;
202
203             case IDC_LIST_ADD:
204                Server_Lists_OnAddEntry (hDlg, lpp);
205                PropSheetChanged (hDlg);
206                break;
207
208             case IDC_LIST_REMOVE:
209                Server_Lists_OnDelEntry (hDlg, lpp);
210                PropSheetChanged (hDlg);
211                break;
212             }
213          break;
214
215       case WM_NOTIFY:
216          switch (((LPNMHDR)lp)->code)
217             {
218             case FLN_ITEMSELECT:
219                if (((LPNMHDR)lp)->hwndFrom == GetDlgItem (hDlg, IDC_LIST_LIST))
220                   {
221                   Server_Lists_OnSelect (hDlg, lpp);
222                   }
223                break;
224             }
225          break;
226       }
227
228    return FALSE;
229 }
230
231
232 void Server_Lists_OnInitDialog (HWND hDlg, LPSVR_SECURITY_PARAMS lpp)
233 {
234    TCHAR szOld[ cchRESOURCE ];
235    GetDlgItemText (hDlg, IDC_LIST_NAME, szOld, cchRESOURCE);
236
237    TCHAR szServer[ cchNAME ];
238    lpp->lpiServer->GetServerName (szServer);
239
240    LPTSTR pszText = FormatString (szOld, TEXT("%s"), szServer);
241    SetDlgItemText (hDlg, IDC_LIST_NAME, pszText);
242    FreeString (pszText);
243
244    HWND hList = GetDlgItem (hDlg, IDC_LIST_LIST);
245
246    // We'll need an imagelist, if we want icons in the list.
247    //
248    HIMAGELIST hLarge;
249    if ((hLarge = ImageList_Create (32, 32, ILC_COLOR4 | ILC_MASK, 1, 1)) != 0)
250       AfsAppLib_AddToImageList (hLarge, IDI_USER, TRUE);
251
252    HIMAGELIST hSmall;
253    if ((hSmall = ImageList_Create (16, 16, ILC_COLOR4 | ILC_MASK, 1, 1)) != 0)
254       AfsAppLib_AddToImageList (hSmall, IDI_USER, FALSE);
255
256    FastList_SetImageLists (hList, hSmall, hLarge);
257
258    // Start loading the admin list
259    //
260    StartTask (taskSVR_ADMLIST_OPEN, hDlg, lpp->lpiServer);
261
262    EnableWindow (hList, FALSE);
263    EnableWindow (GetDlgItem (hDlg, IDC_LIST_ADD), FALSE);
264    EnableWindow (GetDlgItem (hDlg, IDC_LIST_REMOVE), FALSE);
265 }
266
267
268 void Server_Lists_OnEndTask_ListOpen (HWND hDlg, LPSVR_SECURITY_PARAMS lpp, LPTASKPACKET ptp)
269 {
270    HWND hList = GetDlgItem (hDlg, IDC_LIST_LIST);
271
272    lpp->lpAdmList = TASKDATA(ptp)->lpAdmList;
273
274    // Populate the list
275    //
276    FL_StartChange (hList, TRUE);
277
278    if (lpp->lpAdmList)
279       {
280       for (size_t iEntry = 0; iEntry < lpp->lpAdmList->cEntries; ++iEntry)
281          {
282          LPADMINLISTENTRY pEntry = &lpp->lpAdmList->aEntries[ iEntry ];
283          if (pEntry->szAdmin[0] == TEXT('\0'))
284             continue;
285
286          FL_AddItem (hList, 1, (LPARAM)iEntry, 0, pEntry->szAdmin);
287          }
288       }
289
290    FL_EndChange (hList, 0);
291    EnableWindow (hList, (lpp->lpAdmList != NULL));
292    EnableWindow (GetDlgItem (hDlg, IDC_LIST_ADD), (lpp->lpAdmList != NULL));
293
294    Server_Lists_OnSelect (hDlg, lpp);
295 }
296
297
298 void Server_Lists_OnSelect (HWND hDlg, LPSVR_SECURITY_PARAMS lpp)
299 {
300    HWND hList = GetDlgItem (hDlg, IDC_LIST_LIST);
301
302    BOOL fEnableRemove = TRUE;
303
304    if (!IsWindowEnabled (hList))
305       fEnableRemove = FALSE;
306
307    if (FastList_FindFirstSelected (hList) == NULL)
308       fEnableRemove = FALSE;
309
310    EnableWindow (GetDlgItem (hDlg, IDC_LIST_REMOVE), fEnableRemove);
311 }
312
313
314 void Server_Lists_OnApply (HWND hDlg, LPSVR_SECURITY_PARAMS lpp)
315 {
316    if (IsWindowEnabled (GetDlgItem (hDlg, IDC_LIST_LIST)))
317       {
318       // Increment the reference counter on this admin list before handing
319       // it off to the Save task. When the Save task is done, it will attempt
320       // to free the list--which will decrement the counter again, and
321       // actually free the list if the counter hits zero.
322       //
323       InterlockedIncrement (&lpp->lpAdmList->cRef);
324       StartTask (taskSVR_ADMLIST_SAVE, NULL, lpp->lpAdmList);
325       }
326 }
327
328
329 void Server_Lists_OnAddEntry (HWND hDlg, LPSVR_SECURITY_PARAMS lpp)
330 {
331    TCHAR szLocalCell[ cchNAME ];
332    g.lpiCell->GetCellName (szLocalCell);
333
334    BROWSEDLG_PARAMS pp;
335    memset (&pp, 0x00, sizeof(BROWSEDLG_PARAMS));
336    pp.hParent = hDlg;
337    pp.idsTitle = IDS_TITLE_BROWSE_USER;
338    pp.idsPrompt = IDS_PROMPT_BROWSE_USER;
339    pp.bt = btLOCAL_USER;
340    lstrcpy (pp.szCell, szLocalCell);
341    pp.lpcl = AfsAppLib_GetCellList (HKCU, REGSTR_SETTINGS_CELLS);
342    pp.szNamed[0] = TEXT('\0');
343    pp.hCreds = g.hCreds;
344
345    if (!AfsAppLib_ShowBrowseDialog (&pp))
346       {
347       AfsAppLib_FreeCellList (pp.lpcl);
348       return;
349       }
350
351    AfsAppLib_FreeCellList (pp.lpcl);
352
353    size_t iEntry;
354    for (iEntry = 0; iEntry < lpp->lpAdmList->cEntries; ++iEntry)
355       {
356       LPADMINLISTENTRY pEntry = &lpp->lpAdmList->aEntries[ iEntry ];
357       if (pEntry->szAdmin[0] == TEXT('\0'))
358          continue;
359
360       if (!lstrcmpi (pEntry->szAdmin, pp.szNamed))
361          break;
362       }
363
364    if (iEntry >= lpp->lpAdmList->cEntries)
365       {
366       iEntry = AfsClass_AdminList_AddEntry (lpp->lpAdmList, pp.szNamed);
367       }
368
369    HWND hList = GetDlgItem (hDlg, IDC_LIST_LIST);
370    FL_StartChange (hList, FALSE);
371
372    HLISTITEM hItem;
373    if ((hItem = FastList_FindItem (hList, (LPARAM)iEntry)) == NULL)
374       {
375       hItem = FL_AddItem (hList, 1, (LPARAM)iEntry, 0, pp.szNamed);
376       }
377
378    FL_EndChange (hList, (LPARAM)hItem);
379 }
380
381
382 void Server_Lists_OnDelEntry (HWND hDlg, LPSVR_SECURITY_PARAMS lpp)
383 {
384    HWND hList = GetDlgItem (hDlg, IDC_LIST_LIST);
385    FL_StartChange (hList, FALSE);
386
387    HLISTITEM hItem;
388    while ((hItem = FastList_FindFirstSelected (hList)) != NULL)
389       {
390       size_t iEntry = (size_t)FL_GetData (hList, hItem);
391       AfsClass_AdminList_DelEntry (lpp->lpAdmList, iEntry);
392       FastList_RemoveItem (hList, hItem);
393       }
394
395    FL_EndChange (hList);
396 }
397
398
399 BOOL CALLBACK Server_Keys_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
400 {
401    if (AfsAppLib_HandleHelp (IDD_SVR_KEYS, hDlg, msg, wp, lp))
402       return TRUE;
403
404    LPSVR_SECURITY_PARAMS lpp;
405    if ((msg == WM_INITDIALOG_SHEET) || (msg == WM_DESTROY_SHEET))
406       lpp = (LPSVR_SECURITY_PARAMS)lp;
407    else
408       lpp = (LPSVR_SECURITY_PARAMS)PropSheet_FindTabParam (hDlg);
409
410    switch (msg)
411       {
412       case WM_INITDIALOG_SHEET:
413          InterlockedIncrement (&lpp->cRef);
414          break;
415
416       case WM_DESTROY_SHEET:
417          if ((InterlockedDecrement (&lpp->cRef)) == 0)
418             Server_Security_Free (lpp);
419          break;
420
421       case WM_INITDIALOG:
422          Server_Keys_OnInitDialog (hDlg, lpp);
423          break;
424
425       case WM_DESTROY:
426          FL_StoreView (GetDlgItem (hDlg, IDC_KEY_LIST), &gr.viewKey);
427          break;
428
429       case WM_ENDTASK:
430          LPTASKPACKET ptp;
431          if ((ptp = (LPTASKPACKET)lp) != NULL)
432             {
433             if (ptp->idTask == taskSVR_KEYLIST_OPEN)
434                Server_Keys_OnEndTask_ListOpen (hDlg, lpp, ptp);
435             else if (ptp->idTask == taskSVR_KEY_CREATE)
436                Server_Keys_OnEndTask_CreateKey (hDlg, lpp, ptp);
437             else if (ptp->idTask == taskSVR_KEY_DELETE)
438                Server_Keys_OnEndTask_DeleteKey (hDlg, lpp, ptp);
439             FreeTaskPacket (ptp);
440             }
441          break;
442
443       case WM_COMMAND:
444          switch (LOWORD(wp))
445             {
446             case IDC_KEY_ADD:
447                Server_Keys_OnAddKey (hDlg, lpp);
448                break;
449
450             case IDC_KEY_REMOVE:
451                Server_Keys_OnDelKey (hDlg, lpp);
452                break;
453             }
454          break;
455
456       case WM_NOTIFY:
457          switch (((LPNMHDR)lp)->code)
458             {
459             case FLN_ITEMSELECT:
460                if (((LPNMHDR)lp)->hwndFrom == GetDlgItem (hDlg, IDC_KEY_LIST))
461                   {
462                   Server_Keys_OnSelect (hDlg, lpp);
463                   }
464                break;
465             }
466          break;
467       }
468
469    return FALSE;
470 }
471
472
473 void Server_Keys_OnInitDialog (HWND hDlg, LPSVR_SECURITY_PARAMS lpp)
474 {
475    TCHAR szServer[ cchNAME ];
476    lpp->lpiServer->GetServerName (szServer);
477
478    LPTSTR pszText = FormatString (IDS_KEYNAME_NOTIME, TEXT("%s"), szServer);
479    SetDlgItemText (hDlg, IDC_KEY_NAME, pszText);
480    FreeString (pszText);
481
482    HWND hList = GetDlgItem (hDlg, IDC_KEY_LIST);
483    FL_RestoreView (hList, &gr.viewKey);
484    FastList_SetSortFunction (hList, FastList_SortFunc_Numeric);
485    FastList_SetSortStyle (hList, 0, FALSE);
486
487    // We'll need an imagelist, if we want icons in the list.
488    //
489    HIMAGELIST hSmall = AfsAppLib_CreateImageList (FALSE);
490    FastList_SetImageLists (hList, hSmall, NULL);
491
492    // Start loading the server keys
493    //
494    StartTask (taskSVR_KEYLIST_OPEN, hDlg, lpp->lpiServer);
495
496    EnableWindow (hList, FALSE);
497    EnableWindow (GetDlgItem (hDlg, IDC_KEY_ADD), FALSE);
498    EnableWindow (GetDlgItem (hDlg, IDC_KEY_REMOVE), FALSE);
499 }
500
501
502 void Server_Keys_OnEndTask_CreateKey (HWND hDlg, LPSVR_SECURITY_PARAMS lpp, LPTASKPACKET ptp)
503 {
504    StartTask (taskSVR_KEYLIST_OPEN, hDlg, lpp->lpiServer);
505 }
506
507
508 void Server_Keys_OnEndTask_DeleteKey (HWND hDlg, LPSVR_SECURITY_PARAMS lpp, LPTASKPACKET ptp)
509 {
510    StartTask (taskSVR_KEYLIST_OPEN, hDlg, lpp->lpiServer);
511 }
512
513
514 void Server_Keys_OnEndTask_ListOpen (HWND hDlg, LPSVR_SECURITY_PARAMS lpp, LPTASKPACKET ptp)
515 {
516    HWND hList = GetDlgItem (hDlg, IDC_KEY_LIST);
517
518    if (lpp->lpKeyList)
519       AfsClass_KeyList_Free (lpp->lpKeyList);
520    lpp->lpKeyList = TASKDATA(ptp)->lpKeyList;
521
522    // Populate the list
523    //
524    LPARAM iVerSelect = FL_StartChange (hList, TRUE);
525
526    SYSTEMTIME stLastMod;
527    memset (&stLastMod, 0x00, sizeof(stLastMod));
528
529    if (lpp->lpKeyList)
530       {
531       for (size_t iKey = 0; iKey < lpp->lpKeyList->cKeys; ++iKey)
532          {
533          LPSERVERKEY pKey = &lpp->lpKeyList->aKeys[ iKey ];
534          if (!ISKEYINUSE(pKey))
535             continue;
536
537          TCHAR szVersion[ cchRESOURCE ];
538          wsprintf (szVersion, TEXT("%lu"), pKey->keyVersion);
539
540          TCHAR szValue[ cchRESOURCE ];
541          FormatServerKey (szValue, &pKey->keyData);
542
543          TCHAR szChecksum[ cchRESOURCE ];
544          wsprintf (szChecksum, TEXT("%lu"), pKey->keyInfo.dwChecksum);
545
546          FL_AddItem (hList, &gr.viewKey, (LPARAM)pKey->keyVersion, imageSERVERKEY, szVersion, szValue, szChecksum);
547
548          stLastMod = pKey->keyInfo.timeLastModification;
549          }
550       }
551
552    FL_EndChange (hList, iVerSelect);
553    EnableWindow (hList, (lpp->lpKeyList != NULL));
554    EnableWindow (GetDlgItem (hDlg, IDC_KEY_ADD), (lpp->lpKeyList != NULL));
555
556    // Retitle the list
557    //
558    if (lpp->lpKeyList && stLastMod.wYear)
559       {
560       TCHAR szServer[ cchNAME ];
561       lpp->lpiServer->GetServerName (szServer);
562
563       LPTSTR pszText = FormatString (IDS_KEYNAME_WITHTIME, TEXT("%s%t"), szServer, &stLastMod);
564       SetDlgItemText (hDlg, IDC_KEY_NAME, pszText);
565       FreeString (pszText);
566       }
567
568    Server_Lists_OnSelect (hDlg, lpp);
569 }
570
571
572 void Server_Keys_OnSelect (HWND hDlg, LPSVR_SECURITY_PARAMS lpp)
573 {
574    HWND hList = GetDlgItem (hDlg, IDC_KEY_LIST);
575
576    BOOL fEnableRemove = TRUE;
577
578    if (!IsWindowEnabled (hList))
579       fEnableRemove = FALSE;
580
581    if (FastList_FindFirstSelected (hList) == NULL)
582       fEnableRemove = FALSE;
583
584    EnableWindow (GetDlgItem (hDlg, IDC_KEY_REMOVE), fEnableRemove);
585 }
586
587
588 void Server_Keys_OnAddKey (HWND hDlg, LPSVR_SECURITY_PARAMS lpp)
589 {
590    LPKEY_CREATE_PARAMS lpCreate = New (KEY_CREATE_PARAMS);
591    memset (lpCreate, 0x00, sizeof(KEY_CREATE_PARAMS));
592    lpCreate->lpiServer = lpp->lpiServer;
593    lpCreate->keyVersion = 0;
594
595    for (size_t iKey = 0; iKey < lpp->lpKeyList->cKeys; ++iKey)
596       {
597       LPSERVERKEY pKey = &lpp->lpKeyList->aKeys[ iKey ];
598       if (!ISKEYINUSE(pKey))
599          continue;
600       lpCreate->keyVersion = max (lpCreate->keyVersion, 1+pKey->keyVersion);
601       }
602
603    if (ModalDialogParam (IDD_SVR_CREATEKEY, hDlg, (DLGPROC)CreateKey_DlgProc, (LPARAM)lpCreate) != IDOK)
604       {
605       Delete (lpCreate);
606       }
607    else
608       {
609       StartTask (taskSVR_KEY_CREATE, hDlg, lpCreate);
610       }
611 }
612
613
614 void Server_Keys_OnDelKey (HWND hDlg, LPSVR_SECURITY_PARAMS lpp)
615 {
616    HWND hList = GetDlgItem (hDlg, IDC_KEY_LIST);
617
618    HLISTITEM hItem;
619    if ((hItem = FastList_FindFirstSelected (hList)) != NULL)
620       {
621       LPKEY_DELETE_PARAMS lpDel = New (KEY_DELETE_PARAMS);
622       lpDel->lpiServer = lpp->lpiServer;
623       lpDel->keyVersion = (int)FL_GetData (hList, hItem);
624       StartTask (taskSVR_KEY_DELETE, hDlg, lpDel);
625       }
626 }
627
628
629 void FormatServerKey (LPTSTR psz, LPENCRYPTIONKEY pKey)
630 {
631    size_t ii;
632    for (ii = 0; ii < ENCRYPTIONKEY_LEN; ++ii)
633       {
634       if (pKey->key[ii])
635          break;
636       }
637    if (ii == ENCRYPTIONKEY_LEN)
638       {
639       GetString (psz, IDS_SVRKEY_DATA_UNKNOWN);
640       return;
641       }
642
643    for (ii = 0; ii < ENCRYPTIONKEY_LEN; ++ii)
644       {
645           WORD ch1 = (WORD)(pKey->key[ii]) / 64;
646           WORD ch2 = ((WORD)(pKey->key[ii]) - (ch1 * 64)) / 8;
647           WORD ch3 = ((WORD)(pKey->key[ii]) - (ch1 * 64) - (ch2 * 8));
648           wsprintf (psz, TEXT("\\%0d%0d%0d"), ch1, ch2, ch3);
649           psz += 4;
650       }
651
652    *psz = TEXT('\0');
653 }
654
655
656 BOOL ScanServerKey (LPENCRYPTIONKEY pKey, LPTSTR psz)
657 {
658    size_t ich;
659    for (ich = 0; psz && *psz; )
660       {
661       if (ich == ENCRYPTIONKEY_LEN)
662          return FALSE;
663
664       if (*psz != '\\')
665          {
666          pKey->key[ ich++ ] = (BYTE)*psz++;
667          continue;
668          }
669
670       if ((lstrlen(psz) < 4) || (!isdigit(*(1+psz))))
671          return FALSE;
672
673       ++psz; // skip the backslash
674       WORD ch1 = (WORD)((*psz++) - TEXT('0'));
675       WORD ch2 = (WORD)((*psz++) - TEXT('0'));
676       WORD ch3 = (WORD)((*psz++) - TEXT('0'));
677       pKey->key[ ich++ ] = (BYTE)( ch1 * 64 + ch2 * 8 + ch3 );
678       }
679
680    return (ich == ENCRYPTIONKEY_LEN) ? TRUE : FALSE;
681 }
682
683
684 BOOL CALLBACK CreateKey_DlgProc (HWND hDlg, UINT msg, WPARAM wp, LPARAM lp)
685 {
686    static LPKEY_CREATE_PARAMS lpp = NULL;
687
688    switch (msg)
689       {
690       case WM_INITDIALOG:
691          lpp = (LPKEY_CREATE_PARAMS)lp;
692          CreateKey_OnInitDialog (hDlg, lpp);
693          break;
694
695       case WM_DESTROY:
696          lpp = NULL;
697          break;
698
699       case WM_ENDTASK:
700          LPTASKPACKET ptp;
701          if ((ptp = (LPTASKPACKET)lp) != NULL)
702             {
703             if (ptp->idTask == taskSVR_GETRANDOMKEY)
704                CreateKey_OnEndTask_Random (hDlg, ptp);
705             FreeTaskPacket (ptp);
706             }
707          break;
708
709       case WM_COMMAND:
710          switch (LOWORD(wp))
711             {
712             case IDOK:
713                if (CreateKey_OnOK (hDlg, lpp))
714                   EndDialog (hDlg, IDOK);
715                break;
716
717             case IDCANCEL:
718                EndDialog (hDlg, IDCANCEL);
719                break;
720
721             case IDC_KEY_BYSTRING:
722             case IDC_KEY_BYDATA:
723                CreateKey_OnSelect (hDlg);
724                break;
725
726             case IDC_KEY_STRING:
727             case IDC_KEY_DATA:
728                CreateKey_OnType (hDlg);
729                break;
730
731             case IDC_KEY_RANDOM:
732                CreateKey_OnRandom (hDlg, lpp);
733                break;
734             }
735          break;
736       }
737
738    return FALSE;
739 }
740
741
742 void CreateKey_OnInitDialog (HWND hDlg, LPKEY_CREATE_PARAMS lpp)
743 {
744    TCHAR szOld[ cchRESOURCE ];
745    GetDlgItemText (hDlg, IDC_KEY_TITLE, szOld, cchRESOURCE);
746
747    TCHAR szServer[ cchNAME ];
748    lpp->lpiServer->GetServerName (szServer);
749
750    LPTSTR pszText = FormatString (szOld, TEXT("%s"), szServer);
751    SetDlgItemText (hDlg, IDC_KEY_TITLE, pszText);
752    FreeString (pszText);
753
754    CheckDlgButton (hDlg, IDC_KEY_BYSTRING, TRUE);
755    SetDlgItemText (hDlg, IDC_KEY_STRING, lpp->szString);
756
757    CreateSpinner (GetDlgItem (hDlg, IDC_KEY_VERSION), 10, FALSE, 0, lpp->keyVersion, 255);
758    CreateKey_OnSelect (hDlg);
759 }
760
761
762 void CreateKey_OnSelect (HWND hDlg)
763 {
764    EnableWindow (GetDlgItem (hDlg, IDC_KEY_STRING), IsDlgButtonChecked (hDlg, IDC_KEY_BYSTRING));
765    EnableWindow (GetDlgItem (hDlg, IDC_KEY_DATA),   IsDlgButtonChecked (hDlg, IDC_KEY_BYDATA));
766    EnableWindow (GetDlgItem (hDlg, IDC_KEY_RANDOM), IsDlgButtonChecked (hDlg, IDC_KEY_BYDATA));
767    CreateKey_OnType (hDlg);
768 }
769
770
771 void CreateKey_OnType (HWND hDlg)
772 {
773    BOOL fEnable = FALSE;
774
775    if (IsDlgButtonChecked (hDlg, IDC_KEY_BYSTRING))
776       {
777       TCHAR szKey[ cchRESOURCE ];
778       GetDlgItemText (hDlg, IDC_KEY_STRING, szKey, cchRESOURCE);
779       if (szKey[0] != TEXT('\0'))
780          fEnable = TRUE;
781       }
782    else // (IsDlgButtonChecked (hDlg, IDC_KEY_BYDATA))
783       {
784       TCHAR szKey[ cchRESOURCE ];
785       GetDlgItemText (hDlg, IDC_KEY_DATA, szKey, cchRESOURCE);
786
787       ENCRYPTIONKEY key;
788       if (ScanServerKey (&key, szKey))
789          fEnable = TRUE;
790       }
791
792    EnableWindow (GetDlgItem (hDlg, IDOK), fEnable);
793 }
794
795
796 void CreateKey_OnRandom (HWND hDlg, LPKEY_CREATE_PARAMS lpp)
797 {
798    StartTask (taskSVR_GETRANDOMKEY, hDlg, lpp->lpiServer);
799 }
800
801
802 BOOL CreateKey_OnOK (HWND hDlg, LPKEY_CREATE_PARAMS lpp)
803 {
804    if (IsDlgButtonChecked (hDlg, IDC_KEY_BYSTRING))
805       {
806       GetDlgItemText (hDlg, IDC_KEY_STRING, lpp->szString, cchRESOURCE);
807       }
808    else // (!IsDlgButtonChecked (hDlg, IDC_KEY_BYSTRING))
809       {
810       TCHAR szKey[ cchRESOURCE ];
811       GetDlgItemText (hDlg, IDC_KEY_DATA, szKey, cchRESOURCE);
812
813       if (!ScanServerKey (&lpp->key, szKey))
814          return FALSE;
815       }
816
817    lpp->keyVersion = (int) SP_GetPos (GetDlgItem (hDlg, IDC_KEY_VERSION));
818    return TRUE;
819 }
820
821
822 void CreateKey_OnEndTask_Random (HWND hDlg, LPTASKPACKET ptp)
823 {
824    if (!ptp->rc)
825       {
826       EnableWindow (GetDlgItem (hDlg, IDC_KEY_RANDOM), FALSE);
827       }
828    else
829       {
830       TCHAR szKey[ cchRESOURCE ];
831       FormatServerKey (szKey, &TASKDATA(ptp)->key);
832       SetDlgItemText (hDlg, IDC_KEY_DATA, szKey);
833       }
834 }
835