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
26 static const char mpr_key
[] = "Software\\Wine\\Wine\\Mpr\\";
28 static inline BYTE
hex( BYTE x
)
35 static inline signed char ctox( CHAR x
)
37 if( ( x
>= '0' ) && ( x
<= '9' ) )
39 if( ( x
>= 'A' ) && ( x
<= 'F' ) )
41 if( ( x
>= 'a' ) && ( x
<= 'a' ) )
46 static LPSTR
MPR_GetValueName( LPCSTR pbResource
, WORD cbResource
, BYTE nType
)
51 name
= HeapAlloc( GetProcessHeap(), 0, 6+cbResource
*2 );
52 if( !name
) return NULL
;
54 sprintf( name
, "X-%02X-", nType
);
55 for(i
=0; i
<cbResource
; i
++)
57 name
[5+i
*2]=hex((pbResource
[i
]&0xf0)>>4);
58 name
[6+i
*2]=hex(pbResource
[i
]&0x0f);
61 TRACE( "Value is %s\n", name
);
66 /**************************************************************************
67 * WNetCachePassword [MPR.@] Saves password in cache
70 * Only the parameter count is verified
72 * ---- everything below this line might be wrong (js) -----
75 * Failure: WN_ACCESS_DENIED, WN_BAD_PASSWORD, WN_BADVALUE, WN_NET_ERROR,
76 * WN_NOT_SUPPORTED, WN_OUT_OF_MEMORY
78 DWORD WINAPI
WNetCachePassword(
79 LPSTR pbResource
, /* [in] Name of workgroup, computer, or resource */
80 WORD cbResource
, /* [in] Size of name */
81 LPSTR pbPassword
, /* [in] Buffer containing password */
82 WORD cbPassword
, /* [in] Size of password */
83 BYTE nType
, /* [in] Type of password to cache */
91 WARN( "(%p(%s), %d, %p(%s), %d, %d, 0x%08x): totally insecure\n",
92 pbResource
, debugstr_a(pbResource
), cbResource
,
93 pbPassword
, debugstr_a(pbPassword
), cbPassword
,
96 /* @@ Wine registry key: HKCU\Software\Wine\Wine\Mpr */
97 r
= RegCreateKeyA( HKEY_CURRENT_USER
, mpr_key
, &hkey
);
99 return WN_ACCESS_DENIED
;
101 valname
= MPR_GetValueName( pbResource
, cbResource
, nType
);
104 r
= RegSetValueExA( hkey
, valname
, 0, REG_BINARY
,
105 (LPBYTE
)pbPassword
, cbPassword
);
110 HeapFree( GetProcessHeap(), 0, valname
);
113 r
= WN_OUT_OF_MEMORY
;
120 /*****************************************************************
121 * WNetRemoveCachedPassword [MPR.@]
123 UINT WINAPI
WNetRemoveCachedPassword(
124 LPSTR pbResource
, /* [in] resource ID to delete */
125 WORD cbResource
, /* [in] number of bytes in the resource ID */
126 BYTE nType
) /* [in] Type of the resource to delete */
132 WARN( "(%p(%s), %d, %d): totally insecure\n",
133 pbResource
, debugstr_a(pbResource
), cbResource
, nType
);
135 /* @@ Wine registry key: HKCU\Software\Wine\Wine\Mpr */
136 r
= RegCreateKeyA( HKEY_CURRENT_USER
, mpr_key
, &hkey
);
138 return WN_ACCESS_DENIED
;
140 valname
= MPR_GetValueName( pbResource
, cbResource
, nType
);
143 r
= RegDeleteValueA( hkey
, valname
);
145 r
= WN_ACCESS_DENIED
;
148 HeapFree( GetProcessHeap(), 0, valname
);
151 r
= WN_OUT_OF_MEMORY
;
156 /*****************************************************************
157 * WNetGetCachedPassword [MPR.@] Retrieves password from cache
160 * the stub seems to be wrong:
161 * arg1: ptr 0x40xxxxxx -> (no string)
163 * arg3: ptr 0x40xxxxxx -> (no string)
164 * arg4: ptr 0x40xxxxxx -> 0xc8
167 * ---- everything below this line might be wrong (js) -----
169 * Success: WN_SUCCESS
170 * Failure: WN_ACCESS_DENIED, WN_BAD_PASSWORD, WN_BAD_VALUE,
171 * WN_NET_ERROR, WN_NOT_SUPPORTED, WN_OUT_OF_MEMORY
173 DWORD WINAPI
WNetGetCachedPassword(
174 LPSTR pbResource
, /* [in] Name of workgroup, computer, or resource */
175 WORD cbResource
, /* [in] Size of name */
176 LPSTR pbPassword
, /* [out] Buffer to receive password */
177 LPWORD pcbPassword
, /* [out] Receives size of password */
178 BYTE nType
) /* [in] Type of password to retrieve */
181 DWORD r
, type
= 0, sz
;
184 WARN( "(%p(%s), %d, %p, %p, %d): totally insecure\n",
185 pbResource
, debugstr_a(pbResource
), cbResource
,
186 pbPassword
, pcbPassword
, nType
);
188 memset( pbPassword
, 0, *pcbPassword
);
190 /* @@ Wine registry key: HKCU\Software\Wine\Wine\Mpr */
191 r
= RegCreateKeyA( HKEY_CURRENT_USER
, mpr_key
, &hkey
);
193 return WN_ACCESS_DENIED
;
195 valname
= MPR_GetValueName( pbResource
, cbResource
, nType
);
199 r
= RegQueryValueExA( hkey
, valname
, 0, &type
, (LPBYTE
)pbPassword
, &sz
);
205 HeapFree( GetProcessHeap(), 0, valname
);
208 r
= WN_OUT_OF_MEMORY
;
213 /*******************************************************************
214 * WNetEnumCachedPasswords [MPR.@]
217 * The parameter count is verified
219 * This function is a huge security risk, as virii and such can use
220 * it to grab all the passwords in the cache. It's bad enough to
221 * store the passwords (insecurely).
223 * bpPrefix and cbPrefix are used to filter the returned passwords
224 * the first cbPrefix bytes of the password resource identifier
225 * should match the same number of bytes in bpPrefix
228 * Success: WN_SUCCESS (even if no entries were enumerated)
229 * Failure: WN_ACCESS_DENIED, WN_BAD_PASSWORD, WN_BAD_VALUE,
230 * WN_NET_ERROR, WN_NOT_SUPPORTED, WN_OUT_OF_MEMORY
233 UINT WINAPI
WNetEnumCachedPasswords(
234 LPSTR pbPrefix
, /* [in] prefix to filter cache entries */
235 WORD cbPrefix
, /* [in] number of bytes in Prefix substring */
236 BYTE nType
, /* [in] match the Type ID of the entry */
237 ENUMPASSWORDPROC enumPasswordProc
, /* [in] callback function */
238 DWORD param
) /* [in] parameter passed to enum function */
241 DWORD r
, type
, val_sz
, data_sz
, i
, j
, size
;
242 PASSWORD_CACHE_ENTRY
*entry
;
243 CHAR val
[256], prefix
[6];
245 WARN( "(%s, %d, %d, %p, 0x%08x) totally insecure\n",
246 debugstr_an(pbPrefix
,cbPrefix
), cbPrefix
,
247 nType
, enumPasswordProc
, param
);
249 /* @@ Wine registry key: HKCU\Software\Wine\Wine\Mpr */
250 r
= RegCreateKeyA( HKEY_CURRENT_USER
, mpr_key
, &hkey
);
252 return WN_ACCESS_DENIED
;
254 sprintf(prefix
, "X-%02X-", nType
);
262 r
= RegEnumValueA( hkey
, i
, val
, &val_sz
, NULL
, &type
, NULL
, &data_sz
);
263 if( r
!= ERROR_SUCCESS
)
265 if( type
!= REG_BINARY
)
268 /* check the value is in the format we expect */
269 if( val_sz
< sizeof prefix
)
271 if( memcmp( prefix
, val
, 5 ) )
274 /* decode the value */
275 for(j
=5; j
<val_sz
; j
+=2 )
277 signed char hi
= ctox( val
[j
] ), lo
= ctox( val
[j
+1] );
278 if( ( hi
< 0 ) || ( lo
< 0 ) )
280 val
[(j
-5)/2] = (hi
<<4) | lo
;
283 /* find the decoded length */
286 if( val_sz
< cbPrefix
)
289 /* check the prefix matches */
290 if( memcmp(val
, pbPrefix
, cbPrefix
) )
293 /* read the value data */
294 size
= offsetof( PASSWORD_CACHE_ENTRY
, abResource
[val_sz
+ data_sz
] );
295 entry
= HeapAlloc( GetProcessHeap(), 0, size
);
296 memcpy( entry
->abResource
, val
, val_sz
);
297 entry
->cbEntry
= size
;
298 entry
->cbResource
= val_sz
;
299 entry
->cbPassword
= data_sz
;
301 entry
->nType
= nType
;
302 r
= RegEnumValueA( hkey
, i
, NULL
, &val_sz
, NULL
, &type
,
303 &entry
->abResource
[val_sz
], &data_sz
);
304 if( r
== ERROR_SUCCESS
)
305 enumPasswordProc( entry
, param
);
306 HeapFree( GetProcessHeap(), 0, entry
);