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 signed 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 );
59 if( !name
) return NULL
;
61 sprintf( name
, "X-%02X-", nType
);
62 for(i
=0; i
<cbResource
; i
++)
64 name
[5+i
*2]=hex((pbResource
[i
]&0xf0)>>4);
65 name
[6+i
*2]=hex(pbResource
[i
]&0x0f);
68 TRACE( "Value is %s\n", name
);
73 /**************************************************************************
74 * WNetCachePassword [MPR.@] Saves password in cache
77 * Only the parameter count is verified
79 * ---- everything below this line might be wrong (js) -----
82 * Failure: WN_ACCESS_DENIED, WN_BAD_PASSWORD, WN_BADVALUE, WN_NET_ERROR,
83 * WN_NOT_SUPPORTED, WN_OUT_OF_MEMORY
85 DWORD WINAPI
WNetCachePassword(
86 LPSTR pbResource
, /* [in] Name of workgroup, computer, or resource */
87 WORD cbResource
, /* [in] Size of name */
88 LPSTR pbPassword
, /* [in] Buffer containing password */
89 WORD cbPassword
, /* [in] Size of password */
90 BYTE nType
, /* [in] Type of password to cache */
98 WARN( "(%p(%s), %d, %p(%s), %d, %d, 0x%08x): totally insecure\n",
99 pbResource
, debugstr_a(pbResource
), cbResource
,
100 pbPassword
, debugstr_a(pbPassword
), cbPassword
,
103 /* @@ Wine registry key: HKCU\Software\Wine\Wine\Mpr */
104 r
= RegCreateKeyA( HKEY_CURRENT_USER
, mpr_key
, &hkey
);
106 return WN_ACCESS_DENIED
;
108 valname
= MPR_GetValueName( pbResource
, cbResource
, nType
);
111 r
= RegSetValueExA( hkey
, valname
, 0, REG_BINARY
,
112 (LPBYTE
)pbPassword
, cbPassword
);
117 HeapFree( GetProcessHeap(), 0, valname
);
120 r
= WN_OUT_OF_MEMORY
;
127 /*****************************************************************
128 * WNetRemoveCachedPassword [MPR.@]
130 UINT WINAPI
WNetRemoveCachedPassword(
131 LPSTR pbResource
, /* [in] resource ID to delete */
132 WORD cbResource
, /* [in] number of bytes in the resource ID */
133 BYTE nType
) /* [in] Type of the resource to delete */
139 WARN( "(%p(%s), %d, %d): totally insecure\n",
140 pbResource
, debugstr_a(pbResource
), cbResource
, nType
);
142 /* @@ Wine registry key: HKCU\Software\Wine\Wine\Mpr */
143 r
= RegCreateKeyA( HKEY_CURRENT_USER
, mpr_key
, &hkey
);
145 return WN_ACCESS_DENIED
;
147 valname
= MPR_GetValueName( pbResource
, cbResource
, nType
);
150 r
= RegDeleteValueA( hkey
, valname
);
152 r
= WN_ACCESS_DENIED
;
155 HeapFree( GetProcessHeap(), 0, valname
);
158 r
= WN_OUT_OF_MEMORY
;
163 /*****************************************************************
164 * WNetGetCachedPassword [MPR.@] Retrieves password from cache
167 * the stub seems to be wrong:
168 * arg1: ptr 0x40xxxxxx -> (no string)
170 * arg3: ptr 0x40xxxxxx -> (no string)
171 * arg4: ptr 0x40xxxxxx -> 0xc8
174 * ---- everything below this line might be wrong (js) -----
176 * Success: WN_SUCCESS
177 * Failure: WN_ACCESS_DENIED, WN_BAD_PASSWORD, WN_BAD_VALUE,
178 * WN_NET_ERROR, WN_NOT_SUPPORTED, WN_OUT_OF_MEMORY
180 DWORD WINAPI
WNetGetCachedPassword(
181 LPSTR pbResource
, /* [in] Name of workgroup, computer, or resource */
182 WORD cbResource
, /* [in] Size of name */
183 LPSTR pbPassword
, /* [out] Buffer to receive password */
184 LPWORD pcbPassword
, /* [out] Receives size of password */
185 BYTE nType
) /* [in] Type of password to retrieve */
188 DWORD r
, type
= 0, sz
;
191 WARN( "(%p(%s), %d, %p, %p, %d): totally insecure\n",
192 pbResource
, debugstr_a(pbResource
), cbResource
,
193 pbPassword
, pcbPassword
, nType
);
195 memset( pbPassword
, 0, *pcbPassword
);
197 /* @@ Wine registry key: HKCU\Software\Wine\Wine\Mpr */
198 r
= RegCreateKeyA( HKEY_CURRENT_USER
, mpr_key
, &hkey
);
200 return WN_ACCESS_DENIED
;
202 valname
= MPR_GetValueName( pbResource
, cbResource
, nType
);
206 r
= RegQueryValueExA( hkey
, valname
, 0, &type
, (LPBYTE
)pbPassword
, &sz
);
212 HeapFree( GetProcessHeap(), 0, valname
);
215 r
= WN_OUT_OF_MEMORY
;
220 /*******************************************************************
221 * WNetEnumCachedPasswords [MPR.@]
224 * The parameter count is verified
226 * This function is a huge security risk, as virii and such can use
227 * it to grab all the passwords in the cache. It's bad enough to
228 * store the passwords (insecurely).
230 * bpPrefix and cbPrefix are used to filter the returned passwords
231 * the first cbPrefix bytes of the password resource identifier
232 * should match the same number of bytes in bpPrefix
235 * Success: WN_SUCCESS (even if no entries were enumerated)
236 * Failure: WN_ACCESS_DENIED, WN_BAD_PASSWORD, WN_BAD_VALUE,
237 * WN_NET_ERROR, WN_NOT_SUPPORTED, WN_OUT_OF_MEMORY
240 UINT WINAPI
WNetEnumCachedPasswords(
241 LPSTR pbPrefix
, /* [in] prefix to filter cache entries */
242 WORD cbPrefix
, /* [in] number of bytes in Prefix substring */
243 BYTE nType
, /* [in] match the Type ID of the entry */
244 ENUMPASSWORDPROC enumPasswordProc
, /* [in] callback function */
245 DWORD param
) /* [in] parameter passed to enum function */
248 DWORD r
, type
, val_sz
, data_sz
, i
, j
, size
;
249 PASSWORD_CACHE_ENTRY
*entry
;
250 CHAR val
[256], prefix
[6];
252 WARN( "(%s, %d, %d, %p, 0x%08x) totally insecure\n",
253 debugstr_an(pbPrefix
,cbPrefix
), cbPrefix
,
254 nType
, enumPasswordProc
, param
);
256 /* @@ Wine registry key: HKCU\Software\Wine\Wine\Mpr */
257 r
= RegCreateKeyA( HKEY_CURRENT_USER
, mpr_key
, &hkey
);
259 return WN_ACCESS_DENIED
;
261 sprintf(prefix
, "X-%02X-", nType
);
270 r
= RegEnumValueA( hkey
, i
, val
, &val_sz
, NULL
, &type
, NULL
, &data_sz
);
271 if( r
!= ERROR_SUCCESS
)
273 if( type
!= REG_BINARY
)
276 /* check the value is in the format we expect */
277 if( val_sz
< sizeof prefix
)
279 if( memcmp( prefix
, val
, 5 ) )
282 /* decode the value */
283 for(j
=5; j
<val_sz
; j
+=2 )
285 signed char hi
= ctox( val
[j
] ), lo
= ctox( val
[j
+1] );
286 if( ( hi
< 0 ) || ( lo
< 0 ) )
288 val
[(j
-5)/2] = (hi
<<4) | lo
;
291 /* find the decoded length */
294 if( val_sz
< cbPrefix
)
297 /* check the prefix matches */
298 if( memcmp(val
, pbPrefix
, cbPrefix
) )
301 /* read the value data */
302 size
= sizeof *entry
- sizeof entry
->abResource
[0] + val_sz
+ data_sz
;
303 entry
= HeapAlloc( GetProcessHeap(), 0, sizeof *entry
+ val_sz
+ data_sz
);
304 memcpy( entry
->abResource
, val
, val_sz
);
305 entry
->cbEntry
= size
;
306 entry
->cbResource
= val_sz
;
307 entry
->cbPassword
= data_sz
;
309 entry
->nType
= nType
;
310 r
= RegEnumValueA( hkey
, i
, NULL
, &val_sz
, NULL
, &type
,
311 &entry
->abResource
[val_sz
], &data_sz
);
312 if( r
== ERROR_SUCCESS
)
313 enumPasswordProc( entry
, param
);
314 HeapFree( GetProcessHeap(), 0, entry
);