2 * MPR Password Cache functions
4 * Copyright 1999 Ulrich Weigand
5 * Copyright 2003,2004 Mike McCormack for CodeWeavers
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
12 * This library is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, write to the Free Software
19 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
29 #include "wine/debug.h"
31 WINE_DEFAULT_DEBUG_CHANNEL(mpr
);
33 static const char mpr_key
[] = "Software\\Wine\\Wine\\Mpr\\";
35 static inline BYTE
hex( BYTE x
)
42 static inline CHAR
ctox( CHAR x
)
44 if( ( x
>= '0' ) && ( x
<= '9' ) )
46 if( ( x
>= 'A' ) && ( x
<= 'F' ) )
48 if( ( x
>= 'a' ) && ( x
<= 'a' ) )
53 static LPSTR
MPR_GetValueName( LPCSTR pbResource
, WORD cbResource
, BYTE nType
)
58 name
= HeapAlloc( GetProcessHeap(), 0, 6+cbResource
*2 );
60 sprintf( name
, "X-%02X-", nType
);
61 for(i
=0; i
<cbResource
; i
++)
63 name
[5+i
*2]=hex((pbResource
[i
]&0xf0)>>4);
64 name
[6+i
*2]=hex(pbResource
[i
]&0x0f);
67 TRACE( "Value is %s\n", name
);
72 /**************************************************************************
73 * WNetCachePassword [MPR.@] Saves password in cache
76 * only the parameter count is verifyed
78 * ---- everything below this line might be wrong (js) -----
81 * Failure: WN_ACCESS_DENIED, WN_BAD_PASSWORD, WN_BADVALUE, WN_NET_ERROR,
82 * WN_NOT_SUPPORTED, WN_OUT_OF_MEMORY
84 DWORD WINAPI
WNetCachePassword(
85 LPSTR pbResource
, /* [in] Name of workgroup, computer, or resource */
86 WORD cbResource
, /* [in] Size of name */
87 LPSTR pbPassword
, /* [in] Buffer containing password */
88 WORD cbPassword
, /* [in] Size of password */
89 BYTE nType
, /* [in] Type of password to cache */
97 WARN( "(%p(%s), %d, %p(%s), %d, %d, 0x%08x): totally insecure\n",
98 pbResource
, debugstr_a(pbResource
), cbResource
,
99 pbPassword
, debugstr_a(pbPassword
), cbPassword
,
102 /* @@ Wine registry key: HKCU\Software\Wine\Wine\Mpr */
103 r
= RegCreateKeyA( HKEY_CURRENT_USER
, mpr_key
, &hkey
);
105 return WN_ACCESS_DENIED
;
107 valname
= MPR_GetValueName( pbResource
, cbResource
, nType
);
110 r
= RegSetValueExA( hkey
, valname
, 0, REG_BINARY
,
111 (LPBYTE
)pbPassword
, cbPassword
);
116 HeapFree( GetProcessHeap(), 0, valname
);
119 r
= WN_OUT_OF_MEMORY
;
126 /*****************************************************************
127 * WNetRemoveCachedPassword [MPR.@]
129 UINT WINAPI
WNetRemoveCachedPassword(
130 LPSTR pbResource
, /* [in] resource ID to delete */
131 WORD cbResource
, /* [in] number of bytes in the resource ID */
132 BYTE nType
) /* [in] Type of the resource to delete */
138 WARN( "(%p(%s), %d, %d): totally insecure\n",
139 pbResource
, debugstr_a(pbResource
), cbResource
, nType
);
141 /* @@ Wine registry key: HKCU\Software\Wine\Wine\Mpr */
142 r
= RegCreateKeyA( HKEY_CURRENT_USER
, mpr_key
, &hkey
);
144 return WN_ACCESS_DENIED
;
146 valname
= MPR_GetValueName( pbResource
, cbResource
, nType
);
149 r
= RegDeleteValueA( hkey
, valname
);
151 r
= WN_ACCESS_DENIED
;
154 HeapFree( GetProcessHeap(), 0, valname
);
157 r
= WN_OUT_OF_MEMORY
;
162 /*****************************************************************
163 * WNetGetCachedPassword [MPR.@] Retrieves password from cache
166 * the stub seems to be wrong:
167 * arg1: ptr 0x40xxxxxx -> (no string)
169 * arg3: ptr 0x40xxxxxx -> (no string)
170 * arg4: ptr 0x40xxxxxx -> 0xc8
173 * ---- everything below this line might be wrong (js) -----
175 * Success: WN_SUCCESS
176 * Failure: WN_ACCESS_DENIED, WN_BAD_PASSWORD, WN_BAD_VALUE,
177 * WN_NET_ERROR, WN_NOT_SUPPORTED, WN_OUT_OF_MEMORY
179 DWORD WINAPI
WNetGetCachedPassword(
180 LPSTR pbResource
, /* [in] Name of workgroup, computer, or resource */
181 WORD cbResource
, /* [in] Size of name */
182 LPSTR pbPassword
, /* [out] Buffer to receive password */
183 LPWORD pcbPassword
, /* [out] Receives size of password */
184 BYTE nType
) /* [in] Type of password to retrieve */
187 DWORD r
, type
= 0, sz
;
190 WARN( "(%p(%s), %d, %p, %p, %d): totally insecure\n",
191 pbResource
, debugstr_a(pbResource
), cbResource
,
192 pbPassword
, pcbPassword
, nType
);
194 memset( pbPassword
, 0, *pcbPassword
);
196 /* @@ Wine registry key: HKCU\Software\Wine\Wine\Mpr */
197 r
= RegCreateKeyA( HKEY_CURRENT_USER
, mpr_key
, &hkey
);
199 return WN_ACCESS_DENIED
;
201 valname
= MPR_GetValueName( pbResource
, cbResource
, nType
);
205 r
= RegQueryValueExA( hkey
, valname
, 0, &type
, (LPBYTE
)pbPassword
, &sz
);
211 HeapFree( GetProcessHeap(), 0, valname
);
214 r
= WN_OUT_OF_MEMORY
;
219 /*******************************************************************
220 * WNetEnumCachedPasswords [MPR.@]
223 * the parameter count is verifyed
225 * This function is a huge security risk, as virii and such can use
226 * it to grab all the passwords in the cache. It's bad enough to
227 * store the passwords (insecurely).
229 * bpPrefix and cbPrefix are used to filter the returned passwords
230 * the first cbPrefix bytes of the password resource identifier
231 * should match the same number of bytes in bpPrefix
234 * Success: WN_SUCCESS (even if no entries were enumerated)
235 * Failure: WN_ACCESS_DENIED, WN_BAD_PASSWORD, WN_BAD_VALUE,
236 * WN_NET_ERROR, WN_NOT_SUPPORTED, WN_OUT_OF_MEMORY
239 UINT WINAPI
WNetEnumCachedPasswords(
240 LPSTR pbPrefix
, /* [in] prefix to filter cache entries */
241 WORD cbPrefix
, /* [in] number of bytes in Prefix substring */
242 BYTE nType
, /* [in] match the Type ID of the entry */
243 ENUMPASSWORDPROC enumPasswordProc
, /* [in] callback function */
244 DWORD param
) /* [in] parameter passed to enum function */
247 DWORD r
, type
, val_sz
, data_sz
, i
, j
, size
;
248 PASSWORD_CACHE_ENTRY
*entry
;
249 CHAR val
[256], prefix
[6];
251 WARN( "(%s, %d, %d, %p, 0x%08x) totally insecure\n",
252 debugstr_an(pbPrefix
,cbPrefix
), cbPrefix
,
253 nType
, enumPasswordProc
, param
);
255 /* @@ Wine registry key: HKCU\Software\Wine\Wine\Mpr */
256 r
= RegCreateKeyA( HKEY_CURRENT_USER
, mpr_key
, &hkey
);
258 return WN_ACCESS_DENIED
;
260 sprintf(prefix
, "X-%02X-", nType
);
269 r
= RegEnumValueA( hkey
, i
, val
, &val_sz
, NULL
, &type
, NULL
, &data_sz
);
270 if( r
!= ERROR_SUCCESS
)
272 if( type
!= REG_BINARY
)
275 /* check the value is in the format we expect */
276 if( val_sz
< sizeof prefix
)
278 if( memcmp( prefix
, val
, 5 ) )
281 /* decode the value */
282 for(j
=5; j
<val_sz
; j
+=2 )
284 CHAR hi
= ctox( val
[j
] ), lo
= ctox( val
[j
+1] );
285 if( ( hi
< 0 ) || ( lo
< 0 ) )
287 val
[(j
-5)/2] = (hi
<<4) | lo
;
290 /* find the decoded length */
293 if( val_sz
< cbPrefix
)
296 /* check the prefix matches */
297 if( memcmp(val
, pbPrefix
, cbPrefix
) )
300 /* read the value data */
301 size
= sizeof *entry
- sizeof entry
->abResource
[0] + val_sz
+ data_sz
;
302 entry
= HeapAlloc( GetProcessHeap(), 0, sizeof *entry
+ val_sz
+ data_sz
);
303 memcpy( entry
->abResource
, val
, val_sz
);
304 entry
->cbEntry
= size
;
305 entry
->cbResource
= val_sz
;
306 entry
->cbPassword
= data_sz
;
308 entry
->nType
= nType
;
309 r
= RegEnumValueA( hkey
, i
, NULL
, &val_sz
, NULL
, &type
,
310 &entry
->abResource
[val_sz
], &data_sz
);
311 if( r
== ERROR_SUCCESS
)
312 enumPasswordProc( entry
, param
);
313 HeapFree( GetProcessHeap(), 0, entry
);