This is the mail archive of the cygwin mailing list for the Cygwin project.


Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]
Other format: [Raw text]

ssh-agent, keychain, and Vista [Was: Re: Vista + cygwin basics]


Karl M wrote:
Karl M wrote:
Just a comment...keychain is pretty heavy for what you get in
Cygwin.
My solution was to launch ssh-agent as a service (one for each
user that wants it). That service spawns the agent and updates
the user environment in the registry so that other processes can
find the ssh-agent process/socket. The advantages are that it is
fast and the agent survives a logout (only rekey for a reboot is
desired).

It is three bash script files and one C program (just compile it with
gcc). The shell scripts (1) install the service, (2) are the service
under cygrunsrv and (3) is the commands to add to your bash_profile.
If you use a different shell, they will need syntax tweaking. The C
program provides access to sending a Windows API call to broadcast a
message for WM_SETTINGCHANGE. This is needed because the user can log
in before the service is started in XP. I think that this all worked
on WIN2k when last I tried it, but it has been a long time since I
touched a WIN2k box. I have no experience with Vista :.).

I'll give that a try. Here's my attempt, using session ids. There's a simple C program to obtain the session id, a patch to apply to /usr/bin/keychain to use it, and the snippet that goes into ~/.bash_profile.


It seems to do what I want, but as you say, keychain does slow down the login process quite a bit. Other drawbacks to my approach:
(1) the console user's ssh-agent does not survive logoff (but remote logons' ssh-agents do, since they all live in session 0).
(2) non-standard, win32-specific patch to /usr/bin/keychain


--
Chuck

#include <stdio.h>
#include <windows.h>

typedef enum _WTS_INFO_CLASS {
  WTSInitialProgram = 0,
  WTSApplicationName = 1,
  WTSWorkingDirectory = 2,
  WTSOEMId = 3,
  WTSSessionId = 4,
  WTSUserName = 5,
  WTSWinStationName = 6,
  WTSDomainName = 7,
  WTSConnectState = 8,
  WTSClientBuildNumber = 9,
  WTSClientName = 10,
  WTSClientDirectory = 11,
  WTSClientProductId = 12,
  WTSClientHardwareId = 13,
  WTSClientAddress = 14,
  WTSClientDisplay = 15,
  WTSClientProtocolType = 16,
  WTSIdleTime = 17,
  WTSLogonTime = 18,
  WTSIncomingBytes = 19,
  WTSOutgoingBytes = 20,
  WTSIncomingFrames = 21,
  WTSOutgoingFrames = 22,
  WTSClientInfo = 23,
  WTSSessionInfo = 24
} WTS_INFO_CLASS;

BOOL WINAPI WTSQuerySessionInformation(
  HANDLE hServer,
  DWORD SessionId,
  WTS_INFO_CLASS WTSInfoClass,
  LPTSTR* ppBuffer,
  DWORD* pBytesReturned
);

void WINAPI WTSFreeMemory(PVOID pMemory);

BOOL WINAPI ProcessIdToSessionId(DWORD dwProcessId, DWORD* pSessionId);


#define WTS_CURRENT_SERVER_HANDLE 0
#define WTS_CURRENT_SESSION -1

typedef BOOL(WINAPI *PFN_WTSQuerySessionInformation)(HANDLE, DWORD, WTS_INFO_CLASS, LPTSTR*, DWORD*);
static PFN_WTSQuerySessionInformation pfnWTSQuerySessionInformation = NULL;

typedef void(WINAPI *PFN_WTSFreeMemory)(PVOID);
static PFN_WTSFreeMemory pfnWTSFreeMemory = NULL;

typedef BOOL(WINAPI *PFN_ProcessIdToSessionId)(DWORD, DWORD*);
static PFN_ProcessIdToSessionId pfnProcessIdToSessionId = NULL;

/**************************************************************************
 * getProcAddress
 **************************************************************************/
