Check "auth event notification" param in log_json
[nivanova/samba-autobuild/.git] / auth / gensec / ncalrpc.c
1 /*
2    Unix SMB/CIFS implementation.
3
4    dcerpc ncalrpc as system operations
5
6    Copyright (C) 2014      Andreas Schneider <asn@samba.org>
7    Copyright (C) 2014      Stefan Metzmacher <metze@samba.org>
8
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.
13
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.
18
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/>.
21 */
22
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"
32
33 #undef DBGC_CLASS
34 #define DBGC_CLASS DBGC_AUTH
35
36 _PUBLIC_ NTSTATUS gensec_ncalrpc_as_system_init(TALLOC_CTX *ctx);
37
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;
45
46         struct auth_user_info_dc *user_info_dc;
47 };
48
49 static NTSTATUS gensec_ncalrpc_client_start(struct gensec_security *gensec_security)
50 {
51         struct gensec_ncalrpc_state *state;
52
53         state = talloc_zero(gensec_security,
54                             struct gensec_ncalrpc_state);
55         if (state == NULL) {
56                 return NT_STATUS_NO_MEMORY;
57         }
58         gensec_security->private_data = state;
59
60         state->step = GENSEC_NCALRPC_START;
61         return NT_STATUS_OK;
62 }
63
64 static NTSTATUS gensec_ncalrpc_server_start(struct gensec_security *gensec_security)
65 {
66         struct gensec_ncalrpc_state *state;
67
68         state = talloc_zero(gensec_security,
69                             struct gensec_ncalrpc_state);
70         if (state == NULL) {
71                 return NT_STATUS_NO_MEMORY;
72         }
73         gensec_security->private_data = state;
74
75         state->step = GENSEC_NCALRPC_START;
76         return NT_STATUS_OK;
77 }
78
79 struct gensec_ncalrpc_update_state {
80         NTSTATUS status;
81         DATA_BLOB out;
82 };
83
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);
89
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)
94 {
95         struct tevent_req *req;
96         struct gensec_ncalrpc_update_state *state = NULL;
97         NTSTATUS status;
98
99         req = tevent_req_create(mem_ctx, &state,
100                                 struct gensec_ncalrpc_update_state);
101         if (req == NULL) {
102                 return NULL;
103         }
104
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;
111         }
112         if (tevent_req_nterror(req, status)) {
113                 return tevent_req_post(req, ev);
114         }
115
116         tevent_req_done(req);
117         return tevent_req_post(req, ev);
118 }
119
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)
125 {
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;
135
136         *out = data_blob_null;
137
138         if (state->step >= GENSEC_NCALRPC_DONE) {
139                 return NT_STATUS_INVALID_PARAMETER;
140         }
141
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;
150                         }
151
152                         state->step = GENSEC_NCALRPC_MORE;
153                         return NT_STATUS_MORE_PROCESSING_REQUIRED;
154
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;
160                         }
161
162                         state->step = GENSEC_NCALRPC_DONE;
163                         return NT_STATUS_OK;
164
165                 case GENSEC_NCALRPC_DONE:
166                 case GENSEC_NCALRPC_ERROR:
167                         break;
168                 }
169
170                 state->step = GENSEC_NCALRPC_ERROR;
171                 return NT_STATUS_INTERNAL_ERROR;
172
173         case GENSEC_SERVER:
174                 if (state->step != GENSEC_NCALRPC_START) {
175                         state->step = GENSEC_NCALRPC_ERROR;
176                         return NT_STATUS_INTERNAL_ERROR;
177                 }
178
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;
185                         }
186                         return NT_STATUS_LOGON_FAILURE;
187                 }
188
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;
194                         }
195                         return NT_STATUS_LOGON_FAILURE;
196                 }
197
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;
205                         }
206                         return NT_STATUS_LOGON_FAILURE;
207                 }
208
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;
216                         }
217                         return NT_STATUS_LOGON_FAILURE;
218                 }
219
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;
228                         }
229                         return status;
230                 }
231
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;
236                 }
237
238                 state->step = GENSEC_NCALRPC_DONE;
239                 return NT_STATUS_OK;
240         }
241
242         state->step = GENSEC_NCALRPC_ERROR;
243         return NT_STATUS_INTERNAL_ERROR;
244 }
245
246 static NTSTATUS gensec_ncalrpc_update_recv(struct tevent_req *req,
247                                            TALLOC_CTX *out_mem_ctx,
248                                            DATA_BLOB *out)
249 {
250         struct gensec_ncalrpc_update_state *state =
251                 tevent_req_data(req,
252                 struct gensec_ncalrpc_update_state);
253         NTSTATUS status;
254
255         *out = data_blob_null;
256
257         if (tevent_req_is_nterror(req, &status)) {
258                 tevent_req_received(req);
259                 return status;
260         }
261
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;
267 }
268
269 static NTSTATUS gensec_ncalrpc_session_info(struct gensec_security *gensec_security,
270                                             TALLOC_CTX *mem_ctx,
271                                             struct auth_session_info **psession_info)
272 {
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;
280
281         if (gensec_security->gensec_role != GENSEC_SERVER) {
282                 return NT_STATUS_INVALID_PARAMETER;
283         }
284
285         if (state->step != GENSEC_NCALRPC_DONE) {
286                 return NT_STATUS_INVALID_PARAMETER;
287         }
288
289         if (auth_ctx == NULL) {
290                 DEBUG(0, ("Cannot generate a session_info without the auth_context\n"));
291                 return NT_STATUS_INTERNAL_ERROR;
292         }
293
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;
297         }
298
299         if (gensec_security->want_features & GENSEC_FEATURE_UNIX_TOKEN) {
300                 session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
301         }
302
303         session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
304
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;
314         }
315
316         *psession_info = session_info;
317         return NT_STATUS_OK;
318 }
319
320 /* We have no features */
321 static bool gensec_ncalrpc_have_feature(struct gensec_security *gensec_security,
322                                  uint32_t feature)
323 {
324         if (feature & GENSEC_FEATURE_DCE_STYLE) {
325                 return true;
326         }
327
328         return false;
329 }
330
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,
342 };
343
344 _PUBLIC_ NTSTATUS gensec_ncalrpc_as_system_init(TALLOC_CTX *ctx)
345 {
346         NTSTATUS status;
347
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;
353         }
354
355         return status;
356 }