r21897: Add in a basic raw NTLM encrypt request. Now
[tprouty/samba.git] / source3 / libsmb / clifsinfo.c
1 /* 
2    Unix SMB/CIFS implementation.
3    FS info functions
4    Copyright (C) Stefan (metze) Metzmacher      2003
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 "includes.h"
22
23 /****************************************************************************
24  Get UNIX extensions version info.
25 ****************************************************************************/
26                                                                                                                    
27 BOOL cli_unix_extensions_version(struct cli_state *cli, uint16 *pmajor, uint16 *pminor,
28                                         uint32 *pcaplow, uint32 *pcaphigh)
29 {
30         BOOL ret = False;
31         uint16 setup;
32         char param[2];
33         char *rparam=NULL, *rdata=NULL;
34         unsigned int rparam_count=0, rdata_count=0;
35
36         setup = TRANSACT2_QFSINFO;
37         
38         SSVAL(param,0,SMB_QUERY_CIFS_UNIX_INFO);
39
40         if (!cli_send_trans(cli, SMBtrans2, 
41                     NULL, 
42                     0, 0,
43                     &setup, 1, 0,
44                     param, 2, 0,
45                     NULL, 0, 560)) {
46                 goto cleanup;
47         }
48         
49         if (!cli_receive_trans(cli, SMBtrans2,
50                               &rparam, &rparam_count,
51                               &rdata, &rdata_count)) {
52                 goto cleanup;
53         }
54
55         if (cli_is_error(cli)) {
56                 ret = False;
57                 goto cleanup;
58         } else {
59                 ret = True;
60         }
61
62         if (rdata_count < 12) {
63                 goto cleanup;
64         }
65
66         *pmajor = SVAL(rdata,0);
67         *pminor = SVAL(rdata,2);
68         *pcaplow = IVAL(rdata,4);
69         *pcaphigh = IVAL(rdata,8);
70
71         /* todo: but not yet needed 
72          *       return the other stuff
73          */
74
75 cleanup:
76         SAFE_FREE(rparam);
77         SAFE_FREE(rdata);
78
79         return ret;     
80 }
81
82 /****************************************************************************
83  Set UNIX extensions capabilities.
84 ****************************************************************************/
85                                                                                                                    
86 BOOL cli_set_unix_extensions_capabilities(struct cli_state *cli, uint16 major, uint16 minor,
87                                         uint32 caplow, uint32 caphigh)
88 {
89         BOOL ret = False;
90         uint16 setup;
91         char param[4];
92         char data[12];
93         char *rparam=NULL, *rdata=NULL;
94         unsigned int rparam_count=0, rdata_count=0;
95
96         setup = TRANSACT2_SETFSINFO;
97         
98         SSVAL(param,0,0);
99         SSVAL(param,2,SMB_SET_CIFS_UNIX_INFO);
100
101         SSVAL(data,0,major);
102         SSVAL(data,2,minor);
103         SIVAL(data,4,caplow);
104         SIVAL(data,8,caphigh);
105
106         if (!cli_send_trans(cli, SMBtrans2, 
107                     NULL, 
108                     0, 0,
109                     &setup, 1, 0,
110                     param, 4, 0,
111                     data, 12, 560)) {
112                 goto cleanup;
113         }
114         
115         if (!cli_receive_trans(cli, SMBtrans2,
116                               &rparam, &rparam_count,
117                               &rdata, &rdata_count)) {
118                 goto cleanup;
119         }
120
121         if (cli_is_error(cli)) {
122                 ret = False;
123                 goto cleanup;
124         } else {
125                 ret = True;
126         }
127
128 cleanup:
129         SAFE_FREE(rparam);
130         SAFE_FREE(rdata);
131
132         return ret;     
133 }
134
135 BOOL cli_get_fs_attr_info(struct cli_state *cli, uint32 *fs_attr)
136 {
137         BOOL ret = False;
138         uint16 setup;
139         char param[2];
140         char *rparam=NULL, *rdata=NULL;
141         unsigned int rparam_count=0, rdata_count=0;
142
143         if (!cli||!fs_attr)
144                 smb_panic("cli_get_fs_attr_info() called with NULL Pionter!");
145
146         setup = TRANSACT2_QFSINFO;
147         
148         SSVAL(param,0,SMB_QUERY_FS_ATTRIBUTE_INFO);
149
150         if (!cli_send_trans(cli, SMBtrans2, 
151                     NULL, 
152                     0, 0,
153                     &setup, 1, 0,
154                     param, 2, 0,
155                     NULL, 0, 560)) {
156                 goto cleanup;
157         }
158         
159         if (!cli_receive_trans(cli, SMBtrans2,
160                               &rparam, &rparam_count,
161                               &rdata, &rdata_count)) {
162                 goto cleanup;
163         }
164
165         if (cli_is_error(cli)) {
166                 ret = False;
167                 goto cleanup;
168         } else {
169                 ret = True;
170         }
171
172         if (rdata_count < 12) {
173                 goto cleanup;
174         }
175
176         *fs_attr = IVAL(rdata,0);
177
178         /* todo: but not yet needed 
179          *       return the other stuff
180          */
181
182 cleanup:
183         SAFE_FREE(rparam);
184         SAFE_FREE(rdata);
185
186         return ret;     
187 }
188
189 BOOL cli_get_fs_volume_info_old(struct cli_state *cli, fstring volume_name, uint32 *pserial_number)
190 {
191         BOOL ret = False;
192         uint16 setup;
193         char param[2];
194         char *rparam=NULL, *rdata=NULL;
195         unsigned int rparam_count=0, rdata_count=0;
196         unsigned char nlen;
197
198         setup = TRANSACT2_QFSINFO;
199         
200         SSVAL(param,0,SMB_INFO_VOLUME);
201
202         if (!cli_send_trans(cli, SMBtrans2, 
203                     NULL, 
204                     0, 0,
205                     &setup, 1, 0,
206                     param, 2, 0,
207                     NULL, 0, 560)) {
208                 goto cleanup;
209         }
210         
211         if (!cli_receive_trans(cli, SMBtrans2,
212                               &rparam, &rparam_count,
213                               &rdata, &rdata_count)) {
214                 goto cleanup;
215         }
216
217         if (cli_is_error(cli)) {
218                 ret = False;
219                 goto cleanup;
220         } else {
221                 ret = True;
222         }
223
224         if (rdata_count < 5) {
225                 goto cleanup;
226         }
227
228         if (pserial_number) {
229                 *pserial_number = IVAL(rdata,0);
230         }
231         nlen = CVAL(rdata,l2_vol_cch);
232         clistr_pull(cli, volume_name, rdata + l2_vol_szVolLabel, sizeof(fstring), nlen, STR_NOALIGN);
233
234         /* todo: but not yet needed 
235          *       return the other stuff
236          */
237
238 cleanup:
239         SAFE_FREE(rparam);
240         SAFE_FREE(rdata);
241
242         return ret;     
243 }
244
245 BOOL cli_get_fs_volume_info(struct cli_state *cli, fstring volume_name, uint32 *pserial_number, time_t *pdate)
246 {
247         BOOL ret = False;
248         uint16 setup;
249         char param[2];
250         char *rparam=NULL, *rdata=NULL;
251         unsigned int rparam_count=0, rdata_count=0;
252         unsigned int nlen;
253
254         setup = TRANSACT2_QFSINFO;
255         
256         SSVAL(param,0,SMB_QUERY_FS_VOLUME_INFO);
257
258         if (!cli_send_trans(cli, SMBtrans2, 
259                     NULL, 
260                     0, 0,
261                     &setup, 1, 0,
262                     param, 2, 0,
263                     NULL, 0, 560)) {
264                 goto cleanup;
265         }
266         
267         if (!cli_receive_trans(cli, SMBtrans2,
268                               &rparam, &rparam_count,
269                               &rdata, &rdata_count)) {
270                 goto cleanup;
271         }
272
273         if (cli_is_error(cli)) {
274                 ret = False;
275                 goto cleanup;
276         } else {
277                 ret = True;
278         }
279
280         if (rdata_count < 19) {
281                 goto cleanup;
282         }
283
284         if (pdate) {
285                 struct timespec ts;
286                 ts = interpret_long_date(rdata);
287                 *pdate = ts.tv_sec;
288         }
289         if (pserial_number) {
290                 *pserial_number = IVAL(rdata,8);
291         }
292         nlen = IVAL(rdata,12);
293         clistr_pull(cli, volume_name, rdata + 18, sizeof(fstring), nlen, STR_UNICODE);
294
295         /* todo: but not yet needed 
296          *       return the other stuff
297          */
298
299 cleanup:
300         SAFE_FREE(rparam);
301         SAFE_FREE(rdata);
302
303         return ret;     
304 }
305
306 /******************************************************************************
307  Send/receive the request encryption blob.
308 ******************************************************************************/
309
310 static NTSTATUS enc_blob_send_receive(struct cli_state *cli, DATA_BLOB *in, DATA_BLOB *out)
311 {
312         uint16 setup;
313         char param[2];
314         char *rparam=NULL, *rdata=NULL;
315         unsigned int rparam_count=0, rdata_count=0;
316         NTSTATUS status = NT_STATUS_OK;
317
318         setup = TRANSACT2_SETFSINFO;
319
320         SSVAL(param,0,SMB_REQUEST_TRANSPORT_ENCRYPTION);
321
322         if (!cli_send_trans(cli, SMBtrans2,
323                                 NULL,
324                                 0, 0,
325                                 &setup, 1, 0,
326                                 param, 2, 0,
327                                 (char *)in->data, in->length, CLI_BUFFER_SIZE)) {
328                 status = cli_nt_error(cli);
329                 goto out;
330         }
331
332         if (!cli_receive_trans(cli, SMBtrans2,
333                                 &rparam, &rparam_count,
334                                 &rdata, &rdata_count)) {
335                 status = cli_nt_error(cli);
336                 goto out;
337         }
338
339         if (cli_is_error(cli)) {
340                 status = cli_nt_error(cli);
341                 if (!NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
342                         goto out;
343                 }
344         }
345
346         *out = data_blob(rdata, rdata_count);
347
348   out:
349
350         SAFE_FREE(rparam);
351         SAFE_FREE(rdata);
352         return status;
353 }
354
355 /******************************************************************************
356  Start a raw ntlmssp encryption.
357 ******************************************************************************/
358
359 NTSTATUS cli_raw_ntlm_smb_encryption_start(struct cli_state *cli, 
360                                 const char *user,
361                                 const char *pass,
362                                 const char *domain)
363 {
364         DATA_BLOB blob_in = data_blob(NULL, 0);
365         DATA_BLOB blob_out = data_blob(NULL, 0);
366         NTSTATUS status = NT_STATUS_UNSUCCESSFUL;
367         struct smb_trans_enc_state *es = NULL;
368
369         es = SMB_MALLOC_P(struct smb_trans_enc_state);
370         if (!es) {
371                 return NT_STATUS_NO_MEMORY;
372         }
373         ZERO_STRUCTP(es);
374         es->smb_enc_type = SMB_TRANS_ENC_NTLM;
375         status = ntlmssp_client_start(&es->ntlmssp_state);
376         if (!NT_STATUS_IS_OK(status)) {
377                 goto fail;
378         }
379
380         ntlmssp_want_feature(es->ntlmssp_state, NTLMSSP_FEATURE_SESSION_KEY);
381         es->ntlmssp_state->neg_flags |= (NTLMSSP_NEGOTIATE_SIGN|NTLMSSP_NEGOTIATE_SEAL);
382
383         if (!NT_STATUS_IS_OK(status = ntlmssp_set_username(es->ntlmssp_state, user))) {
384                 goto fail;
385         }
386         if (!NT_STATUS_IS_OK(status = ntlmssp_set_domain(es->ntlmssp_state, domain))) {
387                 goto fail;
388         }
389         if (!NT_STATUS_IS_OK(status = ntlmssp_set_password(es->ntlmssp_state, pass))) {
390                 goto fail;
391         }
392
393         do {
394                 status = ntlmssp_update(es->ntlmssp_state, blob_in, &blob_out);
395                 data_blob_free(&blob_in);
396                 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED) || NT_STATUS_IS_OK(status)) {
397                         status = enc_blob_send_receive(cli, &blob_out, &blob_in);
398                 }
399                 data_blob_free(&blob_out);
400         } while (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED));
401
402         data_blob_free(&blob_in);
403
404         if (NT_STATUS_IS_OK(status)) {
405                 /* Replace the old state, if any. */
406                 if (cli->trans_enc_state) {
407                         common_free_encryption_state(&cli->trans_enc_state);
408                 }
409                 cli->trans_enc_state = es;
410                 cli->trans_enc_state->enc_on = True;
411         }
412
413   fail:
414
415         common_free_encryption_state(&es);
416         return status;
417 }