Line data Source code
1 : /* 2 : Unix SMB/CIFS implementation. 3 : 4 : Copyright (C) Volker Lendecke 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 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 loading a whole file into memory 21 : */ 22 : 23 : #include "includes.h" 24 : #include "libcli/composite/composite.h" 25 : #include "libcli/smb_composite/smb_composite.h" 26 : #include "libcli/resolve/resolve.h" 27 : 28 : enum fetchfile_stage {FETCHFILE_CONNECT, 29 : FETCHFILE_READ}; 30 : 31 : struct fetchfile_state { 32 : enum fetchfile_stage stage; 33 : struct smb_composite_fetchfile *io; 34 : struct composite_context *creq; 35 : struct smb_composite_connect *connect; 36 : struct smb_composite_loadfile *loadfile; 37 : }; 38 : 39 : static void fetchfile_composite_handler(struct composite_context *req); 40 : 41 50 : static NTSTATUS fetchfile_connect(struct composite_context *c, 42 : struct smb_composite_fetchfile *io) 43 : { 44 0 : NTSTATUS status; 45 0 : struct fetchfile_state *state; 46 50 : state = talloc_get_type(c->private_data, struct fetchfile_state); 47 : 48 50 : status = smb_composite_connect_recv(state->creq, c); 49 50 : NT_STATUS_NOT_OK_RETURN(status); 50 : 51 50 : state->loadfile = talloc(state, struct smb_composite_loadfile); 52 50 : NT_STATUS_HAVE_NO_MEMORY(state->loadfile); 53 : 54 50 : state->loadfile->in.fname = io->in.filename; 55 : 56 50 : state->creq = smb_composite_loadfile_send(state->connect->out.tree, 57 : state->loadfile); 58 50 : NT_STATUS_HAVE_NO_MEMORY(state->creq); 59 : 60 50 : state->creq->async.private_data = c; 61 50 : state->creq->async.fn = fetchfile_composite_handler; 62 : 63 50 : state->stage = FETCHFILE_READ; 64 : 65 50 : return NT_STATUS_OK; 66 : } 67 : 68 50 : static NTSTATUS fetchfile_read(struct composite_context *c, 69 : struct smb_composite_fetchfile *io) 70 : { 71 0 : NTSTATUS status; 72 0 : struct fetchfile_state *state; 73 50 : state = talloc_get_type(c->private_data, struct fetchfile_state); 74 : 75 50 : status = smb_composite_loadfile_recv(state->creq, NULL); 76 50 : NT_STATUS_NOT_OK_RETURN(status); 77 : 78 50 : io->out.data = state->loadfile->out.data; 79 50 : io->out.size = state->loadfile->out.size; 80 : 81 50 : c->state = COMPOSITE_STATE_DONE; 82 50 : if (c->async.fn) 83 50 : c->async.fn(c); 84 : 85 50 : return NT_STATUS_OK; 86 : } 87 : 88 100 : static void fetchfile_state_handler(struct composite_context *c) 89 : { 90 0 : struct fetchfile_state *state; 91 0 : NTSTATUS status; 92 : 93 100 : state = talloc_get_type(c->private_data, struct fetchfile_state); 94 : 95 : /* when this handler is called, the stage indicates what 96 : call has just finished */ 97 100 : switch (state->stage) { 98 50 : case FETCHFILE_CONNECT: 99 50 : status = fetchfile_connect(c, state->io); 100 50 : break; 101 50 : case FETCHFILE_READ: 102 50 : status = fetchfile_read(c, state->io); 103 50 : break; 104 0 : default: 105 0 : status = NT_STATUS_UNSUCCESSFUL; 106 0 : break; 107 : } 108 : 109 100 : if (!NT_STATUS_IS_OK(status)) { 110 0 : c->status = status; 111 0 : c->state = COMPOSITE_STATE_ERROR; 112 0 : if (c->async.fn) { 113 0 : c->async.fn(c); 114 : } 115 : } 116 100 : } 117 : 118 100 : static void fetchfile_composite_handler(struct composite_context *creq) 119 : { 120 100 : struct composite_context *c = talloc_get_type(creq->async.private_data, 121 : struct composite_context); 122 100 : fetchfile_state_handler(c); 123 100 : } 124 : 125 50 : struct composite_context *smb_composite_fetchfile_send(struct smb_composite_fetchfile *io, 126 : struct tevent_context *event_ctx) 127 : { 128 0 : struct composite_context *c; 129 0 : struct fetchfile_state *state; 130 : 131 50 : c = talloc_zero(NULL, struct composite_context); 132 50 : if (c == NULL) goto failed; 133 : 134 50 : state = talloc(c, struct fetchfile_state); 135 50 : if (state == NULL) goto failed; 136 : 137 50 : state->connect = talloc_zero(state, struct smb_composite_connect); 138 50 : if (state->connect == NULL) goto failed; 139 : 140 50 : state->io = io; 141 : 142 50 : state->connect->in.dest_host = io->in.dest_host; 143 50 : state->connect->in.dest_ports = io->in.ports; 144 50 : state->connect->in.socket_options = io->in.socket_options; 145 50 : state->connect->in.called_name = io->in.called_name; 146 50 : state->connect->in.service = io->in.service; 147 50 : state->connect->in.service_type = io->in.service_type; 148 50 : state->connect->in.credentials = io->in.credentials; 149 50 : state->connect->in.fallback_to_anonymous = false; 150 50 : state->connect->in.workgroup = io->in.workgroup; 151 50 : state->connect->in.gensec_settings = io->in.gensec_settings; 152 : 153 50 : state->connect->in.options = io->in.options; 154 50 : state->connect->in.session_options = io->in.session_options; 155 : 156 50 : state->creq = smb_composite_connect_send(state->connect, state, 157 : io->in.resolve_ctx, event_ctx); 158 50 : if (state->creq == NULL) goto failed; 159 : 160 50 : state->creq->async.private_data = c; 161 50 : state->creq->async.fn = fetchfile_composite_handler; 162 : 163 50 : c->state = COMPOSITE_STATE_IN_PROGRESS; 164 50 : state->stage = FETCHFILE_CONNECT; 165 50 : c->private_data = state; 166 : 167 50 : return c; 168 0 : failed: 169 0 : talloc_free(c); 170 0 : return NULL; 171 : } 172 : 173 50 : NTSTATUS smb_composite_fetchfile_recv(struct composite_context *c, 174 : TALLOC_CTX *mem_ctx) 175 : { 176 0 : NTSTATUS status; 177 : 178 50 : status = composite_wait(c); 179 : 180 50 : if (NT_STATUS_IS_OK(status)) { 181 50 : struct fetchfile_state *state = talloc_get_type(c->private_data, struct fetchfile_state); 182 50 : talloc_steal(mem_ctx, state->io->out.data); 183 : } 184 : 185 50 : talloc_free(c); 186 50 : return status; 187 : } 188 : 189 0 : NTSTATUS smb_composite_fetchfile(struct smb_composite_fetchfile *io, 190 : TALLOC_CTX *mem_ctx) 191 : { 192 0 : struct composite_context *c = smb_composite_fetchfile_send(io, NULL); 193 0 : return smb_composite_fetchfile_recv(c, mem_ctx); 194 : }