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