FARPROC getProcAddress(LPCTSTR lpModuleName, LPCSTR lpProcName)
{
  HMODULE hModule = NULL;
  FARPROC fpProcAddress = NULL;

  hModule = GetModuleHandle(lpModuleName);
  if (!hModule)
  {
    hModule = LoadLibrary(lpModuleName);
    if (!hModule) return NULL;
  }
  fpProcAddress = GetProcAddress(hModule, lpProcName);
  return fpProcAddress;
}

int main(int argc, char* argv)
{
  DWORD dwLength;
  ULONG sessionId;
  LPTSTR ppBuffer = NULL;

  if((pfnWTSQuerySessionInformation = (PFN_WTSQuerySessionInformation) 
      getProcAddress("wtsapi32","WTSQuerySessionInformationA")) == NULL)
  {
    /* must be on an older OS; there is no session */
    return 1;
  }
  if((pfnWTSFreeMemory = (PFN_WTSFreeMemory) 
      getProcAddress("wtsapi32","WTSFreeMemory")) == NULL)
  {
    /* must be on an older OS; there is no session */
    return 1;
  }
  if((pfnProcessIdToSessionId = (PFN_ProcessIdToSessionId) 
      getProcAddress("kernel32","ProcessIdToSessionId")) == NULL)
  {
    /* must be on an older OS; there is no session */
    return 1;
  }

  if (! (*pfnWTSQuerySessionInformation)(WTS_CURRENT_SERVER_HANDLE,
                                         WTS_CURRENT_SESSION,
                                         WTSSessionId,
                                         &ppBuffer,
                                         &dwLength))
  {
    /* terminal services might not be running. Try... */
    DWORD dwSessionId;
    if (! (*pfnProcessIdToSessionId)(GetCurrentProcessId(), &dwSessionId))
    {
      /* that failed to */
      return 2;
    }
    sessionId = (ULONG)dwSessionId;
  }
  else
  {
    sessionId = (ULONG)(*ppBuffer);
    (*pfnWTSFreeMemory)((PVOID)ppBuffer);
  }
  printf("%u\n", sessionId);
  return 0;
}
--- keychain.orig	2008-04-23 01:01:23.858400000 -0400
+++ keychain	2008-04-23 01:04:31.760600000 -0400
@@ -1376,6 +1376,14 @@
 # simultaneously
 [ -z "$hostopt" ] && hostopt="${HOSTNAME}"
 [ -z "$hostopt" ] && hostopt=`uname -n 2>/dev/null || echo unknown`
+
+# This is Win32 specific
+if [ -f /usr/bin/wts_session.exe ]
+then
+  sessionid=`/usr/bin/wts_session.exe`
+  [ -n "${sessionid}" ] && hostopt="${hostopt}_${sessionid}"
+fi
+
 pidf="${keydir}/${hostopt}-sh"
 cshpidf="${keydir}/${hostopt}-csh"
 fishpidf="${keydir}/${hostopt}-fish"
keychain --noask --quiet
sessionid=
hostname_and_session=$HOSTNAME
[[ -f /usr/bin/wts_session.exe ]] && \
  sessionid=$(/usr/bin/wts_session.exe)
[ -n "$sessionid" ] && hostname_and_session="${hostname_and_session}_${sessionid}"

[[ -f $HOME/.keychain/${hostname_and_session}-sh ]] && \
  source $HOME/.keychain/${hostname_and_session}-sh
#[[ -f $HOME/.keychain/${hostname_and_session}-sh-gpg ]] && \
# source  $HOME/.keychain/${hostname_and_session}-sh-gpg


--
Unsubscribe info:      http://cygwin.com/ml/#unsubscribe-simple
Problem reports:       http://cygwin.com/problems.html
Documentation:         http://cygwin.com/docs.html
FAQ:                   http://cygwin.com/faq/

Index Nav: [Date Index] [Subject Index] [Author Index] [Thread Index]
Message Nav: [Date Prev] [Date Next] [Thread Prev] [Thread Next]