xref: /aosp_15_r20/external/mdnsresponder/mDNSWindows/Secret.c (revision 48a54d368dc4fa860885eef7b70b6c53499e7c25)
1*48a54d36SAndroid Build Coastguard Worker /* -*- Mode: C; tab-width: 4 -*-
2*48a54d36SAndroid Build Coastguard Worker  *
3*48a54d36SAndroid Build Coastguard Worker  * Copyright (c) 2002-2004 Apple Computer, Inc. All rights reserved.
4*48a54d36SAndroid Build Coastguard Worker  *
5*48a54d36SAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
6*48a54d36SAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
7*48a54d36SAndroid Build Coastguard Worker  * You may obtain a copy of the License at
8*48a54d36SAndroid Build Coastguard Worker  *
9*48a54d36SAndroid Build Coastguard Worker  *     http://www.apache.org/licenses/LICENSE-2.0
10*48a54d36SAndroid Build Coastguard Worker  *
11*48a54d36SAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
12*48a54d36SAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
13*48a54d36SAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14*48a54d36SAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
15*48a54d36SAndroid Build Coastguard Worker  * limitations under the License.
16*48a54d36SAndroid Build Coastguard Worker  */
17*48a54d36SAndroid Build Coastguard Worker 
18*48a54d36SAndroid Build Coastguard Worker #include "Secret.h"
19*48a54d36SAndroid Build Coastguard Worker #include <stdarg.h>
20*48a54d36SAndroid Build Coastguard Worker #include <stddef.h>
21*48a54d36SAndroid Build Coastguard Worker #include <stdio.h>
22*48a54d36SAndroid Build Coastguard Worker #include <stdlib.h>
23*48a54d36SAndroid Build Coastguard Worker #include <string.h>
24*48a54d36SAndroid Build Coastguard Worker #include <winsock2.h>
25*48a54d36SAndroid Build Coastguard Worker #include <ws2tcpip.h>
26*48a54d36SAndroid Build Coastguard Worker #include <windows.h>
27*48a54d36SAndroid Build Coastguard Worker #include <process.h>
28*48a54d36SAndroid Build Coastguard Worker #include <ntsecapi.h>
29*48a54d36SAndroid Build Coastguard Worker #include <lm.h>
30*48a54d36SAndroid Build Coastguard Worker #include "DebugServices.h"
31*48a54d36SAndroid Build Coastguard Worker 
32*48a54d36SAndroid Build Coastguard Worker 
33*48a54d36SAndroid Build Coastguard Worker mDNSlocal OSStatus MakeLsaStringFromUTF8String( PLSA_UNICODE_STRING output, const char * input );
34*48a54d36SAndroid Build Coastguard Worker mDNSlocal OSStatus MakeUTF8StringFromLsaString( char * output, size_t len, PLSA_UNICODE_STRING input );
35*48a54d36SAndroid Build Coastguard Worker 
36*48a54d36SAndroid Build Coastguard Worker 
37*48a54d36SAndroid Build Coastguard Worker BOOL
LsaGetSecret(const char * inDomain,char * outDomain,unsigned outDomainSize,char * outKey,unsigned outKeySize,char * outSecret,unsigned outSecretSize)38*48a54d36SAndroid Build Coastguard Worker LsaGetSecret( const char * inDomain, char * outDomain, unsigned outDomainSize, char * outKey, unsigned outKeySize, char * outSecret, unsigned outSecretSize )
39*48a54d36SAndroid Build Coastguard Worker {
40*48a54d36SAndroid Build Coastguard Worker 	PLSA_UNICODE_STRING		domainLSA;
41*48a54d36SAndroid Build Coastguard Worker 	PLSA_UNICODE_STRING		keyLSA;
42*48a54d36SAndroid Build Coastguard Worker 	PLSA_UNICODE_STRING		secretLSA;
43*48a54d36SAndroid Build Coastguard Worker 	size_t					i;
44*48a54d36SAndroid Build Coastguard Worker 	size_t					dlen;
45*48a54d36SAndroid Build Coastguard Worker 	LSA_OBJECT_ATTRIBUTES	attrs;
46*48a54d36SAndroid Build Coastguard Worker 	LSA_HANDLE				handle = NULL;
47*48a54d36SAndroid Build Coastguard Worker 	NTSTATUS				res;
48*48a54d36SAndroid Build Coastguard Worker 	OSStatus				err;
49*48a54d36SAndroid Build Coastguard Worker 
50*48a54d36SAndroid Build Coastguard Worker 	check( inDomain );
51*48a54d36SAndroid Build Coastguard Worker 	check( outDomain );
52*48a54d36SAndroid Build Coastguard Worker 	check( outKey );
53*48a54d36SAndroid Build Coastguard Worker 	check( outSecret );
54*48a54d36SAndroid Build Coastguard Worker 
55*48a54d36SAndroid Build Coastguard Worker 	// Initialize
56*48a54d36SAndroid Build Coastguard Worker 
57*48a54d36SAndroid Build Coastguard Worker 	domainLSA	= NULL;
58*48a54d36SAndroid Build Coastguard Worker 	keyLSA		= NULL;
59*48a54d36SAndroid Build Coastguard Worker 	secretLSA	= NULL;
60*48a54d36SAndroid Build Coastguard Worker 
61*48a54d36SAndroid Build Coastguard Worker 	// Make sure we have enough space to add trailing dot
62*48a54d36SAndroid Build Coastguard Worker 
63*48a54d36SAndroid Build Coastguard Worker 	dlen = strlen( inDomain );
64*48a54d36SAndroid Build Coastguard Worker 	err = strcpy_s( outDomain, outDomainSize - 2, inDomain );
65*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
66*48a54d36SAndroid Build Coastguard Worker 
67*48a54d36SAndroid Build Coastguard Worker 	// If there isn't a trailing dot, add one because the mDNSResponder
68*48a54d36SAndroid Build Coastguard Worker 	// presents names with the trailing dot.
69*48a54d36SAndroid Build Coastguard Worker 
70*48a54d36SAndroid Build Coastguard Worker 	if ( outDomain[ dlen - 1 ] != '.' )
71*48a54d36SAndroid Build Coastguard Worker 	{
72*48a54d36SAndroid Build Coastguard Worker 		outDomain[ dlen++ ] = '.';
73*48a54d36SAndroid Build Coastguard Worker 		outDomain[ dlen ] = '\0';
74*48a54d36SAndroid Build Coastguard Worker 	}
75*48a54d36SAndroid Build Coastguard Worker 
76*48a54d36SAndroid Build Coastguard Worker 	// Canonicalize name by converting to lower case (keychain and some name servers are case sensitive)
77*48a54d36SAndroid Build Coastguard Worker 
78*48a54d36SAndroid Build Coastguard Worker 	for ( i = 0; i < dlen; i++ )
79*48a54d36SAndroid Build Coastguard Worker 	{
80*48a54d36SAndroid Build Coastguard Worker 		outDomain[i] = (char) tolower( outDomain[i] );  // canonicalize -> lower case
81*48a54d36SAndroid Build Coastguard Worker 	}
82*48a54d36SAndroid Build Coastguard Worker 
83*48a54d36SAndroid Build Coastguard Worker 	// attrs are reserved, so initialize to zeroes.
84*48a54d36SAndroid Build Coastguard Worker 
85*48a54d36SAndroid Build Coastguard Worker 	ZeroMemory( &attrs, sizeof( attrs ) );
86*48a54d36SAndroid Build Coastguard Worker 
87*48a54d36SAndroid Build Coastguard Worker 	// Get a handle to the Policy object on the local system
88*48a54d36SAndroid Build Coastguard Worker 
89*48a54d36SAndroid Build Coastguard Worker 	res = LsaOpenPolicy( NULL, &attrs, POLICY_GET_PRIVATE_INFORMATION, &handle );
90*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
91*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
92*48a54d36SAndroid Build Coastguard Worker 
93*48a54d36SAndroid Build Coastguard Worker 	// Get the encrypted data
94*48a54d36SAndroid Build Coastguard Worker 
95*48a54d36SAndroid Build Coastguard Worker 	domainLSA = ( PLSA_UNICODE_STRING ) malloc( sizeof( LSA_UNICODE_STRING ) );
96*48a54d36SAndroid Build Coastguard Worker 	require_action( domainLSA != NULL, exit, err = mStatus_NoMemoryErr );
97*48a54d36SAndroid Build Coastguard Worker 	err = MakeLsaStringFromUTF8String( domainLSA, outDomain );
98*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
99*48a54d36SAndroid Build Coastguard Worker 
100*48a54d36SAndroid Build Coastguard Worker 	// Retrieve the key
101*48a54d36SAndroid Build Coastguard Worker 
102*48a54d36SAndroid Build Coastguard Worker 	res = LsaRetrievePrivateData( handle, domainLSA, &keyLSA );
103*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
104*48a54d36SAndroid Build Coastguard Worker 	require_noerr_quiet( err, exit );
105*48a54d36SAndroid Build Coastguard Worker 
106*48a54d36SAndroid Build Coastguard Worker 	// <rdar://problem/4192119> Lsa secrets use a flat naming space.  Therefore, we will prepend "$" to the keyname to
107*48a54d36SAndroid Build Coastguard Worker 	// make sure it doesn't conflict with a zone name.
108*48a54d36SAndroid Build Coastguard Worker 	// Strip off the "$" prefix.
109*48a54d36SAndroid Build Coastguard Worker 
110*48a54d36SAndroid Build Coastguard Worker 	err = MakeUTF8StringFromLsaString( outKey, outKeySize, keyLSA );
111*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
112*48a54d36SAndroid Build Coastguard Worker 	require_action( outKey[0] == '$', exit, err = kUnknownErr );
113*48a54d36SAndroid Build Coastguard Worker 	memcpy( outKey, outKey + 1, strlen( outKey ) );
114*48a54d36SAndroid Build Coastguard Worker 
115*48a54d36SAndroid Build Coastguard Worker 	// Retrieve the secret
116*48a54d36SAndroid Build Coastguard Worker 
117*48a54d36SAndroid Build Coastguard Worker 	res = LsaRetrievePrivateData( handle, keyLSA, &secretLSA );
118*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
119*48a54d36SAndroid Build Coastguard Worker 	require_noerr_quiet( err, exit );
120*48a54d36SAndroid Build Coastguard Worker 
121*48a54d36SAndroid Build Coastguard Worker 	// Convert the secret to UTF8 string
122*48a54d36SAndroid Build Coastguard Worker 
123*48a54d36SAndroid Build Coastguard Worker 	err = MakeUTF8StringFromLsaString( outSecret, outSecretSize, secretLSA );
124*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
125*48a54d36SAndroid Build Coastguard Worker 
126*48a54d36SAndroid Build Coastguard Worker exit:
127*48a54d36SAndroid Build Coastguard Worker 
128*48a54d36SAndroid Build Coastguard Worker 	if ( domainLSA != NULL )
129*48a54d36SAndroid Build Coastguard Worker 	{
130*48a54d36SAndroid Build Coastguard Worker 		if ( domainLSA->Buffer != NULL )
131*48a54d36SAndroid Build Coastguard Worker 		{
132*48a54d36SAndroid Build Coastguard Worker 			free( domainLSA->Buffer );
133*48a54d36SAndroid Build Coastguard Worker 		}
134*48a54d36SAndroid Build Coastguard Worker 
135*48a54d36SAndroid Build Coastguard Worker 		free( domainLSA );
136*48a54d36SAndroid Build Coastguard Worker 	}
137*48a54d36SAndroid Build Coastguard Worker 
138*48a54d36SAndroid Build Coastguard Worker 	if ( keyLSA != NULL )
139*48a54d36SAndroid Build Coastguard Worker 	{
140*48a54d36SAndroid Build Coastguard Worker 		LsaFreeMemory( keyLSA );
141*48a54d36SAndroid Build Coastguard Worker 	}
142*48a54d36SAndroid Build Coastguard Worker 
143*48a54d36SAndroid Build Coastguard Worker 	if ( secretLSA != NULL )
144*48a54d36SAndroid Build Coastguard Worker 	{
145*48a54d36SAndroid Build Coastguard Worker 		LsaFreeMemory( secretLSA );
146*48a54d36SAndroid Build Coastguard Worker 	}
147*48a54d36SAndroid Build Coastguard Worker 
148*48a54d36SAndroid Build Coastguard Worker 	if ( handle )
149*48a54d36SAndroid Build Coastguard Worker 	{
150*48a54d36SAndroid Build Coastguard Worker 		LsaClose( handle );
151*48a54d36SAndroid Build Coastguard Worker 		handle = NULL;
152*48a54d36SAndroid Build Coastguard Worker 	}
153*48a54d36SAndroid Build Coastguard Worker 
154*48a54d36SAndroid Build Coastguard Worker 	return ( !err ) ? TRUE : FALSE;
155*48a54d36SAndroid Build Coastguard Worker }
156*48a54d36SAndroid Build Coastguard Worker 
157*48a54d36SAndroid Build Coastguard Worker 
158*48a54d36SAndroid Build Coastguard Worker mDNSBool
LsaSetSecret(const char * inDomain,const char * inKey,const char * inSecret)159*48a54d36SAndroid Build Coastguard Worker LsaSetSecret( const char * inDomain, const char * inKey, const char * inSecret )
160*48a54d36SAndroid Build Coastguard Worker {
161*48a54d36SAndroid Build Coastguard Worker 	size_t					inDomainLength;
162*48a54d36SAndroid Build Coastguard Worker 	size_t					inKeyLength;
163*48a54d36SAndroid Build Coastguard Worker 	char					domain[ 1024 ];
164*48a54d36SAndroid Build Coastguard Worker 	char					key[ 1024 ];
165*48a54d36SAndroid Build Coastguard Worker 	LSA_OBJECT_ATTRIBUTES	attrs;
166*48a54d36SAndroid Build Coastguard Worker 	LSA_HANDLE				handle = NULL;
167*48a54d36SAndroid Build Coastguard Worker 	NTSTATUS				res;
168*48a54d36SAndroid Build Coastguard Worker 	LSA_UNICODE_STRING		lucZoneName;
169*48a54d36SAndroid Build Coastguard Worker 	LSA_UNICODE_STRING		lucKeyName;
170*48a54d36SAndroid Build Coastguard Worker 	LSA_UNICODE_STRING		lucSecretName;
171*48a54d36SAndroid Build Coastguard Worker 	BOOL					ok = TRUE;
172*48a54d36SAndroid Build Coastguard Worker 	OSStatus				err;
173*48a54d36SAndroid Build Coastguard Worker 
174*48a54d36SAndroid Build Coastguard Worker 	require_action( inDomain != NULL, exit, ok = FALSE );
175*48a54d36SAndroid Build Coastguard Worker 	require_action( inKey != NULL, exit, ok = FALSE );
176*48a54d36SAndroid Build Coastguard Worker 	require_action( inSecret != NULL, exit, ok = FALSE );
177*48a54d36SAndroid Build Coastguard Worker 
178*48a54d36SAndroid Build Coastguard Worker 	// If there isn't a trailing dot, add one because the mDNSResponder
179*48a54d36SAndroid Build Coastguard Worker 	// presents names with the trailing dot.
180*48a54d36SAndroid Build Coastguard Worker 
181*48a54d36SAndroid Build Coastguard Worker 	ZeroMemory( domain, sizeof( domain ) );
182*48a54d36SAndroid Build Coastguard Worker 	inDomainLength = strlen( inDomain );
183*48a54d36SAndroid Build Coastguard Worker 	require_action( inDomainLength > 0, exit, ok = FALSE );
184*48a54d36SAndroid Build Coastguard Worker 	err = strcpy_s( domain, sizeof( domain ) - 2, inDomain );
185*48a54d36SAndroid Build Coastguard Worker 	require_action( !err, exit, ok = FALSE );
186*48a54d36SAndroid Build Coastguard Worker 
187*48a54d36SAndroid Build Coastguard Worker 	if ( domain[ inDomainLength - 1 ] != '.' )
188*48a54d36SAndroid Build Coastguard Worker 	{
189*48a54d36SAndroid Build Coastguard Worker 		domain[ inDomainLength++ ] = '.';
190*48a54d36SAndroid Build Coastguard Worker 		domain[ inDomainLength ] = '\0';
191*48a54d36SAndroid Build Coastguard Worker 	}
192*48a54d36SAndroid Build Coastguard Worker 
193*48a54d36SAndroid Build Coastguard Worker 	// <rdar://problem/4192119>
194*48a54d36SAndroid Build Coastguard Worker 	//
195*48a54d36SAndroid Build Coastguard Worker 	// Prepend "$" to the key name, so that there will
196*48a54d36SAndroid Build Coastguard Worker 	// be no conflict between the zone name and the key
197*48a54d36SAndroid Build Coastguard Worker 	// name
198*48a54d36SAndroid Build Coastguard Worker 
199*48a54d36SAndroid Build Coastguard Worker 	ZeroMemory( key, sizeof( key ) );
200*48a54d36SAndroid Build Coastguard Worker 	inKeyLength = strlen( inKey );
201*48a54d36SAndroid Build Coastguard Worker 	require_action( inKeyLength > 0 , exit, ok = FALSE );
202*48a54d36SAndroid Build Coastguard Worker 	key[ 0 ] = '$';
203*48a54d36SAndroid Build Coastguard Worker 	err = strcpy_s( key + 1, sizeof( key ) - 3, inKey );
204*48a54d36SAndroid Build Coastguard Worker 	require_action( !err, exit, ok = FALSE );
205*48a54d36SAndroid Build Coastguard Worker 	inKeyLength++;
206*48a54d36SAndroid Build Coastguard Worker 
207*48a54d36SAndroid Build Coastguard Worker 	if ( key[ inKeyLength - 1 ] != '.' )
208*48a54d36SAndroid Build Coastguard Worker 	{
209*48a54d36SAndroid Build Coastguard Worker 		key[ inKeyLength++ ] = '.';
210*48a54d36SAndroid Build Coastguard Worker 		key[ inKeyLength ] = '\0';
211*48a54d36SAndroid Build Coastguard Worker 	}
212*48a54d36SAndroid Build Coastguard Worker 
213*48a54d36SAndroid Build Coastguard Worker 	// attrs are reserved, so initialize to zeroes.
214*48a54d36SAndroid Build Coastguard Worker 
215*48a54d36SAndroid Build Coastguard Worker 	ZeroMemory( &attrs, sizeof( attrs ) );
216*48a54d36SAndroid Build Coastguard Worker 
217*48a54d36SAndroid Build Coastguard Worker 	// Get a handle to the Policy object on the local system
218*48a54d36SAndroid Build Coastguard Worker 
219*48a54d36SAndroid Build Coastguard Worker 	res = LsaOpenPolicy( NULL, &attrs, POLICY_ALL_ACCESS, &handle );
220*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
221*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
222*48a54d36SAndroid Build Coastguard Worker 
223*48a54d36SAndroid Build Coastguard Worker 	// Intializing PLSA_UNICODE_STRING structures
224*48a54d36SAndroid Build Coastguard Worker 
225*48a54d36SAndroid Build Coastguard Worker 	err = MakeLsaStringFromUTF8String( &lucZoneName, domain );
226*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
227*48a54d36SAndroid Build Coastguard Worker 
228*48a54d36SAndroid Build Coastguard Worker 	err = MakeLsaStringFromUTF8String( &lucKeyName, key );
229*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
230*48a54d36SAndroid Build Coastguard Worker 
231*48a54d36SAndroid Build Coastguard Worker 	err = MakeLsaStringFromUTF8String( &lucSecretName, inSecret );
232*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
233*48a54d36SAndroid Build Coastguard Worker 
234*48a54d36SAndroid Build Coastguard Worker 	// Store the private data.
235*48a54d36SAndroid Build Coastguard Worker 
236*48a54d36SAndroid Build Coastguard Worker 	res = LsaStorePrivateData( handle, &lucZoneName, &lucKeyName );
237*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
238*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
239*48a54d36SAndroid Build Coastguard Worker 
240*48a54d36SAndroid Build Coastguard Worker 	res = LsaStorePrivateData( handle, &lucKeyName, &lucSecretName );
241*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( res == 0, LsaNtStatusToWinError( res ), kUnknownErr );
242*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
243*48a54d36SAndroid Build Coastguard Worker 
244*48a54d36SAndroid Build Coastguard Worker exit:
245*48a54d36SAndroid Build Coastguard Worker 
246*48a54d36SAndroid Build Coastguard Worker 	if ( handle )
247*48a54d36SAndroid Build Coastguard Worker 	{
248*48a54d36SAndroid Build Coastguard Worker 		LsaClose( handle );
249*48a54d36SAndroid Build Coastguard Worker 		handle = NULL;
250*48a54d36SAndroid Build Coastguard Worker 	}
251*48a54d36SAndroid Build Coastguard Worker 
252*48a54d36SAndroid Build Coastguard Worker 	return ok;
253*48a54d36SAndroid Build Coastguard Worker }
254*48a54d36SAndroid Build Coastguard Worker 
255*48a54d36SAndroid Build Coastguard Worker 
256*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
257*48a54d36SAndroid Build Coastguard Worker //	MakeLsaStringFromUTF8String
258*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
259*48a54d36SAndroid Build Coastguard Worker 
260*48a54d36SAndroid Build Coastguard Worker mDNSlocal OSStatus
MakeLsaStringFromUTF8String(PLSA_UNICODE_STRING output,const char * input)261*48a54d36SAndroid Build Coastguard Worker MakeLsaStringFromUTF8String( PLSA_UNICODE_STRING output, const char * input )
262*48a54d36SAndroid Build Coastguard Worker {
263*48a54d36SAndroid Build Coastguard Worker 	int			size;
264*48a54d36SAndroid Build Coastguard Worker 	OSStatus	err;
265*48a54d36SAndroid Build Coastguard Worker 
266*48a54d36SAndroid Build Coastguard Worker 	check( input );
267*48a54d36SAndroid Build Coastguard Worker 	check( output );
268*48a54d36SAndroid Build Coastguard Worker 
269*48a54d36SAndroid Build Coastguard Worker 	output->Buffer = NULL;
270*48a54d36SAndroid Build Coastguard Worker 
271*48a54d36SAndroid Build Coastguard Worker 	size = MultiByteToWideChar( CP_UTF8, 0, input, -1, NULL, 0 );
272*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( size > 0, GetLastError(), kUnknownErr );
273*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
274*48a54d36SAndroid Build Coastguard Worker 
275*48a54d36SAndroid Build Coastguard Worker 	output->Length = (USHORT)( size * sizeof( wchar_t ) );
276*48a54d36SAndroid Build Coastguard Worker 	output->Buffer = (PWCHAR) malloc( output->Length );
277*48a54d36SAndroid Build Coastguard Worker 	require_action( output->Buffer, exit, err = mStatus_NoMemoryErr );
278*48a54d36SAndroid Build Coastguard Worker 	size = MultiByteToWideChar( CP_UTF8, 0, input, -1, output->Buffer, size );
279*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( size > 0, GetLastError(), kUnknownErr );
280*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
281*48a54d36SAndroid Build Coastguard Worker 
282*48a54d36SAndroid Build Coastguard Worker 	// We're going to subtrace one wchar_t from the size, because we didn't
283*48a54d36SAndroid Build Coastguard Worker 	// include it when we encoded the string
284*48a54d36SAndroid Build Coastguard Worker 
285*48a54d36SAndroid Build Coastguard Worker 	output->MaximumLength = output->Length;
286*48a54d36SAndroid Build Coastguard Worker 	output->Length		-= sizeof( wchar_t );
287*48a54d36SAndroid Build Coastguard Worker 
288*48a54d36SAndroid Build Coastguard Worker exit:
289*48a54d36SAndroid Build Coastguard Worker 
290*48a54d36SAndroid Build Coastguard Worker 	if ( err && output->Buffer )
291*48a54d36SAndroid Build Coastguard Worker 	{
292*48a54d36SAndroid Build Coastguard Worker 		free( output->Buffer );
293*48a54d36SAndroid Build Coastguard Worker 		output->Buffer = NULL;
294*48a54d36SAndroid Build Coastguard Worker 	}
295*48a54d36SAndroid Build Coastguard Worker 
296*48a54d36SAndroid Build Coastguard Worker 	return( err );
297*48a54d36SAndroid Build Coastguard Worker }
298*48a54d36SAndroid Build Coastguard Worker 
299*48a54d36SAndroid Build Coastguard Worker 
300*48a54d36SAndroid Build Coastguard Worker 
301*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
302*48a54d36SAndroid Build Coastguard Worker //	MakeUTF8StringFromLsaString
303*48a54d36SAndroid Build Coastguard Worker //===========================================================================================================================
304*48a54d36SAndroid Build Coastguard Worker 
305*48a54d36SAndroid Build Coastguard Worker mDNSlocal OSStatus
MakeUTF8StringFromLsaString(char * output,size_t len,PLSA_UNICODE_STRING input)306*48a54d36SAndroid Build Coastguard Worker MakeUTF8StringFromLsaString( char * output, size_t len, PLSA_UNICODE_STRING input )
307*48a54d36SAndroid Build Coastguard Worker {
308*48a54d36SAndroid Build Coastguard Worker 	size_t		size;
309*48a54d36SAndroid Build Coastguard Worker 	OSStatus	err = kNoErr;
310*48a54d36SAndroid Build Coastguard Worker 
311*48a54d36SAndroid Build Coastguard Worker 	// The Length field of this structure holds the number of bytes,
312*48a54d36SAndroid Build Coastguard Worker 	// but WideCharToMultiByte expects the number of wchar_t's. So
313*48a54d36SAndroid Build Coastguard Worker 	// we divide by sizeof(wchar_t) to get the correct number.
314*48a54d36SAndroid Build Coastguard Worker 
315*48a54d36SAndroid Build Coastguard Worker 	size = (size_t) WideCharToMultiByte(CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), NULL, 0, NULL, NULL);
316*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( size != 0, GetLastError(), kUnknownErr );
317*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
318*48a54d36SAndroid Build Coastguard Worker 
319*48a54d36SAndroid Build Coastguard Worker 	// Ensure that we have enough space (Add one for trailing '\0')
320*48a54d36SAndroid Build Coastguard Worker 
321*48a54d36SAndroid Build Coastguard Worker 	require_action( ( size + 1 ) <= len, exit, err = mStatus_NoMemoryErr );
322*48a54d36SAndroid Build Coastguard Worker 
323*48a54d36SAndroid Build Coastguard Worker 	// Convert the string
324*48a54d36SAndroid Build Coastguard Worker 
325*48a54d36SAndroid Build Coastguard Worker 	size = (size_t) WideCharToMultiByte( CP_UTF8, 0, input->Buffer, ( input->Length / sizeof( wchar_t ) ), output, (int) size, NULL, NULL);
326*48a54d36SAndroid Build Coastguard Worker 	err = translate_errno( size != 0, GetLastError(), kUnknownErr );
327*48a54d36SAndroid Build Coastguard Worker 	require_noerr( err, exit );
328*48a54d36SAndroid Build Coastguard Worker 
329*48a54d36SAndroid Build Coastguard Worker 	// have to add the trailing 0 because WideCharToMultiByte doesn't do it,
330*48a54d36SAndroid Build Coastguard Worker 	// although it does return the correct size
331*48a54d36SAndroid Build Coastguard Worker 
332*48a54d36SAndroid Build Coastguard Worker 	output[size] = '\0';
333*48a54d36SAndroid Build Coastguard Worker 
334*48a54d36SAndroid Build Coastguard Worker exit:
335*48a54d36SAndroid Build Coastguard Worker 
336*48a54d36SAndroid Build Coastguard Worker 	return err;
337*48a54d36SAndroid Build Coastguard Worker }
338*48a54d36SAndroid Build Coastguard Worker 
339