added mkdir to SMB2 proxy
[ira/wip.git] / source4 / libcli / smb_composite / smb2.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    Copyright (C) Andrew Tridgell 2008
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 3 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, see <http://www.gnu.org/licenses/>.
18 */
19 /*
20   a composite API for making SMB-like calls using SMB2. This is useful
21   as SMB2 often requires more than one requests where a single SMB
22   request would do. In converting code that uses SMB to use SMB2,
23   these routines make life a lot easier
24 */
25
26
27 #include "includes.h"
28 #include "libcli/raw/libcliraw.h"
29 #include "libcli/raw/raw_proto.h"
30 #include "libcli/composite/composite.h"
31 #include "libcli/smb_composite/smb_composite.h"
32 #include "param/param.h"
33 #include "libcli/smb2/smb2_calls.h"
34
35 /*
36   continue after a SMB2 close
37  */
38 static void continue_close(struct smb2_request *req)
39 {
40         struct composite_context *ctx = talloc_get_type(req->async.private_data, 
41                                                         struct composite_context);
42         NTSTATUS status;
43         struct smb2_close close_parm;
44
45         status = smb2_close_recv(req, &close_parm);
46         composite_error(ctx, status);   
47 }
48
49 /*
50   continue after the create in a composite unlink
51  */
52 static void continue_unlink(struct smb2_request *req)
53 {
54         struct composite_context *ctx = talloc_get_type(req->async.private_data, 
55                                                         struct composite_context);
56         struct smb2_tree *tree = req->tree;
57         struct smb2_create create_parm;
58         struct smb2_close close_parm;
59         NTSTATUS status;
60
61         status = smb2_create_recv(req, ctx, &create_parm);
62         if (!NT_STATUS_IS_OK(status)) {
63                 composite_error(ctx, status);
64                 return;
65         }
66
67         ZERO_STRUCT(close_parm);
68         close_parm.in.file.handle = create_parm.out.file.handle;
69         
70         req = smb2_close_send(tree, &close_parm);
71         composite_continue_smb2(ctx, req, continue_close, ctx);
72 }
73
74 /*
75   composite SMB2 unlink call
76 */
77 struct composite_context *smb2_composite_unlink_send(struct smb2_tree *tree, 
78                                                      union smb_unlink *io)
79 {
80         struct composite_context *ctx;
81         struct smb2_create create_parm;
82         struct smb2_request *req;
83
84         ctx = composite_create(tree, tree->session->transport->socket->event.ctx);
85         if (ctx == NULL) return NULL;
86
87         /* check for wildcards - we could support these with a
88            search, but for now they aren't necessary */
89         if (strpbrk(io->unlink.in.pattern, "*?<>") != NULL) {
90                 composite_error(ctx, NT_STATUS_NOT_SUPPORTED);
91                 return ctx;
92         }
93
94         ZERO_STRUCT(create_parm);
95         create_parm.in.desired_access     = SEC_STD_DELETE;
96         create_parm.in.create_disposition = NTCREATEX_DISP_OPEN;
97         create_parm.in.share_access = 
98                 NTCREATEX_SHARE_ACCESS_DELETE|
99                 NTCREATEX_SHARE_ACCESS_READ|
100                 NTCREATEX_SHARE_ACCESS_WRITE;
101         create_parm.in.create_options = NTCREATEX_OPTIONS_DELETE_ON_CLOSE;
102         create_parm.in.fname = io->unlink.in.pattern;
103         if (create_parm.in.fname[0] == '\\') {
104                 create_parm.in.fname++;
105         }
106
107         req = smb2_create_send(tree, &create_parm);
108
109         composite_continue_smb2(ctx, req, continue_unlink, ctx);
110         return ctx;
111 }
112
113
114 /*
115   composite unlink call - sync interface
116 */
117 NTSTATUS smb2_composite_unlink(struct smb2_tree *tree, union smb_unlink *io)
118 {
119         struct composite_context *c = smb2_composite_unlink_send(tree, io);
120         return composite_wait_free(c);
121 }
122
123
124
125
126 /*
127   continue after the create in a composite mkdir
128  */
129 static void continue_mkdir(struct smb2_request *req)
130 {
131         struct composite_context *ctx = talloc_get_type(req->async.private_data, 
132                                                         struct composite_context);
133         struct smb2_tree *tree = req->tree;
134         struct smb2_create create_parm;
135         struct smb2_close close_parm;
136         NTSTATUS status;
137
138         status = smb2_create_recv(req, ctx, &create_parm);
139         if (!NT_STATUS_IS_OK(status)) {
140                 composite_error(ctx, status);
141                 return;
142         }
143
144         ZERO_STRUCT(close_parm);
145         close_parm.in.file.handle = create_parm.out.file.handle;
146         
147         req = smb2_close_send(tree, &close_parm);
148         composite_continue_smb2(ctx, req, continue_close, ctx);
149 }
150
151 /*
152   composite SMB2 mkdir call
153 */
154 struct composite_context *smb2_composite_mkdir_send(struct smb2_tree *tree, 
155                                                      union smb_mkdir *io)
156 {
157         struct composite_context *ctx;
158         struct smb2_create create_parm;
159         struct smb2_request *req;
160
161         ctx = composite_create(tree, tree->session->transport->socket->event.ctx);
162         if (ctx == NULL) return NULL;
163
164         ZERO_STRUCT(create_parm);
165
166         create_parm.in.desired_access = SEC_FLAG_MAXIMUM_ALLOWED;
167         create_parm.in.share_access = 
168                 NTCREATEX_SHARE_ACCESS_READ|
169                 NTCREATEX_SHARE_ACCESS_WRITE;
170         create_parm.in.create_options = NTCREATEX_OPTIONS_DIRECTORY;
171         create_parm.in.file_attributes   = FILE_ATTRIBUTE_DIRECTORY;
172         create_parm.in.create_disposition = NTCREATEX_DISP_CREATE;
173         create_parm.in.fname = io->mkdir.in.path;
174         if (create_parm.in.fname[0] == '\\') {
175                 create_parm.in.fname++;
176         }
177
178         req = smb2_create_send(tree, &create_parm);
179
180         composite_continue_smb2(ctx, req, continue_mkdir, ctx);
181
182         return ctx;
183 }
184
185
186 /*
187   composite mkdir call - sync interface
188 */
189 NTSTATUS smb2_composite_mkdir(struct smb2_tree *tree, union smb_mkdir *io)
190 {
191         struct composite_context *c = smb2_composite_mkdir_send(tree, io);
192         return composite_wait_free(c);
193 }
194