r23779: Change from v2 or later to v3 or later.
[sfrench/samba-autobuild/.git] / source3 / libmsrpc / libmsrpc.c
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 3 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
27 int cac_InitHandleData( CacServerHandle * hnd );
28
29 /*this function is based on code found in smbc_init_context() (libsmb/libsmbclient.c)*/
30 void 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
40 int 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
76 CacServerHandle *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
115 int 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
143 void cac_SetAuthDataFn( CacServerHandle * hnd, smbc_get_auth_data_fn auth_fn )
144 {
145         hnd->_internal.ctx->callbacks.auth_fn = auth_fn;
146 }
147
148 void 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*/
162 SMBCSRV *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
183 int 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
230 void 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
249 void 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
288 void 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 }