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