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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 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( LPSTR 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 r
= RegCreateKeyA( HKEY_CURRENT_USER
, mpr_key
, &hkey
);
104 return WN_ACCESS_DENIED
;
106 valname
= MPR_GetValueName( pbResource
, cbResource
, nType
);
109 r
= RegSetValueExA( hkey
, valname
, 0, REG_BINARY
,
110 pbPassword
, cbPassword
);
115 HeapFree( GetProcessHeap(), 0, valname
);
118 r
= WN_OUT_OF_MEMORY
;
125 /*****************************************************************
126 * WNetRemoveCachedPassword [MPR.@]
128 UINT WINAPI
WNetRemoveCachedPassword(
129 LPSTR pbResource
, /* [in] resource ID to delete */
130 WORD cbResource
, /* [in] number of bytes in the resource ID */
131 BYTE nType
) /* [in] Type of the resource to delete */
137 WARN( "(%p(%s), %d, %d): totally insecure\n",
138 pbResource
, debugstr_a(pbResource
), cbResource
, nType
);
140 r
= RegCreateKeyA( HKEY_CURRENT_USER
, mpr_key
, &hkey
);
142 return WN_ACCESS_DENIED
;
144 valname
= MPR_GetValueName( pbResource
, cbResource
, nType
);
147 r
= RegDeleteValueA( hkey
, valname
);
149 r
= WN_ACCESS_DENIED
;
152 HeapFree( GetProcessHeap(), 0, valname
);
155 r
= WN_OUT_OF_MEMORY
;
160 /*****************************************************************
161 * WNetGetCachedPassword [MPR.@] Retrieves password from cache
164 * the stub seems to be wrong:
165 * arg1: ptr 0x40xxxxxx -> (no string)
167 * arg3: ptr 0x40xxxxxx -> (no string)
168 * arg4: ptr 0x40xxxxxx -> 0xc8
171 * ---- everything below this line might be wrong (js) -----
173 * Success: WN_SUCCESS
174 * Failure: WN_ACCESS_DENIED, WN_BAD_PASSWORD, WN_BAD_VALUE,
175 * WN_NET_ERROR, WN_NOT_SUPPORTED, WN_OUT_OF_MEMORY
177 DWORD WINAPI
WNetGetCachedPassword(
178 LPSTR pbResource
, /* [in] Name of workgroup, computer, or resource */
179 WORD cbResource
, /* [in] Size of name */
180 LPSTR pbPassword
, /* [out] Buffer to receive password */
181 LPWORD pcbPassword
, /* [out] Receives size of password */
182 BYTE nType
) /* [in] Type of password to retrieve */
185 DWORD r
, type
= 0, sz
;
188 WARN( "(%p(%s), %d, %p, %p, %d): totally insecure\n",
189 pbResource
, debugstr_a(pbResource
), cbResource
,
190 pbPassword
, pcbPassword
, nType
);
192 memset( pbPassword
, 0, *pcbPassword
);
194 r
= RegCreateKeyA( HKEY_CURRENT_USER
, mpr_key
, &hkey
);
196 return WN_ACCESS_DENIED
;
198 valname
= MPR_GetValueName( pbResource
, cbResource
, nType
);
202 r
= RegQueryValueExA( hkey
, valname
, 0, &type
, pbPassword
, &sz
);
208 HeapFree( GetProcessHeap(), 0, valname
);
211 r
= WN_OUT_OF_MEMORY
;
216 /*******************************************************************
217 * WNetEnumCachedPasswords [MPR.@]
220 * the parameter count is verifyed
222 * This function is a huge security risk, as virii and such can use
223 * it to grab all the passwords in the cache. It's bad enough to
224 * store the passwords (insecurely).
226 * bpPrefix and cbPrefix are used to filter the returned passwords
227 * the first cbPrefix bytes of the password resource identifier
228 * should match the same number of bytes in bpPrefix
231 * Success: WN_SUCCESS (even if no entries were enumerated)
232 * Failure: WN_ACCESS_DENIED, WN_BAD_PASSWORD, WN_BAD_VALUE,
233 * WN_NET_ERROR, WN_NOT_SUPPORTED, WN_OUT_OF_MEMORY
236 UINT WINAPI
WNetEnumCachedPasswords(
237 LPSTR pbPrefix
, /* [in] prefix to filter cache entries */
238 WORD cbPrefix
, /* [in] number of bytes in Prefix substring */
239 BYTE nType
, /* [in] match the Type ID of the entry */
240 ENUMPASSWORDPROC enumPasswordProc
, /* [in] callback function */
241 DWORD param
) /* [in] parameter passed to enum function */
244 DWORD r
, type
, val_sz
, data_sz
, i
, j
, size
;
245 PASSWORD_CACHE_ENTRY
*entry
;
246 CHAR val
[256], prefix
[6];
248 WARN( "(%s, %d, %d, %p, 0x%08lx) totally insecure\n",
249 debugstr_an(pbPrefix
,cbPrefix
), cbPrefix
,
250 nType
, enumPasswordProc
, param
);
252 r
= RegCreateKeyA( HKEY_CURRENT_USER
, mpr_key
, &hkey
);
254 return WN_ACCESS_DENIED
;
256 sprintf(prefix
, "X-%02X-", nType
);
265 r
= RegEnumValueA( hkey
, i
, val
, &val_sz
, NULL
, &type
, NULL
, &data_sz
);
266 if( r
!= ERROR_SUCCESS
)
268 if( type
!= REG_BINARY
)
271 /* check the value is in the format we expect */
272 if( val_sz
< sizeof prefix
)
274 if( memcmp( prefix
, val
, 5 ) )
277 /* decode the value */
278 for(j
=5; j
<val_sz
; j
+=2 )
280 CHAR hi
= ctox( val
[j
] ), lo
= ctox( val
[j
+1] );
281 if( ( hi
< 0 ) || ( lo
< 0 ) )
283 val
[(j
-5)/2] = (hi
<<4) | lo
;
286 /* find the decoded length */
289 if( val_sz
< cbPrefix
)
292 /* check the prefix matches */
293 if( memcmp(val
, pbPrefix
, cbPrefix
) )
296 /* read the value data */
297 size
= sizeof *entry
- sizeof entry
->abResource
[0] + val_sz
+ data_sz
;
298 entry
= HeapAlloc( GetProcessHeap(), 0, sizeof *entry
+ val_sz
+ data_sz
);
299 memcpy( entry
->abResource
, val
, val_sz
);
300 entry
->cbEntry
= size
;
301 entry
->cbResource
= val_sz
;
302 entry
->cbPassword
= data_sz
;
304 entry
->nType
= nType
;
305 r
= RegEnumValueA( hkey
, i
, NULL
, &val_sz
, NULL
, &type
,
306 &entry
->abResource
[val_sz
], &data_sz
);
307 if( r
== ERROR_SUCCESS
)
308 enumPasswordProc( entry
, param
);
309 HeapFree( GetProcessHeap(), 0, entry
);