• Home
  • History
  • Annotate
  • Line#
  • Navigate
  • Raw
  • Download
  • only in /asuswrt-rt-n18u-9.0.0.4.380.2695/release/src-rt-6.x.4708/router/samba-3.0.25b/source/libmsrpc/
1
2/*
3 *  Unix SMB/CIFS implementation.
4 *  MS-RPC client internal functions
5 *  Copyright (C) Chris Nicholls              2005.
6 *
7 *  This program is free software; you can redistribute it and/or modify
8 *  it under the terms of the GNU General Public License as published by
9 *  the Free Software Foundation; either version 2 of the License, or
10 *  (at your option) any later version.
11 *
12 *  This program 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
15 *  GNU General Public License for more details.
16 *
17 *  You should have received a copy of the GNU General Public License
18 *  along with this program; if not, write to the Free Software
19 *  Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
20 */
21
22
23#include "libmsrpc.h"
24#include "libmsrpc_internal.h"
25
26char *cac_unistr_to_str( TALLOC_CTX * mem_ctx, uint16 * src, int num_bytes );
27char *talloc_unistr2_to_ascii( TALLOC_CTX * mem_ctx, UNISTR2 str );
28char *cac_unistr_ascii( TALLOC_CTX * mem_ctx, UNISTR src );
29
30/*used to get a struct rpc_pipe_client* to be passed into rpccli* calls*/
31struct rpc_pipe_client *cac_GetPipe( CacServerHandle * hnd, int pi_idx )
32{
33	SMBCSRV *srv = NULL;
34	struct rpc_pipe_client *pipe_hnd = NULL;
35
36	if ( !hnd ) {
37		return NULL;
38	}
39
40	if ( hnd->_internal.pipes[pi_idx] == False ) {
41		hnd->status = NT_STATUS_INVALID_HANDLE;
42		return NULL;
43	}
44
45	srv = cac_GetServer( hnd );
46	if ( !srv ) {
47		hnd->status = NT_STATUS_INVALID_CONNECTION;
48		return NULL;
49	}
50
51	pipe_hnd = srv->cli->pipe_list;
52
53	while ( pipe_hnd != NULL && pipe_hnd->pipe_idx != pi_idx ) {
54		pipe_hnd = pipe_hnd->next;
55	}
56
57	return pipe_hnd;
58}
59
60/*takes a string like HKEY_LOCAL_MACHINE\HARDWARE\ACPI and returns the reg_type code and then a pointer to the start of the path (HARDWARE)*/
61int cac_ParseRegPath( char *path, uint32 * reg_type, char **key_name )
62{
63
64	if ( !path )
65		return CAC_FAILURE;
66
67	if ( strncmp( path, "HKLM", 4 ) == 0 ) {
68		*reg_type = HKEY_LOCAL_MACHINE;
69		*key_name = ( path[4] == '\\' ) ? path + 5 : NULL;
70	} else if ( strncmp( path, "HKEY_LOCAL_MACHINE", 18 ) == 0 ) {
71		*reg_type = HKEY_LOCAL_MACHINE;
72		*key_name = ( path[18] == '\\' ) ? path + 19 : NULL;
73	} else if ( strncmp( path, "HKCR", 4 ) == 0 ) {
74		*reg_type = HKEY_CLASSES_ROOT;
75		*key_name = ( path[4] == '\\' ) ? path + 5 : NULL;
76	} else if ( strncmp( path, "HKEY_CLASSES_ROOT", 17 ) == 0 ) {
77		*reg_type = HKEY_CLASSES_ROOT;
78		*key_name = ( path[17] == '\\' ) ? path + 18 : NULL;
79	} else if ( strncmp( path, "HKU", 3 ) == 0 ) {
80		*reg_type = HKEY_USERS;
81		*key_name = ( path[3] == '\\' ) ? path + 4 : NULL;
82	} else if ( strncmp( path, "HKEY_USERS", 10 ) == 0 ) {
83		*reg_type = HKEY_USERS;
84		*key_name = ( path[10] == '\\' ) ? path + 11 : NULL;
85	} else if ( strncmp( path, "HKPD", 4 ) == 0 ) {
86		*reg_type = HKEY_PERFORMANCE_DATA;
87		*key_name = ( path[4] == '\\' ) ? path + 5 : NULL;
88	} else if ( strncmp( path, "HKEY_PERFORMANCE_DATA", 21 ) == 0 ) {
89		*reg_type = HKEY_PERFORMANCE_DATA;
90		*key_name = ( path[21] == '\\' ) ? path + 22 : NULL;
91	} else {
92		return CAC_FAILURE;
93	}
94
95	return CAC_SUCCESS;
96}
97
98
99
100RPC_DATA_BLOB *cac_MakeRpcDataBlob( TALLOC_CTX * mem_ctx, uint32 data_type,
101				    REG_VALUE_DATA data )
102{
103	RPC_DATA_BLOB *blob = NULL;
104	int i;
105	uint32 size = 0;
106	uint8 *multi = NULL;
107	uint32 multi_idx = 0;
108
109	blob = talloc( mem_ctx, RPC_DATA_BLOB );
110
111	if ( !blob ) {
112		errno = ENOMEM;
113		return NULL;
114	}
115
116	switch ( data_type ) {
117	case REG_SZ:
118		init_rpc_blob_str( blob, data.reg_sz,
119				   strlen( data.reg_sz ) + 1 );
120		break;
121
122	case REG_EXPAND_SZ:
123		init_rpc_blob_str( blob, data.reg_expand_sz,
124				   strlen( data.reg_sz ) + 1 );
125		break;
126
127	case REG_BINARY:
128		init_rpc_blob_bytes( blob, data.reg_binary.data,
129				     data.reg_binary.data_length );
130		break;
131
132	case REG_DWORD:
133		init_rpc_blob_uint32( blob, data.reg_dword );
134		break;
135
136	case REG_DWORD_BE:
137		init_rpc_blob_uint32( blob, data.reg_dword_be );
138		break;
139
140	case REG_MULTI_SZ:
141		/*need to find the size */
142		for ( i = 0; i < data.reg_multi_sz.num_strings; i++ ) {
143			size += strlen( data.reg_multi_sz.strings[i] ) + 1;
144		}
145
146	 /**need a whole bunch of unicode strings in a row (seperated by null characters), with an extra null-character on the end*/
147
148		multi = TALLOC_ZERO_ARRAY( mem_ctx, uint8, ( size + 1 ) * 2 );	/*size +1 for the extra null character */
149		if ( !multi ) {
150			errno = ENOMEM;
151			break;
152		}
153
154		/*do it using rpcstr_push() */
155		multi_idx = 0;
156		for ( i = 0; i < data.reg_multi_sz.num_strings; i++ ) {
157			size_t len =
158				strlen( data.reg_multi_sz.strings[i] ) + 1;
159
160			rpcstr_push( ( multi + multi_idx ),
161				     data.reg_multi_sz.strings[i], len * 2,
162				     STR_TERMINATE );
163
164			/* x2 becuase it is a uint8 buffer */
165			multi_idx += len * 2;
166		}
167
168		/*now initialize the buffer as binary data */
169		init_rpc_blob_bytes( blob, multi, ( size + 1 ) * 2 );
170
171		break;
172
173	default:
174		TALLOC_FREE( blob );
175		blob = NULL;
176		return NULL;
177	}
178
179	if ( !( blob->buffer ) ) {
180		TALLOC_FREE( blob );
181		return NULL;
182	}
183
184	return blob;
185}
186
187/*turns a string in a uint16 array to a char array*/
188char *cac_unistr_to_str( TALLOC_CTX * mem_ctx, uint16 * src, int num_bytes )
189{
190	char *buf;
191
192	int i = 0;
193
194	uint32 str_len = 0;
195
196	/*don't allocate more space than we need */
197	while ( ( str_len ) < num_bytes / 2 && src[str_len] != 0x0000 )
198		str_len++;
199
200	/*need room for a '\0' */
201	str_len++;
202
203	buf = TALLOC_ARRAY( mem_ctx, char, str_len );
204
205	if ( !buf ) {
206		return NULL;
207	}
208
209	for ( i = 0; i < num_bytes / 2; i++ ) {
210		buf[i] = ( ( char * ) src )[2 * i];
211	}
212
213	buf[str_len - 1] = '\0';
214
215	return buf;
216}
217
218REG_VALUE_DATA *cac_MakeRegValueData( TALLOC_CTX * mem_ctx, uint32 data_type,
219				      REGVAL_BUFFER buf )
220{
221	REG_VALUE_DATA *data;
222
223	uint32 i;
224
225	/*all of the following used for MULTI_SZ data */
226	uint32 size = 0;
227	uint32 len = 0;
228	uint32 multi_idx = 0;
229	uint32 num_strings = 0;
230	char **strings = NULL;
231
232	data = talloc( mem_ctx, REG_VALUE_DATA );
233	if ( !data ) {
234		errno = ENOMEM;
235		return NULL;
236	}
237
238	switch ( data_type ) {
239	case REG_SZ:
240		data->reg_sz =
241			cac_unistr_to_str( mem_ctx, buf.buffer, buf.buf_len );
242		if ( !data->reg_sz ) {
243			TALLOC_FREE( data );
244			errno = ENOMEM;
245			data = NULL;
246		}
247
248		break;
249
250	case REG_EXPAND_SZ:
251		data->reg_expand_sz =
252			cac_unistr_to_str( mem_ctx, buf.buffer, buf.buf_len );
253
254		if ( !data->reg_expand_sz ) {
255			TALLOC_FREE( data );
256			errno = ENOMEM;
257			data = NULL;
258		}
259
260		break;
261
262	case REG_BINARY:
263		size = buf.buf_len;
264
265		data->reg_binary.data_length = size;
266
267		if (size) {
268			data->reg_binary.data =
269				( uint8 * ) TALLOC_MEMDUP( mem_ctx, buf.buffer, size );
270			if ( !data->reg_binary.data ) {
271				TALLOC_FREE( data );
272				errno = ENOMEM;
273				data = NULL;
274			}
275		} else {
276			data->reg_binary.data = NULL;
277		}
278		break;
279
280	case REG_DWORD:
281		data->reg_dword = *( ( uint32 * ) buf.buffer );
282		break;
283
284	case REG_DWORD_BE:
285		data->reg_dword_be = *( ( uint32 * ) buf.buffer );
286		break;
287
288	case REG_MULTI_SZ:
289		size = buf.buf_len;
290
291		/*find out how many strings there are. size is # of bytes and we want to work uint16 */
292		for ( i = 0; i < ( size / 2 - 1 ); i++ ) {
293			if ( buf.buffer[i] == 0x0000 )
294				num_strings++;
295
296			/*buffer is suppsed to be terminated with \0\0, but it might not be */
297			if ( buf.buffer[i] == 0x0000
298			     && buf.buffer[i + 1] == 0x0000 )
299				break;
300		}
301
302		if (num_strings) {
303			strings = TALLOC_ARRAY( mem_ctx, char *, num_strings );
304
305			if ( !strings ) {
306				errno = ENOMEM;
307				TALLOC_FREE( data );
308				break;
309			}
310		} else {
311			strings = NULL;
312		}
313
314		if ( num_strings == 0 )	/*then our work here is done */
315			break;
316
317		for ( i = 0; i < num_strings; i++ ) {
318			/*find out how many characters are in this string */
319			len = 0;
320			/*make sure we don't go past the end of the buffer and keep looping until we have a uni \0 */
321			while ( multi_idx + len < size / 2
322				&& buf.buffer[multi_idx + len] != 0x0000 )
323				len++;
324
325			/*stay aware of the \0\0 */
326			len++;
327
328			strings[i] = TALLOC_ZERO_ARRAY( mem_ctx, char, len );
329
330			/*pull out the unicode string */
331			rpcstr_pull( strings[i], ( buf.buffer + multi_idx ),
332				     len, -1, STR_TERMINATE );
333
334			/*keep track of where we are in the bigger array */
335			multi_idx += len;
336		}
337
338		data->reg_multi_sz.num_strings = num_strings;
339		data->reg_multi_sz.strings = strings;
340
341		break;
342
343	default:
344		TALLOC_FREE( data );
345		data = NULL;
346	}
347
348	return data;
349}
350
351SAM_USERINFO_CTR *cac_MakeUserInfoCtr( TALLOC_CTX * mem_ctx,
352				       CacUserInfo * info )
353{
354	SAM_USERINFO_CTR *ctr = NULL;
355
356	/*the flags we are 'setting'- include/passdb.h */
357	uint32 flags =
358		ACCT_USERNAME | ACCT_FULL_NAME | ACCT_PRIMARY_GID |
359		ACCT_DESCRIPTION | ACCT_COMMENT | ACCT_HOME_DIR |
360		ACCT_HOME_DRIVE | ACCT_LOGON_SCRIPT | ACCT_PROFILE |
361		ACCT_WORKSTATIONS | ACCT_FLAGS;
362
363	NTTIME logon_time;
364	NTTIME logoff_time;
365	NTTIME kickoff_time;
366	NTTIME pass_last_set_time;
367	NTTIME pass_can_change_time;
368	NTTIME pass_must_change_time;
369
370	UNISTR2 user_name;
371	UNISTR2 full_name;
372	UNISTR2 home_dir;
373	UNISTR2 dir_drive;
374	UNISTR2 log_scr;
375	UNISTR2 prof_path;
376	UNISTR2 desc;
377	UNISTR2 wkstas;
378	UNISTR2 mung_dial;
379	UNISTR2 unk;
380
381	ctr = talloc( mem_ctx, SAM_USERINFO_CTR );
382	if ( !ctr )
383		return NULL;
384
385	ZERO_STRUCTP( ctr->info.id23 );
386
387	ctr->info.id21 = talloc( mem_ctx, SAM_USER_INFO_21 );
388	if ( !ctr->info.id21 )
389		return NULL;
390
391	ctr->switch_value = 21;
392
393	ZERO_STRUCTP( ctr->info.id21 );
394
395	unix_to_nt_time( &logon_time, info->logon_time );
396	unix_to_nt_time( &logoff_time, info->logoff_time );
397	unix_to_nt_time( &kickoff_time, info->kickoff_time );
398	unix_to_nt_time( &pass_last_set_time, info->pass_last_set_time );
399	unix_to_nt_time( &pass_can_change_time, info->pass_can_change_time );
400	unix_to_nt_time( &pass_must_change_time,
401			 info->pass_must_change_time );
402
403	/*initialize the strings */
404	init_unistr2( &user_name, info->username, UNI_STR_TERMINATE );
405	init_unistr2( &full_name, info->full_name, UNI_STR_TERMINATE );
406	init_unistr2( &home_dir, info->home_dir, UNI_STR_TERMINATE );
407	init_unistr2( &dir_drive, info->home_drive, UNI_STR_TERMINATE );
408	init_unistr2( &log_scr, info->logon_script, UNI_STR_TERMINATE );
409	init_unistr2( &prof_path, info->profile_path, UNI_STR_TERMINATE );
410	init_unistr2( &desc, info->description, UNI_STR_TERMINATE );
411	init_unistr2( &wkstas, info->workstations, UNI_STR_TERMINATE );
412	init_unistr2( &unk, "\0", UNI_STR_TERMINATE );
413	init_unistr2( &mung_dial, info->dial, UNI_STR_TERMINATE );
414
415	/*manually set passmustchange */
416	ctr->info.id21->passmustchange =
417		( info->pass_must_change ) ? 0x01 : 0x00;
418
419	init_sam_user_info21W( ctr->info.id21, &logon_time, &logoff_time, &kickoff_time, &pass_last_set_time, &pass_can_change_time, &pass_must_change_time, &user_name, &full_name, &home_dir, &dir_drive, &log_scr, &prof_path, &desc, &wkstas, &unk, &mung_dial, info->lm_password, info->nt_password, info->rid, info->group_rid, info->acb_mask, flags, 168,	/*logon divs */
420			       info->logon_hours,
421			       info->bad_passwd_count, info->logon_count );
422
423	return ctr;
424
425}
426
427char *talloc_unistr2_to_ascii( TALLOC_CTX * mem_ctx, UNISTR2 str )
428{
429	char *buf = NULL;
430
431	if ( !mem_ctx )
432		return NULL;
433
434	buf = TALLOC_ARRAY( mem_ctx, char, ( str.uni_str_len + 1 ) );
435	if ( !buf )
436		return NULL;
437
438	unistr2_to_ascii( buf, &str, str.uni_str_len + 1 );
439
440	return buf;
441}
442
443CacUserInfo *cac_MakeUserInfo( TALLOC_CTX * mem_ctx, SAM_USERINFO_CTR * ctr )
444{
445	CacUserInfo *info = NULL;
446	SAM_USER_INFO_21 *id21 = NULL;
447
448	if ( !ctr || ctr->switch_value != 21 )
449		return NULL;
450
451	info = talloc( mem_ctx, CacUserInfo );
452	if ( !info )
453		return NULL;
454
455	id21 = ctr->info.id21;
456
457	ZERO_STRUCTP( info );
458
459	info->logon_time = nt_time_to_unix( id21->logon_time );
460	info->logoff_time = nt_time_to_unix( id21->logoff_time );
461	info->kickoff_time = nt_time_to_unix( id21->kickoff_time );
462	info->pass_last_set_time =
463		nt_time_to_unix( id21->pass_last_set_time );
464	info->pass_can_change_time =
465		nt_time_to_unix( id21->pass_can_change_time );
466	info->pass_must_change_time =
467		nt_time_to_unix( id21->pass_must_change_time );
468
469	info->username =
470		talloc_unistr2_to_ascii( mem_ctx, id21->uni_user_name );
471	if ( !info->username )
472		return NULL;
473
474	info->full_name =
475		talloc_unistr2_to_ascii( mem_ctx, id21->uni_full_name );
476	if ( !info->full_name )
477		return NULL;
478
479	info->home_dir =
480		talloc_unistr2_to_ascii( mem_ctx, id21->uni_home_dir );
481	if ( !info->home_dir )
482		return NULL;
483
484	info->home_drive =
485		talloc_unistr2_to_ascii( mem_ctx, id21->uni_dir_drive );
486	if ( !info->home_drive )
487		return NULL;
488
489	info->logon_script =
490		talloc_unistr2_to_ascii( mem_ctx, id21->uni_logon_script );
491	if ( !info->logon_script )
492		return NULL;
493
494	info->profile_path =
495		talloc_unistr2_to_ascii( mem_ctx, id21->uni_profile_path );
496	if ( !info->profile_path )
497		return NULL;
498
499	info->description =
500		talloc_unistr2_to_ascii( mem_ctx, id21->uni_acct_desc );
501	if ( !info->description )
502		return NULL;
503
504	info->workstations =
505		talloc_unistr2_to_ascii( mem_ctx, id21->uni_workstations );
506	if ( !info->workstations )
507		return NULL;
508
509	info->dial =
510		talloc_unistr2_to_ascii( mem_ctx, id21->uni_munged_dial );
511	if ( !info->dial )
512		return NULL;
513
514	info->rid = id21->user_rid;
515	info->group_rid = id21->group_rid;
516	info->acb_mask = id21->acb_info;
517	info->bad_passwd_count = id21->bad_password_count;
518	info->logon_count = id21->logon_count;
519
520	memcpy( info->nt_password, id21->nt_pwd, 8 );
521	memcpy( info->lm_password, id21->lm_pwd, 8 );
522
523	info->logon_hours =
524		( LOGON_HRS * ) TALLOC_MEMDUP( mem_ctx, &( id21->logon_hrs ),
525					       sizeof( LOGON_HRS ) );
526	if ( !info->logon_hours )
527		return NULL;
528
529	info->pass_must_change = ( id21->passmustchange ) ? True : False;
530
531	return info;
532}
533
534CacGroupInfo *cac_MakeGroupInfo( TALLOC_CTX * mem_ctx, GROUP_INFO_CTR * ctr )
535{
536	CacGroupInfo *info = NULL;
537
538	if ( !mem_ctx || !ctr || ctr->switch_value1 != 1 )
539		return NULL;
540
541	info = talloc( mem_ctx, CacGroupInfo );
542	if ( !info )
543		return NULL;
544
545	info->name =
546		talloc_unistr2_to_ascii( mem_ctx,
547					 ctr->group.info1.uni_acct_name );
548	if ( !info->name )
549		return NULL;
550
551	info->description =
552		talloc_unistr2_to_ascii( mem_ctx,
553					 ctr->group.info1.uni_acct_desc );
554	if ( !info->description )
555		return NULL;
556
557	info->num_members = ctr->group.info1.num_members;
558
559	return info;
560}
561
562GROUP_INFO_CTR *cac_MakeGroupInfoCtr( TALLOC_CTX * mem_ctx,
563				      CacGroupInfo * info )
564{
565	GROUP_INFO_CTR *ctr = NULL;
566
567	if ( !mem_ctx || !info )
568		return NULL;
569
570	ctr = talloc( mem_ctx, GROUP_INFO_CTR );
571	if ( !ctr )
572		return NULL;
573
574	ctr->switch_value1 = 1;
575
576	init_samr_group_info1( &( ctr->group.info1 ), info->name,
577			       info->description, info->num_members );
578
579	return ctr;
580}
581
582CacAliasInfo *cac_MakeAliasInfo( TALLOC_CTX * mem_ctx, ALIAS_INFO_CTR ctr )
583{
584	CacGroupInfo *info = NULL;
585
586	if ( !mem_ctx || ctr.level != 1 )
587		return NULL;
588
589	info = talloc( mem_ctx, CacAliasInfo );
590	if ( !info )
591		return NULL;
592
593	info->name =
594		talloc_unistr2_to_ascii( mem_ctx,
595					 *( ctr.alias.info1.name.string ) );
596	if ( !info->name )
597		return NULL;
598
599	info->description =
600		talloc_unistr2_to_ascii( mem_ctx,
601					 *( ctr.alias.info1.description.
602					    string ) );
603	if ( !info->name )
604		return NULL;
605
606	info->num_members = ctr.alias.info1.num_member;
607
608	return info;
609}
610
611ALIAS_INFO_CTR *cac_MakeAliasInfoCtr( TALLOC_CTX * mem_ctx,
612				      CacAliasInfo * info )
613{
614	ALIAS_INFO_CTR *ctr = NULL;
615
616	if ( !mem_ctx || !info )
617		return NULL;
618
619	ctr = talloc( mem_ctx, ALIAS_INFO_CTR );
620	if ( !ctr )
621		return NULL;
622
623	ctr->level = 1;
624
625	init_samr_alias_info1( &( ctr->alias.info1 ), info->name,
626			       info->num_members, info->description );
627
628	return ctr;
629}
630
631CacDomainInfo *cac_MakeDomainInfo( TALLOC_CTX * mem_ctx,
632				   SAM_UNK_INFO_1 * info1,
633				   SAM_UNK_INFO_2 * info2,
634				   SAM_UNK_INFO_12 * info12 )
635{
636	CacDomainInfo *info = NULL;
637
638	if ( !mem_ctx || !info1 || !info2 || !info12 )
639		return NULL;
640
641	info = talloc( mem_ctx, CacDomainInfo );
642	if ( !info )
643		return NULL;
644
645	info->min_pass_length = info1->min_length_password;
646	info->pass_history = info1->password_history;
647
648	cac_InitCacTime( &( info->expire ), info1->expire );
649	cac_InitCacTime( &( info->min_pass_age ), info1->min_passwordage );
650
651	info->server_role = info2->server_role;
652	info->num_users = info2->num_domain_usrs;
653	info->num_domain_groups = info2->num_domain_grps;
654	info->num_local_groups = info2->num_local_grps;
655
656	/*if these have been ZERO'd out we need to know. uni_str_len will be 0 */
657	if ( info2->uni_comment.uni_str_len == 0 ) {
658		info->comment = talloc_strdup( mem_ctx, "\0" );
659	} else {
660		info->comment =
661			talloc_unistr2_to_ascii( mem_ctx,
662						 info2->uni_comment );
663	}
664
665	if ( info2->uni_domain.uni_str_len == 0 ) {
666		info->domain_name = talloc_strdup( mem_ctx, "\0" );
667	} else {
668		info->domain_name =
669			talloc_unistr2_to_ascii( mem_ctx, info2->uni_domain );
670	}
671
672	if ( info2->uni_server.uni_str_len == 0 ) {
673		info->server_name = talloc_strdup( mem_ctx, "\0" );
674	} else {
675		info->server_name =
676			talloc_unistr2_to_ascii( mem_ctx, info2->uni_server );
677	}
678
679
680	cac_InitCacTime( &( info->lockout_duration ), info12->duration );
681	cac_InitCacTime( &( info->lockout_reset ), info12->reset_count );
682	info->num_bad_attempts = info12->bad_attempt_lockout;
683
684	return info;
685}
686
687char *cac_unistr_ascii( TALLOC_CTX * mem_ctx, UNISTR src )
688{
689	char *buf;
690	uint32 len;
691
692	if ( !mem_ctx || !src.buffer )
693		return NULL;
694
695	len = unistrlen( src.buffer ) + 1;
696
697	buf = TALLOC_ZERO_ARRAY( mem_ctx, char, len );
698	if ( !buf )
699		return NULL;
700
701	rpcstr_pull( buf, src.buffer, len, -1, STR_TERMINATE );
702
703	return buf;
704}
705
706CacService *cac_MakeServiceArray( TALLOC_CTX * mem_ctx,
707				  ENUM_SERVICES_STATUS * svc,
708				  uint32 num_services )
709{
710	int i;
711	CacService *services = NULL;
712
713	if ( !mem_ctx || !svc )
714		return NULL;
715
716	if (num_services) {
717		services = TALLOC_ZERO_ARRAY( mem_ctx, CacService, num_services );
718		if ( !services )
719			return NULL;
720	} else {
721		services = NULL;
722	}
723
724	for ( i = 0; i < num_services; i++ ) {
725		services[i].service_name =
726			cac_unistr_ascii( mem_ctx, svc[i].servicename );
727		services[i].display_name =
728			cac_unistr_ascii( mem_ctx, svc[i].displayname );
729
730		if ( !services[i].service_name || !services[i].display_name )
731			return NULL;
732
733		services[i].status = svc[i].status;
734	}
735
736	return services;
737}
738
739int cac_InitCacServiceConfig( TALLOC_CTX * mem_ctx, SERVICE_CONFIG * src,
740			      CacServiceConfig * dest )
741{
742	if ( !src || !dest )
743		return CAC_FAILURE;
744
745	dest->exe_path =
746		talloc_unistr2_to_ascii( mem_ctx, *src->executablepath );
747	if ( !dest->exe_path )
748		return CAC_FAILURE;
749
750	dest->load_order_group =
751		talloc_unistr2_to_ascii( mem_ctx, *src->loadordergroup );
752	if ( !dest->load_order_group )
753		return CAC_FAILURE;
754
755	dest->dependencies =
756		talloc_unistr2_to_ascii( mem_ctx, *src->dependencies );
757	if ( !dest->dependencies )
758		return CAC_FAILURE;
759
760	dest->start_name =
761		talloc_unistr2_to_ascii( mem_ctx, *src->startname );
762	if ( !dest->start_name )
763		return CAC_FAILURE;
764
765	dest->display_name =
766		talloc_unistr2_to_ascii( mem_ctx, *src->displayname );
767	if ( !dest->display_name )
768		return CAC_FAILURE;
769
770	dest->type = src->service_type;
771	dest->start_type = src->start_type;
772	dest->error_control = src->error_control;
773	dest->tag_id = src->tag_id;
774
775	return CAC_SUCCESS;
776}
777