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 576 : static NTSTATUS gensec_ncalrpc_client_start(struct gensec_security *gensec_security)
50 : {
51 8 : struct gensec_ncalrpc_state *state;
52 :
53 576 : state = talloc_zero(gensec_security,
54 : struct gensec_ncalrpc_state);
55 576 : if (state == NULL) {
56 0 : return NT_STATUS_NO_MEMORY;
57 : }
58 576 : gensec_security->private_data = state;
59 :
60 576 : state->step = GENSEC_NCALRPC_START;
61 576 : return NT_STATUS_OK;
62 : }
63 :
64 575 : static NTSTATUS gensec_ncalrpc_server_start(struct gensec_security *gensec_security)
65 : {
66 8 : struct gensec_ncalrpc_state *state;
67 :
68 575 : state = talloc_zero(gensec_security,
69 : struct gensec_ncalrpc_state);
70 575 : if (state == NULL) {
71 0 : return NT_STATUS_NO_MEMORY;
72 : }
73 575 : gensec_security->private_data = state;
74 :
75 575 : state->step = GENSEC_NCALRPC_START;
76 575 : 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 1727 : 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 1727 : struct gensec_ncalrpc_update_state *state = NULL;
97 24 : NTSTATUS status;
98 :
99 1727 : req = tevent_req_create(mem_ctx, &state,
100 : struct gensec_ncalrpc_update_state);
101 1727 : if (req == NULL) {
102 0 : return NULL;
103 : }
104 :
105 1751 : status = gensec_ncalrpc_update_internal(gensec_security,
106 : state, in,
107 1727 : &state->out);
108 1727 : state->status = status;
109 1727 : if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
110 576 : status = NT_STATUS_OK;
111 : }
112 1727 : if (tevent_req_nterror(req, status)) {
113 0 : return tevent_req_post(req, ev);
114 : }
115 :
116 1727 : tevent_req_done(req);
117 1727 : return tevent_req_post(req, ev);
118 : }
119 :
120 1727 : 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 1727 : talloc_get_type_abort(gensec_security->private_data,
128 : struct gensec_ncalrpc_state);
129 1727 : DATA_BLOB magic_req = data_blob_string_const("NCALRPC_AUTH_TOKEN");
130 1727 : DATA_BLOB magic_ok = data_blob_string_const("NCALRPC_AUTH_OK");
131 1727 : DATA_BLOB magic_fail = data_blob_string_const("NCALRPC_AUTH_FAIL");
132 1727 : char *unix_path = NULL;
133 24 : int cmp;
134 24 : NTSTATUS status;
135 :
136 1727 : *out = data_blob_null;
137 :
138 1727 : if (state->step >= GENSEC_NCALRPC_DONE) {
139 0 : return NT_STATUS_INVALID_PARAMETER;
140 : }
141 :
142 1727 : switch (gensec_security->gensec_role) {
143 1152 : case GENSEC_CLIENT:
144 1152 : switch (state->step) {
145 576 : case GENSEC_NCALRPC_START:
146 576 : *out = data_blob_dup_talloc(mem_ctx, magic_req);
147 576 : if (out->data == NULL) {
148 0 : state->step = GENSEC_NCALRPC_ERROR;
149 0 : return NT_STATUS_NO_MEMORY;
150 : }
151 :
152 576 : state->step = GENSEC_NCALRPC_MORE;
153 576 : return NT_STATUS_MORE_PROCESSING_REQUIRED;
154 :
155 576 : case GENSEC_NCALRPC_MORE:
156 576 : cmp = data_blob_cmp(&in, &magic_ok);
157 576 : if (cmp != 0) {
158 0 : state->step = GENSEC_NCALRPC_ERROR;
159 0 : return NT_STATUS_LOGON_FAILURE;
160 : }
161 :
162 576 : state->step = GENSEC_NCALRPC_DONE;
163 576 : 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 575 : case GENSEC_SERVER:
174 575 : if (state->step != GENSEC_NCALRPC_START) {
175 0 : state->step = GENSEC_NCALRPC_ERROR;
176 0 : return NT_STATUS_INTERNAL_ERROR;
177 : }
178 :
179 575 : cmp = data_blob_cmp(&in, &magic_req);
180 575 : 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 575 : 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 575 : unix_path = tsocket_address_unix_path(gensec_security->remote_addr,
199 : state);
200 575 : 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 575 : cmp = strcmp(unix_path, AS_SYSTEM_MAGIC_PATH_TOKEN);
210 575 : TALLOC_FREE(unix_path);
211 575 : 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 575 : status = auth_system_user_info_dc(state,
221 575 : lpcfg_netbios_name(gensec_security->settings->lp_ctx),
222 : &state->user_info_dc);
223 575 : 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 575 : *out = data_blob_dup_talloc(mem_ctx, magic_ok);
233 575 : if (out->data == NULL) {
234 0 : state->step = GENSEC_NCALRPC_ERROR;
235 0 : return NT_STATUS_NO_MEMORY;
236 : }
237 :
238 575 : state->step = GENSEC_NCALRPC_DONE;
239 575 : return NT_STATUS_OK;
240 : }
241 :
242 0 : state->step = GENSEC_NCALRPC_ERROR;
243 0 : return NT_STATUS_INTERNAL_ERROR;
244 : }
245 :
246 1727 : 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 1727 : tevent_req_data(req,
252 : struct gensec_ncalrpc_update_state);
253 24 : NTSTATUS status;
254 :
255 1727 : *out = data_blob_null;
256 :
257 1727 : if (tevent_req_is_nterror(req, &status)) {
258 0 : tevent_req_received(req);
259 0 : return status;
260 : }
261 :
262 1727 : status = state->status;
263 1727 : talloc_steal(out_mem_ctx, state->out.data);
264 1727 : *out = state->out;
265 1727 : tevent_req_received(req);
266 1727 : return status;
267 : }
268 :
269 575 : 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 575 : talloc_get_type_abort(gensec_security->private_data,
275 : struct gensec_ncalrpc_state);
276 575 : struct auth4_context *auth_ctx = gensec_security->auth_context;
277 575 : struct auth_session_info *session_info = NULL;
278 575 : uint32_t session_info_flags = 0;
279 8 : NTSTATUS status;
280 :
281 575 : if (gensec_security->gensec_role != GENSEC_SERVER) {
282 0 : return NT_STATUS_INVALID_PARAMETER;
283 : }
284 :
285 575 : if (state->step != GENSEC_NCALRPC_DONE) {
286 0 : return NT_STATUS_INVALID_PARAMETER;
287 : }
288 :
289 575 : 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 575 : 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 575 : if (gensec_security->want_features & GENSEC_FEATURE_UNIX_TOKEN) {
300 0 : session_info_flags |= AUTH_SESSION_INFO_UNIX_TOKEN;
301 : }
302 :
303 575 : session_info_flags |= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES;
304 :
305 575 : status = auth_ctx->generate_session_info(
306 : auth_ctx,
307 : mem_ctx,
308 567 : state->user_info_dc,
309 575 : state->user_info_dc->info->account_name,
310 : session_info_flags,
311 : &session_info);
312 575 : if (!NT_STATUS_IS_OK(status)) {
313 0 : return status;
314 : }
315 :
316 575 : *psession_info = session_info;
317 575 : return NT_STATUS_OK;
318 : }
319 :
320 : /* We have no features */
321 2651 : static bool gensec_ncalrpc_have_feature(struct gensec_security *gensec_security,
322 : uint32_t feature)
323 : {
324 2651 : if (feature & GENSEC_FEATURE_DCE_STYLE) {
325 0 : return true;
326 : }
327 :
328 2613 : 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 52291 : _PUBLIC_ NTSTATUS gensec_ncalrpc_as_system_init(TALLOC_CTX *ctx)
345 : {
346 1208 : NTSTATUS status;
347 :
348 52291 : status = gensec_register(ctx, &gensec_ncalrpc_security_ops);
349 52291 : 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 52291 : return status;
356 : }
|