472 lines
13 KiB
C++
Raw Normal View History

2000-11-04 10:01:08 +00:00
/*
* Copyright 2000, International Business Machines Corporation and others.
* All Rights Reserved.
*
* This software has been released under the terms of the IBM Public
* License. For details, see the LICENSE file in the top-level source
* directory or online at http://www.openafs.org/dl/license10.html
*/
2000-11-04 02:13:13 +00:00
extern "C" {
#include <afs\stds.h>
#include <afs\param.h>
#include <afs\auth.h>
#include <afs\kautils.h>
#include <rxkad.h>
2000-11-04 02:13:13 +00:00
#include <afs\cm_config.h>
#include <afs\afskfw.h>
#include "ipaddrchg.h"
2000-11-04 02:13:13 +00:00
}
#include "afscreds.h"
2000-11-04 02:13:13 +00:00
/*
* DEFINITIONS ________________________________________________________________
*
*/
#define cREALLOC_CREDS 4
#define cszLIBTOKENS TEXT("afsauthent.dll")
#define cszLIBCONF TEXT("libafsconf.dll")
/*
* DYNAMIC LINKING ____________________________________________________________
*
*/
extern "C" {
typedef unsigned int (*initAFSDirPath_t)(void);
typedef int (*ka_Init_t)(int flags);
typedef int (*rx_Init_t)(int port);
typedef int (*ktc_GetToken_t)(struct ktc_principal *server, struct ktc_token *token, int tokenLen, struct ktc_principal *client);
typedef int (*ktc_ListTokens_t)(int cellNum, int *cellNumP, struct ktc_principal *serverName);
typedef int (*ktc_ForgetToken_t)(struct ktc_principal *server);
typedef int (*ka_UserAuthenticateGeneral_t)(int flags, char *name, char *instance, char *realm, char *password, int lifetime, int *password_expiresP, int spare, char **reasonP);
typedef long (*cm_GetRootCellName_t)(char *namep);
typedef int (*ka_ParseLoginName_t)(char *login, char *name, char *inst, char *cell);
2000-11-04 02:13:13 +00:00
}
static struct l
{
HINSTANCE hInstLibTokens;
HINSTANCE hInstLibConf;
initAFSDirPath_t initAFSDirPathP;
ka_Init_t ka_InitP;
rx_Init_t rx_InitP;
ktc_GetToken_t ktc_GetTokenP;
ktc_ListTokens_t ktc_ListTokensP;
ktc_ForgetToken_t ktc_ForgetTokenP;
ka_UserAuthenticateGeneral_t ka_UserAuthenticateGeneralP;
ka_ParseLoginName_t ka_ParseLoginNameP;
2000-11-04 02:13:13 +00:00
cm_GetRootCellName_t cm_GetRootCellNameP;
} l;
#define initAFSDirPath (*l.initAFSDirPathP)
#define ka_Init (*l.ka_InitP)
#define rx_Init (*l.rx_InitP)
#define ktc_GetToken (*l.ktc_GetTokenP)
#define ktc_ListTokens (*l.ktc_ListTokensP)
#define ktc_ForgetToken (*l.ktc_ForgetTokenP)
#define ka_UserAuthenticateGeneral (*l.ka_UserAuthenticateGeneralP)
#define cm_GetRootCellName (*l.cm_GetRootCellNameP)
BOOL Creds_OpenLibraries (void)
{
if (!l.hInstLibTokens)
{
if ((l.hInstLibTokens = LoadLibrary (cszLIBTOKENS)) != NULL)
{
l.initAFSDirPathP = (initAFSDirPath_t)GetProcAddress (l.hInstLibTokens, "initAFSDirPath");
l.ka_InitP = (ka_Init_t)GetProcAddress (l.hInstLibTokens, "ka_Init");
l.rx_InitP = (rx_Init_t)GetProcAddress (l.hInstLibTokens, "rx_Init");
l.ktc_GetTokenP = (ktc_GetToken_t)GetProcAddress (l.hInstLibTokens, "ktc_GetToken");
l.ktc_ListTokensP = (ktc_ListTokens_t)GetProcAddress (l.hInstLibTokens, "ktc_ListTokens");
l.ktc_ForgetTokenP = (ktc_ForgetToken_t)GetProcAddress (l.hInstLibTokens, "ktc_ForgetToken");
l.ka_ParseLoginNameP = (ka_ParseLoginName_t)GetProcAddress (l.hInstLibTokens, "ka_ParseLoginName");
2000-11-04 02:13:13 +00:00
l.ka_UserAuthenticateGeneralP = (ka_UserAuthenticateGeneral_t)GetProcAddress (l.hInstLibTokens, "ka_UserAuthenticateGeneral");
if (!l.initAFSDirPathP ||
!l.ka_InitP ||
!l.rx_InitP ||
!l.ktc_GetTokenP ||
!l.ktc_ListTokensP ||
!l.ktc_ForgetTokenP ||
!l.ka_ParseLoginNameP ||
2000-11-04 02:13:13 +00:00
!l.ka_UserAuthenticateGeneralP)
{
FreeLibrary (l.hInstLibTokens);
l.hInstLibTokens = NULL;
}
else
{
rx_Init(0);
initAFSDirPath();
ka_Init(0);
}
}
}
if (!l.hInstLibConf)
{
if ((l.hInstLibConf = LoadLibrary (cszLIBCONF)) != NULL)
{
l.cm_GetRootCellNameP = (cm_GetRootCellName_t)GetProcAddress (l.hInstLibConf, "cm_GetRootCellName");
if (!l.cm_GetRootCellNameP)
{
FreeLibrary (l.hInstLibConf);
l.hInstLibConf = NULL;
}
}
}
return l.hInstLibTokens && l.hInstLibConf;
}
void Creds_CloseLibraries (void)
{
if (l.hInstLibTokens)
{
FreeLibrary (l.hInstLibTokens);
l.hInstLibTokens = NULL;
}
if (l.hInstLibConf)
{
FreeLibrary (l.hInstLibConf);
l.hInstLibConf = NULL;
}
}
/*
* ROUTINES ___________________________________________________________________
*
*/
void GetGatewayName (LPTSTR pszGateway)
{
*pszGateway = TEXT('\0');
HKEY hk;
if (RegOpenKey (HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters"), &hk) == 0)
{
DWORD dwSize = MAX_PATH;
DWORD dwType = REG_SZ;
if (RegQueryValueEx (hk, TEXT("Gateway"), NULL, &dwType, (PBYTE)pszGateway, &dwSize) != 0)
*pszGateway = TEXT('\0');
RegCloseKey (hk);
}
}
BOOL IsServiceRunning (void)
{
if (g.fIsWinNT)
{
SERVICE_STATUS Status;
memset (&Status, 0x00, sizeof(Status));
Status.dwCurrentState = SERVICE_STOPPED;
SC_HANDLE hManager;
if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
{
SC_HANDLE hService;
if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
{
QueryServiceStatus (hService, &Status);
CloseServiceHandle (hService);
} else if ( IsDebuggerPresent() )
OutputDebugString("Unable to open Transarc AFS Daemon Service\n");
2000-11-04 02:13:13 +00:00
CloseServiceHandle (hManager);
} else if ( IsDebuggerPresent() )
OutputDebugString("Unable to open SC Manager\n");
2000-11-04 02:13:13 +00:00
return (Status.dwCurrentState == SERVICE_RUNNING);
}
TCHAR szGateway[ MAX_PATH ];
GetGatewayName (szGateway);
return (szGateway[0]) ? TRUE : FALSE;
}
BOOL IsServicePersistent (void)
{
struct {
QUERY_SERVICE_CONFIG Config;
BYTE buf[1024];
} Config;
memset (&Config, 0x00, sizeof(Config));
Config.Config.dwStartType = SERVICE_AUTO_START;
SC_HANDLE hManager;
if ((hManager = OpenSCManager (NULL, NULL, GENERIC_READ)) != NULL)
{
SC_HANDLE hService;
if ((hService = OpenService (hManager, TEXT("TransarcAFSDaemon"), GENERIC_READ)) != NULL)
{
DWORD dwSize = sizeof(Config);
QueryServiceConfig (hService, (QUERY_SERVICE_CONFIG*)&Config, sizeof(Config), &dwSize);
CloseServiceHandle (hService);
}
CloseServiceHandle (hManager);
}
return (Config.Config.dwStartType == SERVICE_AUTO_START) ? TRUE : FALSE;
}
BOOL IsServiceConfigured (void)
{
BOOL rc = FALSE;
HKEY hk;
if (!g.fIsWinNT)
{
rc = TRUE;
}
else if (RegOpenKey (HKEY_LOCAL_MACHINE, TEXT("System\\CurrentControlSet\\Services\\TransarcAFSDaemon\\Parameters"), &hk) == 0)
{
TCHAR szCell[ MAX_PATH ];
DWORD dwSize = sizeof(szCell);
DWORD dwType = REG_SZ;
if (RegQueryValueEx (hk, TEXT("Cell"), NULL, &dwType, (PBYTE)szCell, &dwSize) == 0)
{
if (szCell[0] != TEXT('\0'))
rc = TRUE;
}
RegCloseKey (hk);
}
return rc;
}
int GetCurrentCredentials (void)
{
int rc = KTC_NOCM;
lock_ObtainMutex(&g.credsLock);
2000-11-04 02:13:13 +00:00
// Free any knowledge we currently have about the user's credentials
//
if (g.aCreds)
Free (g.aCreds);
g.aCreds = NULL;
g.cCreds = 0;
g.tickLastRetest = GetTickCount();
// Start enumerating tokens.
//
if (!Creds_OpenLibraries())
{
rc = ERROR_DLL_INIT_FAILED;
}
else if (IsServiceRunning())
{
for (int iCell = 0; ; )
{
struct ktc_principal Principal;
if ((rc = ktc_ListTokens (iCell, &iCell, &Principal)) != 0)
break;
struct ktc_token Token;
struct ktc_principal ClientName;
if ((rc = ktc_GetToken (&Principal, &Token, sizeof(Token), &ClientName)) != 0)
break;
// Translate what we found about the user's creds in this particular
// cell into something readable.
//
TCHAR szCell[ 256 ];
CopyAnsiToString (szCell, Principal.cell);
if (!szCell[0])
continue;
TCHAR szUser[ 256 ];
CopyAnsiToString (szUser, ClientName.name);
if (ClientName.instance[0])
{
lstrcat (szUser, TEXT("."));
CopyAnsiToString (&szUser[ lstrlen(szUser) ], ClientName.instance);
}
SYSTEMTIME stExpires;
TimeToSystemTime (&stExpires, Token.endTime);
// We've found out that the user has--or perhaps recently had--
// credentials within a certain cell under the certain name.
// Stick that knowledge in our g.aCreds array.
//
for (size_t iCreds = 0; iCreds < g.cCreds; ++iCreds)
{
if (!lstrcmpi (g.aCreds[ iCreds ].szCell, szCell))
break;
}
if (iCreds == g.cCreds)
{
for (iCreds = 0; iCreds < g.cCreds; ++iCreds)
{
if (!g.aCreds[ iCreds ].szCell[0])
break;
}
if (!REALLOC (g.aCreds, g.cCreds, 1+iCreds, cREALLOC_CREDS))
break;
}
lstrcpy (g.aCreds[ iCreds ].szCell, szCell);
lstrcpy (g.aCreds[ iCreds ].szUser, szUser);
memcpy (&g.aCreds[ iCreds ].stExpires, &stExpires, sizeof(SYSTEMTIME));
LoadRemind (iCreds);
}
}
lock_ReleaseMutex(&g.credsLock);
2000-11-04 02:13:13 +00:00
// We've finished updating g.aCreds. Update the tray icon to reflect
// whether the user currently has any credentials at all, and
// re-enable the Remind timer.
//
ChangeTrayIcon (NIM_MODIFY);
return rc;
}
int DestroyCurrentCredentials (LPCTSTR pszCell)
{
int rc = KTC_NOCM;
if (!Creds_OpenLibraries())
{
rc = ERROR_DLL_INIT_FAILED;
}
else if (IsServiceRunning())
{
struct ktc_principal Principal;
memset (&Principal, 0x00, sizeof(Principal));
CopyStringToAnsi (Principal.cell, pszCell);
CopyStringToAnsi (Principal.name, TEXT("afs"));
rc = ktc_ForgetToken (&Principal);
skyrope-mit-merge-hell-20040226 From Skyrope: The Skyrope work attempted to improve on the end user experience of using OpenAFS in the following ways: * Obtain tokens using renewable Kerberos 5 tickets in order to reduce the need for end users to renew expired tokens * Monitor the list of IP Addresses in order to detect changes in the network configuration which might affect the reachability of cells or the state of the AFS Client Service. When cells are newly reachable, obtain tokens for the cells. If the AFS Client Service is not running, start it. If tokens are expiring attempt to renew them. * Use KDC probes to detect the accessibility of realms/cells. If the KDC is not reachable, do not prompt the end user for a username and password. (fs probe is not implemented on windows) * Automatically obtain tokens using the Windows Logon Session Kerberos credentials (if available) * Allow tokens for multiple cells to be obtained by using the same Kerberos 5 tickets. (no UI yet implemented) * Perform drive mapping persistance by tracking it within the afsdsbmt.ini file instead of relying on the Windows Shell to persist the state. * Add new afscreds.exe command line options and change the default set used when creating the "AFS Credentials" shortcut in the Start Menu->Programs->Startup folder. From MIT: * Auto-detection of loopback adapters. Use "AFS" as the netbios name when a loopback adapter is installed. * Support for responding to power management events. Used to flush the cache when the machine is about to suspend, hibernate, or shutdown * Documentation of Registry entries * Support for Extended SMB Requests * Beginning of support for true Event Log reporting from a message database * Hidden Dot File support (configured via the HideDotFiles registry option) * Configurable Max number of Multiplexed Sessions (MaxMpxRequests registry option) * Configurable Max MTU size (RxMaxMTU registry option) * Configurable Jumbogram support (RxNoJumbo registry option) * Configurable Max number of Virtual Connections per Server (MaxVCPerServer registry option) * Win32 DNS API support * Addition of SMB_ATTR_xxxx defines for use instead of hex numbers * A variety of heap access and resource deallocation errors corrected in the SMB code * Support for recursive directory creation * Modifications to the en_US version of the client configuration dialog (need to port to other languages) Notes on the current check-in: * The KfW code will always be used when installed on the machine. This code only supports Krb5 and will not work with Krb4 only realms. A registry flag indicating whether or not KfW should be used if found needs to be added. * afscreds.exe needs to have a registry entry created to control the parameter list it should be started with. There should be a dialog to control this in the installer and within afscreds.exe * The MIT method of auto-assigning the mount-root and the netbios name is in conflict with the morgan stanley submissions in some parts of the code. If you are using the loopback adapter with this code both the "NetbiosName" = "AFS" and "Mountroot" = "/afs" registry options must be specified. This will be fixed in coming days.
2004-02-26 19:22:35 +00:00
if ( KFW_is_available() )
KFW_AFS_destroy_tickets_for_cell(Principal.cell);
2000-11-04 02:13:13 +00:00
}
if (rc != 0)
{
int idsTitle = (g.fIsWinNT) ? IDS_ERROR_TITLE : IDS_ERROR_TITLE_95;
int idsDesc = (!g.fIsWinNT) ? IDS_ERROR_DESTROY_95 : (rc == KTC_NOCM) ? IDS_ERROR_DESTROY_NOCM : IDS_ERROR_DESTROY_UNKNOWN;
Message (MB_ICONHAND | MB_OK, idsTitle, idsDesc, TEXT("%s%ld"), pszCell, rc);
}
return rc;
}
int ObtainNewCredentials (LPCTSTR pszCell, LPCTSTR pszUser, LPCTSTR pszPassword, BOOL Silent)
2000-11-04 02:13:13 +00:00
{
int rc = KTC_NOCM;
char *Result = NULL;
if (!Creds_OpenLibraries())
{
rc = ERROR_DLL_INIT_FAILED;
}
else if (IsServiceRunning())
{
char szCellA[ 256 ];
CopyStringToAnsi (szCellA, pszCell);
char szNameA[ 256 ];
CopyStringToAnsi (szNameA, pszUser);
char szPasswordA[ 256 ];
CopyStringToAnsi (szPasswordA, pszPassword);
char szSmbNameA[ MAXRANDOMNAMELEN ];
CopyStringToAnsi (szSmbNameA, g.SmbName);
2000-11-04 02:13:13 +00:00
int Expiration = 0;
if ( KFW_is_available() ) {
// KFW_AFS_get_cred() parses the szNameA field as complete princial including potentially
// a different realm then the specified cell name.
rc = KFW_AFS_get_cred(szNameA, szCellA, szPasswordA, 0, szSmbNameA[0] ? szSmbNameA : NULL, &Result);
} else {
char name[sizeof(szNameA)];
char instance[sizeof(szNameA)];
char cell[sizeof(szNameA)];
name[0] = '\0';
instance[0] = '\0';
cell[0] = '\0';
ka_ParseLoginName(szNameA, name, instance, cell);
if ( szSmbNameA[0] ) {
rc = ka_UserAuthenticateGeneral2(KA_USERAUTH_VERSION+KA_USERAUTH_AUTHENT_LOGON,
name, instance, szCellA, szPasswordA, szSmbNameA, 0, &Expiration, 0, &Result);
} else {
rc = ka_UserAuthenticateGeneral(KA_USERAUTH_VERSION, name, instance, szCellA, szPasswordA, 0, &Expiration, 0, &Result);
}
}
}
2000-11-04 02:13:13 +00:00
if (!Silent && rc != 0)
2000-11-04 02:13:13 +00:00
{
int idsTitle = (g.fIsWinNT) ? IDS_ERROR_TITLE : IDS_ERROR_TITLE_95;
int idsDesc = (g.fIsWinNT) ? IDS_ERROR_OBTAIN : IDS_ERROR_OBTAIN_95;
Message (MB_ICONHAND | MB_OK, idsTitle, idsDesc, TEXT("%s%s%s%ld"), pszCell, pszUser, (Result) ? Result : TEXT(""), rc);
}
return rc;
}
int GetDefaultCell (LPTSTR pszCell)
{
int rc = KTC_NOCM;
*pszCell = TEXT('\0');
if (!Creds_OpenLibraries())
{
rc = ERROR_DLL_INIT_FAILED;
}
else if (IsServiceRunning())
{
char szCellA[ 256 ] = "";
int rc;
HKEY hk;
if (RegOpenKey (HKEY_CURRENT_USER, REGSTR_PATH_OPENAFS_CLIENT, &hk) == 0)
{
DWORD dwSize = sizeof(szCellA);
DWORD dwType = REG_SZ;
RegQueryValueEx (hk, TEXT("Authentication Cell"), NULL, &dwType, (PBYTE)szCellA, &dwSize);
RegCloseKey (hk);
}
if (szCellA[0] == '\0') {
rc = cm_GetRootCellName (szCellA);
} else {
rc = 0;
}
if (rc == 0)
CopyAnsiToString(pszCell, szCellA);
}
return rc;
2000-11-04 02:13:13 +00:00
}