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"
34 #define DBGC_CLASS DBGC_AUTH
36 _PUBLIC_ NTSTATUS
gensec_ncalrpc_as_system_init(TALLOC_CTX
*ctx
);
38 struct gensec_ncalrpc_state
{
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
);
56 return NT_STATUS_NO_MEMORY
;
58 gensec_security
->private_data
= state
;
60 state
->step
= GENSEC_NCALRPC_START
;
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
);
71 return NT_STATUS_NO_MEMORY
;
73 gensec_security
->private_data
= state
;
75 state
->step
= GENSEC_NCALRPC_START
;
79 struct gensec_ncalrpc_update_state
{
84 static NTSTATUS
gensec_ncalrpc_update_internal(
85 struct gensec_security
*gensec_security
,
90 static struct tevent_req
*gensec_ncalrpc_update_send(TALLOC_CTX
*mem_ctx
,
91 struct tevent_context
*ev
,
92 struct gensec_security
*gensec_security
,
95 struct tevent_req
*req
;
96 struct gensec_ncalrpc_update_state
*state
= NULL
;
99 req
= tevent_req_create(mem_ctx
, &state
,
100 struct gensec_ncalrpc_update_state
);
105 status
= gensec_ncalrpc_update_internal(gensec_security
,
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
,
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
;
136 *out
= data_blob_null
;
138 if (state
->step
>= GENSEC_NCALRPC_DONE
) {
139 return NT_STATUS_INVALID_PARAMETER
;
142 switch (gensec_security
->gensec_role
) {
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
);
158 state
->step
= GENSEC_NCALRPC_ERROR
;
159 return NT_STATUS_LOGON_FAILURE
;
162 state
->step
= GENSEC_NCALRPC_DONE
;
165 case GENSEC_NCALRPC_DONE
:
166 case GENSEC_NCALRPC_ERROR
:
170 state
->step
= GENSEC_NCALRPC_ERROR
;
171 return NT_STATUS_INTERNAL_ERROR
;
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
);
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
,
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
);
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
;
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
;
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
,
250 struct gensec_ncalrpc_update_state
*state
=
252 struct gensec_ncalrpc_update_state
);
255 *out
= data_blob_null
;
257 if (tevent_req_is_nterror(req
, &status
)) {
258 tevent_req_received(req
);
262 status
= state
->status
;
263 talloc_steal(out_mem_ctx
, state
->out
.data
);
265 tevent_req_received(req
);
269 static NTSTATUS
gensec_ncalrpc_session_info(struct gensec_security
*gensec_security
,
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;
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(
309 state
->user_info_dc
->info
->account_name
,
312 if (!NT_STATUS_IS_OK(status
)) {
316 *psession_info
= session_info
;
320 /* We have no features */
321 static bool gensec_ncalrpc_have_feature(struct gensec_security
*gensec_security
,
324 if (feature
& GENSEC_FEATURE_DCE_STYLE
) {
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
,
341 .priority
= GENSEC_EXTERNAL
,
344 _PUBLIC_ NTSTATUS
gensec_ncalrpc_as_system_init(TALLOC_CTX
*ctx
)
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
));