vfs_default: remove assert from vfswrap_mkdirat()
[Samba.git] / auth / gensec / ncalrpc.c
blob7474b6aff9b3f971db5b166604517ade650eb279
1 /*
2 Unix SMB/CIFS implementation.
4 dcerpc ncalrpc as system operations
6 Copyright (C) 2014 Andreas Schneider <asn@samba.org>
7 Copyright (C) 2014 Stefan Metzmacher <metze@samba.org>
9 This program is free software; you can redistribute it and/or modify
10 it under the terms of the GNU General Public License as published by
11 the Free Software Foundation; either version 3 of the License, or
12 (at your option) any later version.
14 This program is distributed in the hope that it will be useful,
15 but WITHOUT ANY WARRANTY; without even the implied warranty of
16 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 GNU General Public License for more details.
19 You should have received a copy of the GNU General Public License
20 along with this program. If not, see <http://www.gnu.org/licenses/>.
23 #include "includes.h"
24 #include <tevent.h>
25 #include "lib/util/tevent_ntstatus.h"
26 #include "auth/auth.h"
27 #include "auth/gensec/gensec.h"
28 #include "auth/gensec/gensec_internal.h"
29 #include "librpc/gen_ndr/dcerpc.h"
30 #include "lib/param/param.h"
31 #include "tsocket.h"
33 #undef DBGC_CLASS
34 #define DBGC_CLASS DBGC_AUTH
36 _PUBLIC_ NTSTATUS gensec_ncalrpc_as_system_init(TALLOC_CTX *ctx);
38 struct gensec_ncalrpc_state {
39 enum {
40 GENSEC_NCALRPC_START,
41 GENSEC_NCALRPC_MORE,
42 GENSEC_NCALRPC_DONE,
43 GENSEC_NCALRPC_ERROR,
44 } step;
46 struct auth_user_info_dc *user_info_dc;
49 static NTSTATUS gensec_ncalrpc_client_start(struct gensec_security *gensec_security)
51 struct gensec_ncalrpc_state *state;
53 state = talloc_zero(gensec_security,
54 struct gensec_ncalrpc_state);
55 if (state == NULL) {
56 return NT_STATUS_NO_MEMORY;
58 gensec_security->private_data = state;
60 state->step = GENSEC_NCALRPC_START;
61 return NT_STATUS_OK;
64 static NTSTATUS gensec_ncalrpc_server_start(struct gensec_security *gensec_security)
66 struct gensec_ncalrpc_state *state;
68 state = talloc_zero(gensec_security,
69 struct gensec_ncalrpc_state);
70 if (state == NULL) {
71 return NT_STATUS_NO_MEMORY;
73 gensec_security->private_data = state;
75 state->step = GENSEC_NCALRPC_START;
76 return NT_STATUS_OK;
79 struct gensec_ncalrpc_update_state {
80 NTSTATUS status;
81 DATA_BLOB out;
84 static NTSTATUS gensec_ncalrpc_update_internal(
85 struct gensec_security *gensec_security,
86 TALLOC_CTX *mem_ctx,
87 const DATA_BLOB in,
88 DATA_BLOB *out);
90 static struct tevent_req *gensec_ncalrpc_update_send(TALLOC_CTX *mem_ctx,
91 struct tevent_context *ev,
92 struct gensec_security *gensec_security,
93 const DATA_BLOB in)
95 struct tevent_req *req;
96 struct gensec_ncalrpc_update_state *state = NULL;
97 NTSTATUS status;
99 req = tevent_req_create(mem_ctx, &state,
100 struct gensec_ncalrpc_update_state);
101 if (req == NULL) {
102 return NULL;
105 status = gensec_ncalrpc_update_internal(gensec_security,
106 state, in,
107 &state->out);
108 state->status = status;
109 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
110 status = NT_STATUS_OK;
112 if (tevent_req_nterror(req, status)) {
113 return tevent_req_post(req, ev);
116 tevent_req_done(req);
117 return tevent_req_post(req, ev);
120 static NTSTATUS gensec_ncalrpc_update_internal(
121 struct gensec_security *gensec_security,
122 TALLOC_CTX *mem_ctx,
123 const DATA_BLOB in,
124 DATA_BLOB *out)
126 struct gensec_ncalrpc_state *state =
127 talloc_get_type_abort(gensec_security->private_data,
128 struct gensec_ncalrpc_state);
129 DATA_BLOB magic_req = data_blob_string_const("NCALRPC_AUTH_TOKEN");
130 DATA_BLOB magic_ok = data_blob_string_const("NCALRPC_AUTH_OK");
131 DATA_BLOB magic_fail = data_blob_string_const("NCALRPC_AUTH_FAIL");
132 char *unix_path = NULL;
133 int cmp;
134 NTSTATUS status;
136 *out = data_blob_null;
138 if (state->step >= GENSEC_NCALRPC_DONE) {
139 return NT_STATUS_INVALID_PARAMETER;
142 switch (gensec_security->gensec_role) {
143 case GENSEC_CLIENT:
144 switch (state->step) {
145 case GENSEC_NCALRPC_START:
146 *out = data_blob_dup_talloc(mem_ctx, magic_req);
147 if (out->data == NULL) {
148 state->step = GENSEC_NCALRPC_ERROR;
149 return NT_STATUS_NO_MEMORY;
152 state->step = GENSEC_NCALRPC_MORE;
153 return NT_STATUS_MORE_PROCESSING_REQUIRED;
155 case GENSEC_NCALRPC_MORE:
156 cmp = data_blob_cmp(&in, &magic_ok);
157 if (cmp != 0) {
158 state->step = GENSEC_NCALRPC_ERROR;
159 return NT_STATUS_LOGON_FAILURE;
162 state->step = GENSEC_NCALRPC_DONE;
163 return NT_STATUS_OK;
165 case GENSEC_NCALRPC_DONE:
166 case GENSEC_NCALRPC_ERROR:
167 break;
170 state->step = GENSEC_NCALRPC_ERROR;
171 return NT_STATUS_INTERNAL_ERROR;
173 case GENSEC_SERVER:
174 if (state->step != GENSEC_NCALRPC_START) {
175 state->step = GENSEC_NCALRPC_ERROR;
176 return NT_STATUS_INTERNAL_ERROR;
179 cmp = data_blob_cmp(&in, &magic_req);
180 if (cmp != 0) {
181 state->step = GENSEC_NCALRPC_ERROR;
182 *out = data_blob_dup_talloc(mem_ctx, magic_fail);
183 if (out->data == NULL) {
184 return NT_STATUS_NO_MEMORY;
186 return NT_STATUS_LOGON_FAILURE;
189 if (gensec_security->remote_addr == NULL) {
190 state->step = GENSEC_NCALRPC_ERROR;
191 *out = data_blob_dup_talloc(mem_ctx, magic_fail);
192 if (out->data == NULL) {
193 return NT_STATUS_NO_MEMORY;
195 return NT_STATUS_LOGON_FAILURE;
198 unix_path = tsocket_address_unix_path(gensec_security->remote_addr,
199 state);
200 if (unix_path == NULL) {
201 state->step = GENSEC_NCALRPC_ERROR;
202 *out = data_blob_dup_talloc(mem_ctx, magic_fail);
203 if (out->data == NULL) {
204 return NT_STATUS_NO_MEMORY;
206 return NT_STATUS_LOGON_FAILURE;
209 cmp = strcmp(unix_path, AS_SYSTEM_MAGIC_PATH_TOKEN);
210 TALLOC_FREE(unix_path);
211 if (cmp != 0) {
212 state->step = GENSEC_NCALRPC_ERROR;
213 *out = data_blob_dup_talloc(mem_ctx, magic_fail);
214 if (out->data == NULL) {
215 return NT_STATUS_NO_MEMORY;
217 return NT_STATUS_LOGON_FAILURE;
220 status = auth_system_user_info_dc(state,
221 lpcfg_netbios_name(gensec_security->settings->lp_ctx),
222 &state->user_info_dc);
223 if (!NT_STATUS_IS_OK(status)) {
224 state->step = GENSEC_NCALRPC_ERROR;
225 *out = data_blob_dup_talloc(mem_ctx, magic_fail);
226 if (out->data == NULL) {
227 return NT_STATUS_NO_MEMORY;
229 return status;
232 *out = data_blob_dup_talloc(mem_ctx, magic_ok);
233 if (out->data == NULL) {
234 state->step = GENSEC_NCALRPC_ERROR;
235 return NT_STATUS_NO_MEMORY;
238 state->step = GENSEC_NCALRPC_DONE;
239 return NT_STATUS_OK;
242 state->step = GENSEC_NCALRPC_ERROR;
243 return NT_STATUS_INTERNAL_ERROR;
246 static NTSTATUS gensec_ncalrpc_update_recv(struct tevent_req *req,
247 TALLOC_CTX *out_mem_ctx,
248 DATA_BLOB *out)
250 struct gensec_ncalrpc_update_state *state =
251 tevent_req_data(req,
252 struct gensec_ncalrpc_update_state);
253 NTSTATUS status;
255 *out = data_blob_null;
257 if (tevent_req_is_nterror(req, &status)) {
258 tevent_req_received(req);
259 return status;
262 status = state->status;
263 talloc_steal(out_mem_ctx, state->out.data);
264 *out = state->out;
265 tevent_req_received(req);
266 return status;
269 static NTSTATUS gensec_ncalrpc_session_info(struct gensec_security *gensec_security,
270 TALLOC_CTX *mem_ctx,
271 struct auth_session_info **psession_info)
273 struct gensec_ncalrpc_state *state =
274 talloc_get_type_abort(gensec_security->private_data,
275 struct gensec_ncalrpc_state);
276 struct auth4_context *auth_ctx = gensec_security->auth_context;
277 struct auth_session_info *session_info = NULL;
278 uint32_t session_info_flags = 0;
279 NTSTATUS status;
281 if (gensec_security->gensec_role != GENSEC_SERVER) {
282 return NT_STATUS_INVALID_PARAMETER;
285 if (state->step != GENSEC_NCALRPC_DONE) {
286 return NT_STATUS_INVALID_PARAMETER;
289 if (auth_ctx == NULL) {
290 DEBUG(0, ("Cannot generate a session_info without the auth_context\n"));
291 return NT_STATUS_INTERNAL_ERROR;
294 if (auth_ctx->generate_session_info == NULL) {
295 DEBUG(0, ("Cannot generate a session_info without the generate_session_info hook\n"));
296 return NT_STATUS_INTERNAL_ERROR;
299 if (gensec_security->want_features & GENSEC_FEATURE_UNIX_TOKEN) {
300 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
303 session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
305 status = auth_ctx->generate_session_info(
306 auth_ctx,
307 mem_ctx,
308 state->user_info_dc,
309 state->user_info_dc->info->account_name,
310 session_info_flags,
311 &session_info);
312 if (!NT_STATUS_IS_OK(status)) {
313 return status;
316 *psession_info = session_info;
317 return NT_STATUS_OK;
320 /* We have no features */
321 static bool gensec_ncalrpc_have_feature(struct gensec_security *gensec_security,
322 uint32_t feature)
324 if (feature & GENSEC_FEATURE_DCE_STYLE) {
325 return true;
328 return false;
331 static const struct gensec_security_ops gensec_ncalrpc_security_ops = {
332 .name = "naclrpc_as_system",
333 .auth_type = DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM,
334 .client_start = gensec_ncalrpc_client_start,
335 .server_start = gensec_ncalrpc_server_start,
336 .update_send = gensec_ncalrpc_update_send,
337 .update_recv = gensec_ncalrpc_update_recv,
338 .session_info = gensec_ncalrpc_session_info,
339 .have_feature = gensec_ncalrpc_have_feature,
340 .enabled = true,
341 .priority = GENSEC_EXTERNAL,
344 _PUBLIC_ NTSTATUS gensec_ncalrpc_as_system_init(TALLOC_CTX *ctx)
346 NTSTATUS status;
348 status = gensec_register(ctx, &gensec_ncalrpc_security_ops);
349 if (!NT_STATUS_IS_OK(status)) {
350 DEBUG(0, ("Failed to register '%s' gensec backend!\n",
351 gensec_ncalrpc_security_ops.name));
352 return status;
355 return status;