1
2/*
3 *  Unix SMB/CIFS implementation.
4 *  MS-RPC client library implementation
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#include "libmsrpc.h"
23#include "libmsrpc_internal.h"
24#include "libsmbclient.h"
25#include "libsmb_internal.h"
26
27int cac_InitHandleData( CacServerHandle * hnd );
28
29/*this function is based on code found in smbc_init_context() (libsmb/libsmbclient.c)*/
30void cac_Init( int debug )
31{
32	if ( debug < 0 || debug > 99 )
33		debug = 0;
34
35	DEBUGLEVEL = debug;
36
37	setup_logging( "libmsrpc", True );
38}
39
40int cac_InitHandleMem( CacServerHandle * hnd )
41{
42	hnd->username = SMB_MALLOC_ARRAY( char, sizeof( fstring ) );
43
44	if ( !hnd->username )
45		return CAC_FAILURE;
46
47	hnd->username[0] = '\0';
48
49	hnd->domain = SMB_MALLOC_ARRAY( char, sizeof( fstring ) );
50	if ( !hnd->domain )
51		return CAC_FAILURE;
52
53	hnd->domain[0] = '\0';
54
55	hnd->netbios_name = SMB_MALLOC_ARRAY( char, sizeof( fstring ) );
56	if ( !hnd->netbios_name )
57		return CAC_FAILURE;
58
59	hnd->netbios_name[0] = '\0';
60
61	hnd->password = SMB_MALLOC_ARRAY( char, sizeof( fstring ) );
62	if ( !hnd->password )
63		return CAC_FAILURE;
64
65	hnd->password[0] = '\0';
66
67	hnd->server = SMB_MALLOC_ARRAY( char, sizeof( fstring ) );
68	if ( !hnd->server )
69		return CAC_FAILURE;
70
71	hnd->server[0] = '\0';
72
73	return CAC_SUCCESS;
74}
75
76CacServerHandle *cac_NewServerHandle( BOOL allocate_fields )
77{
78	CacServerHandle *hnd;
79
80	hnd = SMB_MALLOC_P( CacServerHandle );
81
82	if ( !hnd ) {
83		errno = ENOMEM;
84		return NULL;
85	}
86
87	ZERO_STRUCTP( hnd );
88
89	if ( allocate_fields == True ) {
90		if ( !cac_InitHandleMem( hnd ) ) {
91			SAFE_FREE( hnd );
92			return NULL;
93		}
94	}
95
96	hnd->_internal.ctx = smbc_new_context(  );
97	if ( !hnd->_internal.ctx ) {
98		cac_FreeHandle( hnd );
99		return NULL;
100	}
101
102	hnd->_internal.ctx->callbacks.auth_fn = cac_GetAuthDataFn;
103
104	/*add defaults */
105	hnd->debug = 0;
106
107	/*start at the highest and it will fall down after trying the functions */
108	hnd->_internal.srv_level = SRV_WIN_2K3;
109
110	hnd->_internal.user_supplied_ctx = False;
111
112	return hnd;
113}
114
115int cac_InitHandleData( CacServerHandle * hnd )
116{
117	/*store any automatically initialized values */
118	if ( !hnd->netbios_name ) {
119		hnd->netbios_name =
120			SMB_STRDUP( hnd->_internal.ctx->netbios_name );
121	} else if ( hnd->netbios_name[0] == '\0' ) {
122		strncpy( hnd->netbios_name, hnd->_internal.ctx->netbios_name,
123			 sizeof( fstring ) );
124	}
125
126	if ( !hnd->username ) {
127		hnd->username = SMB_STRDUP( hnd->_internal.ctx->user );
128	} else if ( hnd->username[0] == '\0' ) {
129		strncpy( hnd->username, hnd->_internal.ctx->user,
130			 sizeof( fstring ) );
131	}
132
133	if ( !hnd->domain ) {
134		hnd->domain = SMB_STRDUP( hnd->_internal.ctx->workgroup );
135	} else if ( hnd->domain[0] == '\0' ) {
136		strncpy( hnd->domain, hnd->_internal.ctx->workgroup,
137			 sizeof( fstring ) );
138	}
139
140	return CAC_SUCCESS;
141}
142
143void cac_SetAuthDataFn( CacServerHandle * hnd, smbc_get_auth_data_fn auth_fn )
144{
145	hnd->_internal.ctx->callbacks.auth_fn = auth_fn;
146}
147
148void cac_SetSmbcContext( CacServerHandle * hnd, SMBCCTX * ctx )
149{
150
151	SAFE_FREE( hnd->_internal.ctx );
152
153	hnd->_internal.user_supplied_ctx = True;
154
155	hnd->_internal.ctx = ctx;
156
157   /*_try_ to avoid any problems that might occur if cac_Connect() isn't called*/
158	/*cac_InitHandleData(hnd); */
159}
160
161/*used internally*/
162SMBCSRV *cac_GetServer( CacServerHandle * hnd )
163{
164	SMBCSRV *srv;
165
166	if ( !hnd || !hnd->_internal.ctx ) {
167		return NULL;
168	}
169
170	srv = smbc_attr_server( hnd->_internal.ctx, hnd->server, "IPC$",
171				hnd->domain, hnd->username, hnd->password,
172				NULL );
173	if ( !srv ) {
174		hnd->status = NT_STATUS_UNSUCCESSFUL;
175		DEBUG( 1,
176		       ( "cac_GetServer: Could not find server connection.\n" ) );
177	}
178
179	return srv;
180}
181
182
183int cac_Connect( CacServerHandle * hnd, const char *srv )
184{
185	if ( !hnd ) {
186		return CAC_FAILURE;
187	}
188
189	/*these values should be initialized by the user */
190	if ( !hnd->server && !srv ) {
191		return CAC_FAILURE;
192	}
193
194
195	/*change the server name in the server handle if necessary */
196	if ( srv && hnd->server && strcmp( hnd->server, srv ) == 0 ) {
197		SAFE_FREE( hnd->server );
198		hnd->server = SMB_STRDUP( srv );
199	}
200
201
202	/*first see if the context has already been setup */
203	if ( !( hnd->_internal.ctx->internal->_initialized ) ) {
204		hnd->_internal.ctx->debug = hnd->debug;
205
206		/*initialize the context */
207		if ( !smbc_init_context( hnd->_internal.ctx ) ) {
208			return CAC_FAILURE;
209		}
210	}
211
212	/*copy any uninitialized values out of the smbc context into the handle */
213	if ( !cac_InitHandleData( hnd ) ) {
214		return CAC_FAILURE;
215	}
216
217	DEBUG( 3, ( "cac_Connect: Username:     %s\n", hnd->username ) );
218	DEBUG( 3, ( "cac_Connect: Domain:       %s\n", hnd->domain ) );
219	DEBUG( 3, ( "cac_Connect: Netbios Name: %s\n", hnd->netbios_name ) );
220
221	if ( !cac_GetServer( hnd ) ) {
222		return CAC_FAILURE;
223	}
224
225	return CAC_SUCCESS;
226
227}
228
229
230void cac_FreeHandle( CacServerHandle * hnd )
231{
232	if ( !hnd )
233		return;
234
235	/*only free the context if we created it */
236	if ( !hnd->_internal.user_supplied_ctx ) {
237		smbc_free_context( hnd->_internal.ctx, True );
238	}
239
240	SAFE_FREE( hnd->netbios_name );
241	SAFE_FREE( hnd->domain );
242	SAFE_FREE( hnd->username );
243	SAFE_FREE( hnd->password );
244	SAFE_FREE( hnd->server );
245	SAFE_FREE( hnd );
246
247}
248
249void cac_InitCacTime( CacTime * cactime, NTTIME nttime )
250{
251	float high, low;
252	uint32 sec;
253
254	if ( !cactime )
255		return;
256
257	ZERO_STRUCTP( cactime );
258
259	/*this code is taken from display_time() found in rpcclient/cmd_samr.c */
260	if ( nttime == 0 )
261		return;
262
263	if ( nttime == 0x80000000000000LL )
264		return;
265
266	high = 65536;
267	high = high / 10000;
268	high = high * 65536;
269	high = high / 1000;
270	high = high * ( ~( nttime >> 32 ) );
271
272	low = ~( nttime & 0xFFFFFFFF );
273	low = low / ( 1000 * 1000 * 10 );
274
275	sec = high + low;
276
277	cactime->days = sec / ( 60 * 60 * 24 );
278	cactime->hours =
279		( sec - ( cactime->days * 60 * 60 * 24 ) ) / ( 60 * 60 );
280	cactime->minutes =
281		( sec - ( cactime->days * 60 * 60 * 24 ) -
282		  ( cactime->hours * 60 * 60 ) ) / 60;
283	cactime->seconds =
284		sec - ( cactime->days * 60 * 60 * 24 ) -
285		( cactime->hours * 60 * 60 ) - ( cactime->minutes * 60 );
286}
287
288void cac_GetAuthDataFn( const char *pServer,
289			const char *pShare,
290			char *pWorkgroup,
291			int maxLenWorkgroup,
292			char *pUsername,
293			int maxLenUsername,
294			char *pPassword, int maxLenPassword )
295{
296	char temp[sizeof( fstring )];
297
298	static char authUsername[sizeof( fstring )];
299	static char authWorkgroup[sizeof( fstring )];
300	static char authPassword[sizeof( fstring )];
301	static char authSet = 0;
302
303	char *pass = NULL;
304
305
306	if ( authSet ) {
307		strncpy( pWorkgroup, authWorkgroup, maxLenWorkgroup - 1 );
308		strncpy( pUsername, authUsername, maxLenUsername - 1 );
309		strncpy( pPassword, authPassword, maxLenPassword - 1 );
310	} else {
311		d_printf( "Domain: [%s] ", pWorkgroup );
312		fgets( temp, sizeof( fstring ), stdin );
313
314		if ( temp[strlen( temp ) - 1] == '\n' ) {	/* A new line? */
315			temp[strlen( temp ) - 1] = '\0';
316		}
317
318
319		if ( temp[0] != '\0' ) {
320			strncpy( pWorkgroup, temp, maxLenWorkgroup - 1 );
321			strncpy( authWorkgroup, temp, maxLenWorkgroup - 1 );
322		}
323
324		d_printf( "Username: [%s] ", pUsername );
325		fgets( temp, sizeof( fstring ), stdin );
326
327		if ( temp[strlen( temp ) - 1] == '\n' ) {	/* A new line? */
328			temp[strlen( temp ) - 1] = '\0';
329		}
330
331		if ( temp[0] != '\0' ) {
332			strncpy( pUsername, temp, maxLenUsername - 1 );
333			strncpy( authUsername, pUsername,
334				 maxLenUsername - 1 );
335		}
336
337		pass = getpass( "Password: " );
338		if ( pass )
339			fstrcpy( temp, pass );
340		if ( temp[strlen( temp ) - 1] == '\n' ) {	/* A new line? */
341			temp[strlen( temp ) - 1] = '\0';
342		}
343		if ( temp[0] != '\0' ) {
344			strncpy( pPassword, temp, maxLenPassword - 1 );
345			strncpy( authPassword, pPassword,
346				 maxLenPassword - 1 );
347		}
348		authSet = 1;
349	}
350}
351