thread-and-timer-corrections-to-afscreds-20031121
[openafs.git] / src / WINNT / client_creds / creds.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 "afscreds.h"
11
12 extern "C" {
13 #include <afs\stds.h>
14 #include <afs\param.h>
15 #include <afs\auth.h>
16 #include <afs\kautils.h>
17 #include <afs\cm_config.h>
18 }
19
20
21 /*
22  * DEFINITIONS ________________________________________________________________
23  *
24  */
25
26 #define cREALLOC_CREDS       4
27
28 #define cszLIBTOKENS         TEXT("afsauthent.dll")
29 #define cszLIBCONF           TEXT("libafsconf.dll")
30
31
32 /*
33  * DYNAMIC LINKING ____________________________________________________________
34  *
35  */
36
37 extern "C" {
38    typedef unsigned int (*initAFSDirPath_t)(void);
39    typedef int (*ka_Init_t)(int flags);
40    typedef int (*rx_Init_t)(int port);
41    typedef int (*ktc_GetToken_t)(struct ktc_principal *server, struct ktc_token *token, int tokenLen, struct ktc_principal *client);
42    typedef int (*ktc_ListTokens_t)(int cellNum, int *cellNumP, struct ktc_principal *serverName);
43    typedef int (*ktc_ForgetToken_t)(struct ktc_principal *server);
44    typedef int (*ka_UserAuthenticateGeneral_t)(int flags, char *name, char *instance, char *realm, char *password, int lifetime, int *password_expiresP, int spare, char **reasonP);
45    typedef long (*cm_GetRootCellName_t)(char *namep);
46 }
47
48 static struct l
49    {
50    HINSTANCE hInstLibTokens;
51    HINSTANCE hInstLibConf;
52
53    initAFSDirPath_t initAFSDirPathP;
54    ka_Init_t ka_InitP;
55    rx_Init_t rx_InitP;
56    ktc_GetToken_t ktc_GetTokenP;
57    ktc_ListTokens_t ktc_ListTokensP;
58    ktc_ForgetToken_t ktc_ForgetTokenP;
59    ka_UserAuthenticateGeneral_t ka_UserAuthenticateGeneralP;
60    cm_GetRootCellName_t cm_GetRootCellNameP;
61    } l;
62
63 #define initAFSDirPath (*l.initAFSDirPathP)
64 #define ka_Init (*l.ka_InitP)
65 #define rx_Init (*l.rx_InitP)
66 #define ktc_GetToken (*l.ktc_GetTokenP)
67 #define ktc_ListTokens (*l.ktc_ListTokensP)
68 #define ktc_ForgetToken (*l.ktc_ForgetTokenP)
69 #define ka_UserAuthenticateGeneral (*l.ka_UserAuthenticateGeneralP)
70 #define cm_GetRootCellName (*l.cm_GetRootCellNameP)
71
72
73 BOOL Creds_OpenLibraries (void)
74 {
75    if (!l.hInstLibTokens)
76       {
77       if ((l.hInstLibTokens = LoadLibrary (cszLIBTOKENS)) != NULL)
78          {
79          l.initAFSDirPathP = (initAFSDirPath_t)GetProcAddress (l.hInstLibTokens, "initAFSDirPath");
80          l.ka_InitP = (ka_Init_t)GetProcAddress (l.hInstLibTokens, "ka_Init");
81          l.rx_InitP = (rx_Init_t)GetProcAddress (l.hInstLibTokens, "rx_Init");
82          l.ktc_GetTokenP = (ktc_GetToken_t)GetProcAddress (l.hInstLibTokens, "ktc_GetToken");
83          l.ktc_ListTokensP = (ktc_ListTokens_t)GetProcAddress (l.hInstLibTokens, "ktc_ListTokens");
84          l.ktc_ForgetTokenP = (ktc_ForgetToken_t)GetProcAddress (l.hInstLibTokens, "ktc_ForgetToken");
85          l.ka_UserAuthenticateGeneralP = (ka_UserAuthenticateGeneral_t)GetProcAddress (l.hInstLibTokens, "ka_UserAuthenticateGeneral");
86
87          if (!l.initAFSDirPathP ||
88              !l.ka_InitP ||
89              !l.rx_InitP ||
90              !l.ktc_GetTokenP ||
91              !l.ktc_ListTokensP ||
92              !l.ktc_ForgetTokenP ||
93              !l.ka_UserAuthenticateGeneralP)
94             {
95             FreeLibrary (l.hInstLibTokens);
96             l.hInstLibTokens = NULL;
97             }
98          else
99             {
100             rx_Init(0);
101             initAFSDirPath();
102             ka_Init(0);
103             }
104          }
105       }
106
107    if (!l.hInstLibConf)
108       {
109       if ((l.hInstLibConf = LoadLibrary (cszLIBCONF)) != NULL)
110          {
111          l.cm_GetRootCellNameP = (cm_GetRootCellName_t)GetProcAddress (l.hInstLibConf, "cm_GetRootCellName");
112
113          if (!l.cm_GetRootCellNameP)
114             {
115             FreeLibrary (l.hInstLibConf);
116             l.hInstLibConf = NULL;
117             }
118          }
119       }
120
121    return l.hInstLibTokens && l.hInstLibConf;
122 }
123
124
125 void Creds_CloseLibraries (void)
126 {
127    if (l.hInstLibTokens)
128       {
129       FreeLibrary (l.hInstLibTokens);
130       l.hInstLibTokens = NULL;
131       }
132
133    if (l.hInstLibConf)
134       {
135       FreeLibrary (l.hInstLibConf);
136       l.hInstLibConf = NULL;
137       }
138 }
139
140
141
142 /*
143  * ROUTINES ___________________________________________________________________
144  *
145  */
146
147 void GetGatewayName (LPTSTR pszGateway)
148 {
149    *pszGateway = TEXT('\0');
150    HKEY hk;
151    if (RegOpenKey (HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters"), &hk) == 0)
152       {
153       DWORD dwSize = MAX_PATH;
154       DWORD dwType = REG_SZ;
155
156       if (RegQueryValueEx (hk, TEXT("Gateway"), NULL, &dwType, (PBYTE)pszGateway, &dwSize) != 0)
157          *pszGateway = TEXT('\0');
158
159       RegCloseKey (hk);
160       }
161 }
162
163
164 BOOL IsServiceRunning (void)
165 {
166    if (g.fIsWinNT)
167       {
168       SERVICE_STATUS Status;
169       memset (&Status, 0x00, sizeof(Status));
170       Status.dwCurrentState = SERVICE_STOPPED;
171
172       SC_HANDLE hManager;
173       if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
174          {
175          SC_HANDLE hService;
176          if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
177             {
178             QueryServiceStatus (hService, &Status);
179             CloseServiceHandle (hService);
180             } else if ( IsDebuggerPresent() )
181                 OutputDebugString("Unable to open Transarc AFS Daemon Service\n");
182
183          CloseServiceHandle (hManager);
184          } else if ( IsDebuggerPresent() )
185              OutputDebugString("Unable to open SC Manager\n");
186
187       return (Status.dwCurrentState == SERVICE_RUNNING);
188       }
189
190    TCHAR szGateway[ MAX_PATH ];
191    GetGatewayName (szGateway);
192    return (szGateway[0]) ? TRUE : FALSE;
193 }
194
195
196 BOOL IsServicePersistent (void)
197 {
198    struct {
199       QUERY_SERVICE_CONFIG Config;
200       BYTE buf[1024];
201    } Config;
202    memset (&Config, 0x00, sizeof(Config));
203    Config.Config.dwStartType = SERVICE_AUTO_START;
204
205    SC_HANDLE hManager;
206    if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
207       {
208       SC_HANDLE hService;
209       if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
210          {
211          DWORD dwSize = sizeof(Config);
212          QueryServiceConfig (hService, (QUERY_SERVICE_CONFIG*)&Config, sizeof(Config), &dwSize);
213
214          CloseServiceHandle (hService);
215          }
216
217       CloseServiceHandle (hManager);
218       }
219
220    return (Config.Config.dwStartType == SERVICE_AUTO_START) ? TRUE : FALSE;
221 }
222
223
224 BOOL IsServiceConfigured (void)
225 {
226    BOOL rc = FALSE;
227    HKEY hk;
228
229    if (!g.fIsWinNT)
230       {
231       rc = TRUE;
232       }
233    else if (RegOpenKey (HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters"), &hk) == 0)
234       {
235       TCHAR szCell[ MAX_PATH ];
236       DWORD dwSize = sizeof(szCell);
237       DWORD dwType = REG_SZ;
238
239       if (RegQueryValueEx (hk, TEXT("Cell"), NULL, &dwType, (PBYTE)szCell, &dwSize) == 0)
240          {
241          if (szCell[0] != TEXT('\0'))
242             rc = TRUE;
243          }
244
245       RegCloseKey (hk);
246       }
247
248    return rc;
249 }
250
251
252 int GetCurrentCredentials (void)
253 {
254    int rc = KTC_NOCM;
255
256    lock_ObtainMutex(&g.credsLock);
257
258    // Free any knowledge we currently have about the user's credentials
259    //
260    if (g.aCreds)
261       Free (g.aCreds);
262    g.aCreds = NULL;
263    g.cCreds = 0;
264    g.tickLastRetest = GetTickCount();
265
266    // Start enumerating tokens.
267    //
268    if (!Creds_OpenLibraries())
269       {
270       rc = ERROR_DLL_INIT_FAILED;
271       }
272    else if (IsServiceRunning())
273       {
274       for (int iCell = 0; ; )
275          {
276          struct ktc_principal Principal;
277          if ((rc = ktc_ListTokens (iCell, &iCell, &Principal)) != 0)
278             break;
279
280          struct ktc_token Token;
281          struct ktc_principal ClientName;
282          if ((rc = ktc_GetToken (&Principal, &Token, sizeof(Token), &ClientName)) != 0)
283             break;
284
285          // Translate what we found about the user's creds in this particular
286          // cell into something readable.
287          //
288          TCHAR szCell[ 256 ];
289          CopyAnsiToString (szCell, Principal.cell);
290          if (!szCell[0])
291             continue;
292
293          TCHAR szUser[ 256 ];
294          CopyAnsiToString (szUser, ClientName.name);
295          if (ClientName.instance[0])
296             {
297             lstrcat (szUser, TEXT("."));
298             CopyAnsiToString (&szUser[ lstrlen(szUser) ], ClientName.instance);
299             }
300
301          SYSTEMTIME stExpires;
302          TimeToSystemTime (&stExpires, Token.endTime);
303
304          // We've found out that the user has--or perhaps recently had--
305          // credentials within a certain cell under the certain name.
306          // Stick that knowledge in our g.aCreds array.
307          //
308          for (size_t iCreds = 0; iCreds < g.cCreds; ++iCreds)
309             {
310             if (!lstrcmpi (g.aCreds[ iCreds ].szCell, szCell))
311                break;
312             }
313          if (iCreds == g.cCreds)
314             {
315             for (iCreds = 0; iCreds < g.cCreds; ++iCreds)
316                {
317                if (!g.aCreds[ iCreds ].szCell[0])
318                   break;
319                }
320             if (!REALLOC (g.aCreds, g.cCreds, 1+iCreds, cREALLOC_CREDS))
321                break;
322             }
323
324          lstrcpy (g.aCreds[ iCreds ].szCell, szCell);
325          lstrcpy (g.aCreds[ iCreds ].szUser, szUser);
326          memcpy (&g.aCreds[ iCreds ].stExpires, &stExpires, sizeof(SYSTEMTIME));
327          LoadRemind (iCreds);
328          }
329       }
330
331    lock_ReleaseMutex(&g.credsLock);
332
333    // We've finished updating g.aCreds. Update the tray icon to reflect
334    // whether the user currently has any credentials at all, and
335    // re-enable the Remind timer.
336    //
337    ChangeTrayIcon (NIM_MODIFY);
338    return rc;
339 }
340
341
342 int DestroyCurrentCredentials (LPCTSTR pszCell)
343 {
344    int rc = KTC_NOCM;
345
346    if (!Creds_OpenLibraries())
347       {
348       rc = ERROR_DLL_INIT_FAILED;
349       }
350    else if (IsServiceRunning())
351       {
352       struct ktc_principal Principal;
353       memset (&Principal, 0x00, sizeof(Principal));
354       CopyStringToAnsi (Principal.cell, pszCell);
355       CopyStringToAnsi (Principal.name, TEXT("afs"));
356       rc = ktc_ForgetToken (&Principal);
357       }
358
359    if (rc != 0)
360       {
361       int idsTitle = (g.fIsWinNT) ? IDS_ERROR_TITLE : IDS_ERROR_TITLE_95;
362       int idsDesc = (!g.fIsWinNT) ? IDS_ERROR_DESTROY_95 : (rc == KTC_NOCM) ? IDS_ERROR_DESTROY_NOCM : IDS_ERROR_DESTROY_UNKNOWN;
363       Message (MB_ICONHAND | MB_OK, idsTitle, idsDesc, TEXT("%s%ld"), pszCell, rc);
364       }
365
366    return rc;
367 }
368
369
370 int ObtainNewCredentials (LPCTSTR pszCell, LPCTSTR pszUser, LPCTSTR pszPassword)
371 {
372    int rc = KTC_NOCM;
373    char *Result = NULL;
374
375    if (!Creds_OpenLibraries())
376       {
377       rc = ERROR_DLL_INIT_FAILED;
378       }
379    else if (IsServiceRunning())
380       {
381       char szCellA[ 256 ];
382       CopyStringToAnsi (szCellA, pszCell);
383
384       char szNameA[ 256 ];
385       CopyStringToAnsi (szNameA, pszUser);
386
387       char szPasswordA[ 256 ];
388       CopyStringToAnsi (szPasswordA, pszPassword);
389
390       int Expiration = 0;
391
392       rc = ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION, szNameA, "", szCellA, szPasswordA, 0, &Expiration, 0, &Result);
393       }
394
395    if (rc != 0)
396       {
397       int idsTitle = (g.fIsWinNT) ? IDS_ERROR_TITLE : IDS_ERROR_TITLE_95;
398       int idsDesc = (g.fIsWinNT) ? IDS_ERROR_OBTAIN : IDS_ERROR_OBTAIN_95;
399       Message (MB_ICONHAND | MB_OK, idsTitle, idsDesc, TEXT("%s%s%s%ld"), pszCell, pszUser, (Result) ? Result : TEXT(""), rc);
400       }
401
402    return rc;
403 }
404
405
406 int GetDefaultCell (LPTSTR pszCell)
407 {
408    int rc = KTC_NOCM;
409    *pszCell = TEXT('\0');
410
411    if (!Creds_OpenLibraries())
412       {
413       rc = ERROR_DLL_INIT_FAILED;
414       }
415    else if (IsServiceRunning())
416       {
417       char szCellA[ 256 ];
418
419       int rc;
420       if ((rc = cm_GetRootCellName (szCellA)) == 0)
421          CopyAnsiToString (pszCell, szCellA);
422       }
423
424    return rc;
425 }
426