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