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/>.
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"
33 _PUBLIC_ NTSTATUS
gensec_ncalrpc_as_system_init(TALLOC_CTX
*ctx
);
35 struct gensec_ncalrpc_state
{
43 struct auth_user_info_dc
*user_info_dc
;
46 static NTSTATUS
gensec_ncalrpc_client_start(struct gensec_security
*gensec_security
)
48 struct gensec_ncalrpc_state
*state
;
50 state
= talloc_zero(gensec_security
,
51 struct gensec_ncalrpc_state
);
53 return NT_STATUS_NO_MEMORY
;
55 gensec_security
->private_data
= state
;
57 state
->step
= GENSEC_NCALRPC_START
;
61 static NTSTATUS
gensec_ncalrpc_server_start(struct gensec_security
*gensec_security
)
63 struct gensec_ncalrpc_state
*state
;
65 state
= talloc_zero(gensec_security
,
66 struct gensec_ncalrpc_state
);
68 return NT_STATUS_NO_MEMORY
;
70 gensec_security
->private_data
= state
;
72 state
->step
= GENSEC_NCALRPC_START
;
76 struct gensec_ncalrpc_update_state
{
81 static NTSTATUS
gensec_ncalrpc_update_internal(
82 struct gensec_security
*gensec_security
,
87 static struct tevent_req
*gensec_ncalrpc_update_send(TALLOC_CTX
*mem_ctx
,
88 struct tevent_context
*ev
,
89 struct gensec_security
*gensec_security
,
92 struct tevent_req
*req
;
93 struct gensec_ncalrpc_update_state
*state
= NULL
;
96 req
= tevent_req_create(mem_ctx
, &state
,
97 struct gensec_ncalrpc_update_state
);
102 status
= gensec_ncalrpc_update_internal(gensec_security
,
105 state
->status
= status
;
106 if (NT_STATUS_EQUAL(status
, NT_STATUS_MORE_PROCESSING_REQUIRED
)) {
107 status
= NT_STATUS_OK
;
109 if (tevent_req_nterror(req
, status
)) {
110 return tevent_req_post(req
, ev
);
113 tevent_req_done(req
);
114 return tevent_req_post(req
, ev
);
117 static NTSTATUS
gensec_ncalrpc_update_internal(
118 struct gensec_security
*gensec_security
,
123 struct gensec_ncalrpc_state
*state
=
124 talloc_get_type_abort(gensec_security
->private_data
,
125 struct gensec_ncalrpc_state
);
126 DATA_BLOB magic_req
= data_blob_string_const("NCALRPC_AUTH_TOKEN");
127 DATA_BLOB magic_ok
= data_blob_string_const("NCALRPC_AUTH_OK");
128 DATA_BLOB magic_fail
= data_blob_string_const("NCALRPC_AUTH_FAIL");
129 char *unix_path
= NULL
;
133 *out
= data_blob_null
;
135 if (state
->step
>= GENSEC_NCALRPC_DONE
) {
136 return NT_STATUS_INVALID_PARAMETER
;
139 switch (gensec_security
->gensec_role
) {
141 switch (state
->step
) {
142 case GENSEC_NCALRPC_START
:
143 *out
= data_blob_dup_talloc(mem_ctx
, magic_req
);
144 if (out
->data
== NULL
) {
145 state
->step
= GENSEC_NCALRPC_ERROR
;
146 return NT_STATUS_NO_MEMORY
;
149 state
->step
= GENSEC_NCALRPC_MORE
;
150 return NT_STATUS_MORE_PROCESSING_REQUIRED
;
152 case GENSEC_NCALRPC_MORE
:
153 cmp
= data_blob_cmp(&in
, &magic_ok
);
155 state
->step
= GENSEC_NCALRPC_ERROR
;
156 return NT_STATUS_LOGON_FAILURE
;
159 state
->step
= GENSEC_NCALRPC_DONE
;
162 case GENSEC_NCALRPC_DONE
:
163 case GENSEC_NCALRPC_ERROR
:
167 state
->step
= GENSEC_NCALRPC_ERROR
;
168 return NT_STATUS_INTERNAL_ERROR
;
171 if (state
->step
!= GENSEC_NCALRPC_START
) {
172 state
->step
= GENSEC_NCALRPC_ERROR
;
173 return NT_STATUS_INTERNAL_ERROR
;
176 cmp
= data_blob_cmp(&in
, &magic_req
);
178 state
->step
= GENSEC_NCALRPC_ERROR
;
179 *out
= data_blob_dup_talloc(mem_ctx
, magic_fail
);
180 if (out
->data
== NULL
) {
181 return NT_STATUS_NO_MEMORY
;
183 return NT_STATUS_LOGON_FAILURE
;
186 if (gensec_security
->remote_addr
== NULL
) {
187 state
->step
= GENSEC_NCALRPC_ERROR
;
188 *out
= data_blob_dup_talloc(mem_ctx
, magic_fail
);
189 if (out
->data
== NULL
) {
190 return NT_STATUS_NO_MEMORY
;
192 return NT_STATUS_LOGON_FAILURE
;
195 unix_path
= tsocket_address_unix_path(gensec_security
->remote_addr
,
197 if (unix_path
== NULL
) {
198 state
->step
= GENSEC_NCALRPC_ERROR
;
199 *out
= data_blob_dup_talloc(mem_ctx
, magic_fail
);
200 if (out
->data
== NULL
) {
201 return NT_STATUS_NO_MEMORY
;
203 return NT_STATUS_LOGON_FAILURE
;
206 cmp
= strcmp(unix_path
, "/root/ncalrpc_as_system");
207 TALLOC_FREE(unix_path
);
209 state
->step
= GENSEC_NCALRPC_ERROR
;
210 *out
= data_blob_dup_talloc(mem_ctx
, magic_fail
);
211 if (out
->data
== NULL
) {
212 return NT_STATUS_NO_MEMORY
;
214 return NT_STATUS_LOGON_FAILURE
;
217 status
= auth_system_user_info_dc(state
,
218 lpcfg_netbios_name(gensec_security
->settings
->lp_ctx
),
219 &state
->user_info_dc
);
220 if (!NT_STATUS_IS_OK(status
)) {
221 state
->step
= GENSEC_NCALRPC_ERROR
;
222 *out
= data_blob_dup_talloc(mem_ctx
, magic_fail
);
223 if (out
->data
== NULL
) {
224 return NT_STATUS_NO_MEMORY
;
229 *out
= data_blob_dup_talloc(mem_ctx
, magic_ok
);
230 if (out
->data
== NULL
) {
231 state
->step
= GENSEC_NCALRPC_ERROR
;
232 return NT_STATUS_NO_MEMORY
;
235 state
->step
= GENSEC_NCALRPC_DONE
;
239 state
->step
= GENSEC_NCALRPC_ERROR
;
240 return NT_STATUS_INTERNAL_ERROR
;
243 static NTSTATUS
gensec_ncalrpc_update_recv(struct tevent_req
*req
,
244 TALLOC_CTX
*out_mem_ctx
,
247 struct gensec_ncalrpc_update_state
*state
=
249 struct gensec_ncalrpc_update_state
);
252 *out
= data_blob_null
;
254 if (tevent_req_is_nterror(req
, &status
)) {
255 tevent_req_received(req
);
259 status
= state
->status
;
260 talloc_steal(out_mem_ctx
, state
->out
.data
);
262 tevent_req_received(req
);
266 static NTSTATUS
gensec_ncalrpc_session_info(struct gensec_security
*gensec_security
,
268 struct auth_session_info
**psession_info
)
270 struct gensec_ncalrpc_state
*state
=
271 talloc_get_type_abort(gensec_security
->private_data
,
272 struct gensec_ncalrpc_state
);
273 struct auth4_context
*auth_ctx
= gensec_security
->auth_context
;
274 struct auth_session_info
*session_info
= NULL
;
275 uint32_t session_info_flags
= 0;
278 if (gensec_security
->gensec_role
!= GENSEC_SERVER
) {
279 return NT_STATUS_INVALID_PARAMETER
;
282 if (state
->step
!= GENSEC_NCALRPC_DONE
) {
283 return NT_STATUS_INVALID_PARAMETER
;
286 if (auth_ctx
== NULL
) {
287 DEBUG(0, ("Cannot generate a session_info without the auth_context\n"));
288 return NT_STATUS_INTERNAL_ERROR
;
291 if (auth_ctx
->generate_session_info
== NULL
) {
292 DEBUG(0, ("Cannot generate a session_info without the generate_session_info hook\n"));
293 return NT_STATUS_INTERNAL_ERROR
;
296 if (gensec_security
->want_features
& GENSEC_FEATURE_UNIX_TOKEN
) {
297 session_info_flags
|= AUTH_SESSION_INFO_UNIX_TOKEN
;
300 session_info_flags
|= AUTH_SESSION_INFO_SIMPLE_PRIVILEGES
;
302 status
= auth_ctx
->generate_session_info(
306 state
->user_info_dc
->info
->account_name
,
309 if (!NT_STATUS_IS_OK(status
)) {
313 *psession_info
= session_info
;
317 /* We have no features */
318 static bool gensec_ncalrpc_have_feature(struct gensec_security
*gensec_security
,
321 if (feature
& GENSEC_FEATURE_DCE_STYLE
) {
328 static const struct gensec_security_ops gensec_ncalrpc_security_ops
= {
329 .name
= "naclrpc_as_system",
330 .auth_type
= DCERPC_AUTH_TYPE_NCALRPC_AS_SYSTEM
,
331 .client_start
= gensec_ncalrpc_client_start
,
332 .server_start
= gensec_ncalrpc_server_start
,
333 .update_send
= gensec_ncalrpc_update_send
,
334 .update_recv
= gensec_ncalrpc_update_recv
,
335 .session_info
= gensec_ncalrpc_session_info
,
336 .have_feature
= gensec_ncalrpc_have_feature
,
338 .priority
= GENSEC_EXTERNAL
,
341 _PUBLIC_ NTSTATUS
gensec_ncalrpc_as_system_init(TALLOC_CTX
*ctx
)
345 status
= gensec_register(ctx
, &gensec_ncalrpc_security_ops
);
346 if (!NT_STATUS_IS_OK(status
)) {
347 DEBUG(0, ("Failed to register '%s' gensec backend!\n",
348 gensec_ncalrpc_security_ops
.name
));