Line data Source code
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 572 : static NTSTATUS gensec_ncalrpc_client_start(struct gensec_security *gensec_security)
50 : {
51 8 : struct gensec_ncalrpc_state *state;
52 :
53 572 : state = talloc_zero(gensec_security,
54 : struct gensec_ncalrpc_state);
55 572 : if (state == NULL) {
56 0 : return NT_STATUS_NO_MEMORY;
57 : }
58 572 : gensec_security->private_data = state;
59 :
60 572 : state->step = GENSEC_NCALRPC_START;
61 572 : return NT_STATUS_OK;
62 : }
63 :
64 571 : static NTSTATUS gensec_ncalrpc_server_start(struct gensec_security *gensec_security)
65 : {
66 8 : struct gensec_ncalrpc_state *state;
67 :
68 571 : state = talloc_zero(gensec_security,
69 : struct gensec_ncalrpc_state);
70 571 : if (state == NULL) {
71 0 : return NT_STATUS_NO_MEMORY;
72 : }
73 571 : gensec_security->private_data = state;
74 :
75 571 : state->step = GENSEC_NCALRPC_START;
76 571 : 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 1715 : 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 24 : struct tevent_req *req;
96 1715 : struct gensec_ncalrpc_update_state *state = NULL;
97 24 : NTSTATUS status;
98 :
99 1715 : req = tevent_req_create(mem_ctx, &state,
100 : struct gensec_ncalrpc_update_state);
101 1715 : if (req == NULL) {
102 0 : return NULL;
103 : }
104 :
105 1739 : status = gensec_ncalrpc_update_internal(gensec_security,
106 : state, in,
107 1715 : &state->out);
108 1715 : state->status = status;
109 1715 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
110 572 : status = NT_STATUS_OK;
111 : }
112 1715 : if (tevent_req_nterror(req, status)) {
113 0 : return tevent_req_post(req, ev);
114 : }
115 :
116 1715 : tevent_req_done(req);
117 1715 : return tevent_req_post(req, ev);
118 : }
119 :
120 1715 : 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 24 : struct gensec_ncalrpc_state *state =
127 1715 : talloc_get_type_abort(gensec_security->private_data,
128 : struct gensec_ncalrpc_state);
129 1715 : DATA_BLOB magic_req = data_blob_string_const("NCALRPC_AUTH_TOKEN");
130 1715 : DATA_BLOB magic_ok = data_blob_string_const("NCALRPC_AUTH_OK");
131 1715 : DATA_BLOB magic_fail = data_blob_string_const("NCALRPC_AUTH_FAIL");
132 1715 : char *unix_path = NULL;
133 24 : int cmp;
134 24 : NTSTATUS status;
135 :
136 1715 : *out = data_blob_null;
137 :
138 1715 : if (state->step >= GENSEC_NCALRPC_DONE) {
139 0 : return NT_STATUS_INVALID_PARAMETER;
140 : }
141 :
142 1715 : switch (gensec_security->gensec_role) {
143 1144 : case GENSEC_CLIENT:
144 1144 : switch (state->step) {
145 572 : case GENSEC_NCALRPC_START:
146 572 : *out = data_blob_dup_talloc(mem_ctx, magic_req);
147 572 : if (out->data == NULL) {
148 0 : state->step = GENSEC_NCALRPC_ERROR;
149 0 : return NT_STATUS_NO_MEMORY;
150 : }
151 :
152 572 : state->step = GENSEC_NCALRPC_MORE;
153 572 : return NT_STATUS_MORE_PROCESSING_REQUIRED;
154 :
155 572 : case GENSEC_NCALRPC_MORE:
156 572 : cmp = data_blob_cmp(&in, &magic_ok);
157 572 : if (cmp != 0) {
158 0 : state->step = GENSEC_NCALRPC_ERROR;
159 0 : return NT_STATUS_LOGON_FAILURE;
160 : }
161 :
162 572 : state->step = GENSEC_NCALRPC_DONE;
163 572 : return NT_STATUS_OK;
164 :
165 0 : case GENSEC_NCALRPC_DONE:
166 : case GENSEC_NCALRPC_ERROR:
167 0 : break;
168 : }
169 :
170 0 : state->step = GENSEC_NCALRPC_ERROR;
171 0 : return NT_STATUS_INTERNAL_ERROR;
172 :
173 571 : case GENSEC_SERVER:
174 571 : if (state->step != GENSEC_NCALRPC_START) {
175 0 : state->step = GENSEC_NCALRPC_ERROR;
176 0 : return NT_STATUS_INTERNAL_ERROR;
177 : }
178 :
179 571 : cmp = data_blob_cmp(&in, &magic_req);
180 571 : if (cmp != 0) {
181 0 : state->step = GENSEC_NCALRPC_ERROR;
182 0 : *out = data_blob_dup_talloc(mem_ctx, magic_fail);
183 0 : if (out->data == NULL) {
184 0 : return NT_STATUS_NO_MEMORY;
185 : }
186 0 : return NT_STATUS_LOGON_FAILURE;
187 : }
188 :
189 571 : if (gensec_security->remote_addr == NULL) {
190 0 : state->step = GENSEC_NCALRPC_ERROR;
191 0 : *out = data_blob_dup_talloc(mem_ctx, magic_fail);
192 0 : if (out->data == NULL) {
193 0 : return NT_STATUS_NO_MEMORY;
194 : }
195 0 : return NT_STATUS_LOGON_FAILURE;
196 : }
197 :
198 571 : unix_path = tsocket_address_unix_path(gensec_security->remote_addr,
199 : state);
200 571 : if (unix_path == NULL) {
201 0 : state->step = GENSEC_NCALRPC_ERROR;
202 0 : *out = data_blob_dup_talloc(mem_ctx, magic_fail);
203 0 : if (out->data == NULL) {
204 0 : return NT_STATUS_NO_MEMORY;
205 : }
206 0 : return NT_STATUS_LOGON_FAILURE;
207 : }
208 :
209 571 : cmp = strcmp(unix_path, AS_SYSTEM_MAGIC_PATH_TOKEN);
210 571 : TALLOC_FREE(unix_path);
211 571 : if (cmp != 0) {
212 0 : state->step = GENSEC_NCALRPC_ERROR;
213 0 : *out = data_blob_dup_talloc(mem_ctx, magic_fail);
214 0 : if (out->data == NULL) {
215 0 : return NT_STATUS_NO_MEMORY;
216 : }
217 0 : return NT_STATUS_LOGON_FAILURE;
218 : }
219 :
220 571 : status = auth_system_user_info_dc(state,
221 571 : lpcfg_netbios_name(gensec_security->settings->lp_ctx),
222 : &state->user_info_dc);
223 571 : if (!NT_STATUS_IS_OK(status)) {
224 0 : state->step = GENSEC_NCALRPC_ERROR;
225 0 : *out = data_blob_dup_talloc(mem_ctx, magic_fail);
226 0 : if (out->data == NULL) {
227 0 : return NT_STATUS_NO_MEMORY;
228 : }
229 0 : return status;
230 : }
231 :
232 571 : *out = data_blob_dup_talloc(mem_ctx, magic_ok);
233 571 : if (out->data == NULL) {
234 0 : state->step = GENSEC_NCALRPC_ERROR;
235 0 : return NT_STATUS_NO_MEMORY;
236 : }
237 :
238 571 : state->step = GENSEC_NCALRPC_DONE;
239 571 : return NT_STATUS_OK;
240 : }
241 :
242 0 : state->step = GENSEC_NCALRPC_ERROR;
243 0 : return NT_STATUS_INTERNAL_ERROR;
244 : }
245 :
246 1715 : static NTSTATUS gensec_ncalrpc_update_recv(struct tevent_req *req,
247 : TALLOC_CTX *out_mem_ctx,
248 : DATA_BLOB *out)
249 : {
250 24 : struct gensec_ncalrpc_update_state *state =
251 1715 : tevent_req_data(req,
252 : struct gensec_ncalrpc_update_state);
253 24 : NTSTATUS status;
254 :
255 1715 : *out = data_blob_null;
256 :
257 1715 : if (tevent_req_is_nterror(req, &status)) {
258 0 : tevent_req_received(req);
259 0 : return status;
260 : }
261 :
262 1715 : status = state->status;
263 1715 : talloc_steal(out_mem_ctx, state->out.data);
264 1715 : *out = state->out;
265 1715 : tevent_req_received(req);
266 1715 : return status;
267 : }
268 :
269 571 : 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 8 : struct gensec_ncalrpc_state *state =
274 571 : talloc_get_type_abort(gensec_security->private_data,
275 : struct gensec_ncalrpc_state);
276 571 : struct auth4_context *auth_ctx = gensec_security->auth_context;
277 571 : struct auth_session_info *session_info = NULL;
278 571 : uint32_t session_info_flags = 0;
279 8 : NTSTATUS status;
280 :
281 571 : if (gensec_security->gensec_role != GENSEC_SERVER) {
282 0 : return NT_STATUS_INVALID_PARAMETER;
283 : }
284 :
285 571 : if (state->step != GENSEC_NCALRPC_DONE) {
286 0 : return NT_STATUS_INVALID_PARAMETER;
287 : }
288 :
289 571 : if (auth_ctx == NULL) {
290 0 : DEBUG(0, ("Cannot generate a session_info without the auth_context\n"));
291 0 : return NT_STATUS_INTERNAL_ERROR;
292 : }
293 :
294 571 : if (auth_ctx->generate_session_info == NULL) {
295 0 : DEBUG(0, ("Cannot generate a session_info without the generate_session_info hook\n"));
296 0 : return NT_STATUS_INTERNAL_ERROR;
297 : }
298 :
299 571 : if (gensec_security->want_features & GENSEC_FEATURE_UNIX_TOKEN) {
300 0 : session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
301 : }
302 :
303 571 : session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
304 :
305 571 : status = auth_ctx->generate_session_info(
306 : auth_ctx,
307 : mem_ctx,
308 563 : state->user_info_dc,
309 571 : state->user_info_dc->info->account_name,
310 : session_info_flags,
311 : &session_info);
312 571 : if (!NT_STATUS_IS_OK(status)) {
313 0 : return status;
314 : }
315 :
316 571 : *psession_info = session_info;
317 571 : return NT_STATUS_OK;
318 : }
319 :
320 : /* We have no features */
321 2639 : static bool gensec_ncalrpc_have_feature(struct gensec_security *gensec_security,
322 : uint32_t feature)
323 : {
324 2639 : if (feature & GENSEC_FEATURE_DCE_STYLE) {
325 0 : return true;
326 : }
327 :
328 2601 : return false;
329 : }
330 :
331 : static const struct gensec_security_ops gensec_ncalrpc_security_ops = {
332 : .name = "ncalrpc_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 51498 : _PUBLIC_ NTSTATUS gensec_ncalrpc_as_system_init(TALLOC_CTX *ctx)
345 : {
346 1174 : NTSTATUS status;
347 :
348 51498 : status = gensec_register(ctx, &gensec_ncalrpc_security_ops);
349 51498 : if (!NT_STATUS_IS_OK(status)) {
350 0 : DEBUG(0, ("Failed to register '%s' gensec backend!\n",
351 : gensec_ncalrpc_security_ops.name));
352 0 : return status;
353 : }
354 :
355 51498 : return status;
356 : }
|