Hi,
This patch should be improved to use ssh-agent to cache a key to unlock the stored passwords.
Mike
ChageLog: * implement password caching
Index: dlls/mpr/pwcache.c =================================================================== RCS file: /home/wine/wine/dlls/mpr/pwcache.c,v retrieving revision 1.7 diff -u -r1.7 pwcache.c --- dlls/mpr/pwcache.c 12 May 2003 03:29:50 -0000 1.7 +++ dlls/mpr/pwcache.c 17 Jul 2003 16:35:34 -0000 @@ -2,6 +2,7 @@ * MPR Password Cache functions * * Copyright 1999 Ulrich Weigand + * Copyright 2003 Mike McCormack for Codeweavers * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public @@ -18,12 +19,33 @@ * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA */ +#include <stdio.h> + #include "winbase.h" #include "winnetwk.h" +#include "winreg.h" #include "wine/debug.h" WINE_DEFAULT_DEBUG_CHANNEL(mpr); +static LPCSTR mpr_key = "Software\\Wine\\Wine\\Mpr\\"; + +static LPSTR MPR_GetValueName( LPSTR pbResource, WORD cbResource, BYTE nType ) +{ + LPSTR name; + DWORD i, x = 0; + + /* just a hash so the value name doesn't get too large */ + for( i=0; i<cbResource; i++ ) + x = ((x<<7) | (x >> 25)) ^ toupper(pbResource[i]); + + name = HeapAlloc( GetProcessHeap(), 0, 0x10 ); + if( name ) + sprintf( name, "I-%08lX-%02X", x, nType ); + TRACE( "Value is %s\n", name ); + return name; +} + /************************************************************************** * WNetCachePassword [MPR.@] Saves password in cache * @@ -45,12 +67,36 @@ WORD x) { - FIXME( "(%p(%s), %d, %p(%s), %d, %d, 0x%08x): stub\n", + HKEY hkey; + DWORD r; + LPSTR valname; + + WARN( "(%p(%s), %d, %p(%s), %d, %d, 0x%08x): totally insecure\n", pbResource, debugstr_a(pbResource), cbResource, pbPassword, debugstr_a(pbPassword), cbPassword, nType, x ); - return WN_NOT_SUPPORTED; + r = RegCreateKeyA( HKEY_CURRENT_USER, mpr_key, &hkey ); + if( r ) + return WN_ACCESS_DENIED; + + valname = MPR_GetValueName( pbResource, cbResource, nType ); + if( valname ) + { + r = RegSetValueExA( hkey, valname, 0, REG_BINARY, + pbPassword, cbPassword ); + if( r ) + r = WN_ACCESS_DENIED; + else + r = WN_SUCCESS; + HeapFree( GetProcessHeap(), 0, valname ); + } + else + r = WN_OUT_OF_MEMORY; + + RegCloseKey( hkey ); + + return r; } /***************************************************************** @@ -59,10 +105,31 @@ UINT WINAPI WNetRemoveCachedPassword( LPSTR pbResource, WORD cbResource, BYTE nType ) { - FIXME( "(%p(%s), %d, %d): stub\n", + HKEY hkey; + DWORD r; + LPSTR valname; + + WARN( "(%p(%s), %d, %d): totally insecure\n", pbResource, debugstr_a(pbResource), cbResource, nType ); - return WN_NOT_SUPPORTED; + r = RegCreateKeyA( HKEY_CURRENT_USER, mpr_key, &hkey ); + if( r ) + return WN_ACCESS_DENIED; + + valname = MPR_GetValueName( pbResource, cbResource, nType ); + if( valname ) + { + r = RegDeleteValueA( hkey, valname ); + if( r ) + r = WN_ACCESS_DENIED; + else + r = WN_SUCCESS; + HeapFree( GetProcessHeap(), 0, valname ); + } + else + r = WN_OUT_OF_MEMORY; + + return r; } /***************************************************************** @@ -89,11 +156,34 @@ LPWORD pcbPassword, /* [out] Receives size of password */ BYTE nType) /* [in] Type of password to retrieve */ { - FIXME( "(%p(%s), %d, %p, %p, %d): stub\n", + HKEY hkey; + DWORD r, type = 0, sz; + LPSTR valname; + + WARN( "(%p(%s), %d, %p, %p, %d): stub\n", pbResource, debugstr_a(pbResource), cbResource, pbPassword, pcbPassword, nType ); - return WN_NOT_SUPPORTED; + r = RegCreateKeyA( HKEY_CURRENT_USER, mpr_key, &hkey ); + if( r ) + return WN_ACCESS_DENIED; + + valname = MPR_GetValueName( pbResource, cbResource, nType ); + if( valname ) + { + sz = *pcbPassword; + r = RegQueryValueExA( hkey, valname, 0, &type, pbPassword, &sz ); + *pcbPassword = sz; + if( r ) + r = WN_ACCESS_DENIED; + else + r = WN_SUCCESS; + HeapFree( GetProcessHeap(), 0, valname ); + } + else + r = WN_OUT_OF_MEMORY; + + return r; } /******************************************************************* @@ -101,6 +191,10 @@ * * NOTES * the parameter count is verifyed + * + * This function is a huge security risk, as virii and such can use + * it to grab all the passwords in the cache. It's bad enough to + * store the passwords (insecurely). * * observed values: * arg1 ptr 0x40xxxxxx -> (no string) @@ -115,7 +209,7 @@ UINT WINAPI WNetEnumCachedPasswords( LPSTR pbPrefix, WORD cbPrefix, BYTE nType, ENUMPASSWORDPROC enumPasswordProc, DWORD x) { - FIXME( "(%p(%s), %d, %d, %p, 0x%08lx): stub\n", + WARN( "(%p(%s), %d, %d, %p, 0x%08lx): don't implement this\n", pbPrefix, debugstr_a(pbPrefix), cbPrefix, nType, enumPasswordProc, x ); Index: include/winnetwk.h =================================================================== RCS file: /home/wine/wine/include/winnetwk.h,v retrieving revision 1.10 diff -u -r1.10 winnetwk.h --- include/winnetwk.h 10 Mar 2002 00:02:34 -0000 1.10 +++ include/winnetwk.h 17 Jul 2003 16:35:34 -0000 @@ -68,7 +68,8 @@ #define RESOURCEUSAGE_CONTAINER 0x00000002 #define RESOURCEUSAGE_NOLOCALDEVICE 0x00000004 #define RESOURCEUSAGE_SIBLING 0x00000008 -#define RESOURCEUSAGE_ALL (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER) +#define RESOURCEUSAGE_ATTACHED 0x00000010 +#define RESOURCEUSAGE_ALL (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_ATTACHED) #define RESOURCEUSAGE_RESERVED 0x80000000 #define RESOURCEDISPLAYTYPE_GENERIC 0x00000000 @@ -388,5 +389,8 @@ typedef BOOL (CALLBACK *ENUMPASSWORDPROC)(PASSWORD_CACHE_ENTRY *, DWORD); UINT WINAPI WNetEnumCachedPasswords( LPSTR, WORD, BYTE, ENUMPASSWORDPROC, DWORD); +DWORD WINAPI WNetGetCachedPassword( LPSTR, WORD, LPSTR, LPWORD, BYTE ); +DWORD WINAPI WNetCachePassword( LPSTR, WORD, LPSTR, WORD, BYTE, WORD ); + #endif /* _WINNETWK_H_ */