s4:rpc_server: split out log_successful_dcesrv_authz_event()
[samba.git] / source4 / rpc_server / dcesrv_auth.c
1 /* 
2    Unix SMB/CIFS implementation.
3
4    server side dcerpc authentication code
5
6    Copyright (C) Andrew Tridgell 2003
7    Copyright (C) Stefan (metze) Metzmacher 2004
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 "rpc_server/dcerpc_server.h"
25 #include "rpc_server/dcerpc_server_proto.h"
26 #include "rpc_server/common/proto.h"
27 #include "librpc/rpc/dcerpc_proto.h"
28 #include "librpc/gen_ndr/ndr_dcerpc.h"
29 #include "auth/credentials/credentials.h"
30 #include "auth/gensec/gensec.h"
31 #include "auth/auth.h"
32 #include "param/param.h"
33 #include "librpc/rpc/rpc_common.h"
34
35 static bool dcesrv_auth_prepare_gensec(struct dcesrv_call_state *call)
36 {
37         struct cli_credentials *server_credentials = NULL;
38         struct dcesrv_connection *dce_conn = call->conn;
39         struct dcesrv_auth *auth = call->auth_state;
40         bool want_header_signing = false;
41         NTSTATUS status;
42
43         if (auth->auth_invalid) {
44                 return false;
45         }
46
47         if (auth->auth_finished) {
48                 return false;
49         }
50
51         if (auth->gensec_security != NULL) {
52                 return false;
53         }
54
55         switch (call->in_auth_info.auth_level) {
56         case DCERPC_AUTH_LEVEL_CONNECT:
57         case DCERPC_AUTH_LEVEL_CALL:
58         case DCERPC_AUTH_LEVEL_PACKET:
59         case DCERPC_AUTH_LEVEL_INTEGRITY:
60         case DCERPC_AUTH_LEVEL_PRIVACY:
61                 /*
62                  * We evaluate auth_type only if auth_level was valid
63                  */
64                 break;
65         default:
66                 /*
67                  * Setting DCERPC_AUTH_LEVEL_NONE,
68                  * gives the caller the reject_reason
69                  * as auth_context_id.
70                  *
71                  * Note: DCERPC_AUTH_LEVEL_NONE == 1
72                  */
73                 auth->auth_type = DCERPC_AUTH_TYPE_NONE;
74                 auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
75                 auth->auth_context_id = DCERPC_BIND_NAK_REASON_NOT_SPECIFIED;
76                 return false;
77         }
78
79         auth->auth_type = call->in_auth_info.auth_type;
80         auth->auth_level = call->in_auth_info.auth_level;
81         auth->auth_context_id = call->in_auth_info.auth_context_id;
82
83         server_credentials 
84                 = cli_credentials_init(auth);
85         if (!server_credentials) {
86                 DEBUG(1, ("Failed to init server credentials\n"));
87                 return false;
88         }
89         
90         cli_credentials_set_conf(server_credentials, call->conn->dce_ctx->lp_ctx);
91         status = cli_credentials_set_machine_account(server_credentials, call->conn->dce_ctx->lp_ctx);
92         if (!NT_STATUS_IS_OK(status)) {
93                 DEBUG(1, ("Failed to obtain server credentials: %s\n",
94                           nt_errstr(status)));
95                 return false;
96         }
97
98         status = samba_server_gensec_start(auth,
99                                            call->event_ctx,
100                                            call->msg_ctx,
101                                            call->conn->dce_ctx->lp_ctx,
102                                            server_credentials,
103                                            NULL,
104                                            &auth->gensec_security);
105         if (!NT_STATUS_IS_OK(status)) {
106                 DEBUG(1, ("Failed to call samba_server_gensec_start %s\n",
107                           nt_errstr(status)));
108                 return false;
109         }
110
111         /*
112          * We have to call this because we set the target_service for
113          * Kerberos to NULL above, and in any case we wish to log a
114          * more specific service target.
115          *
116          */
117         status = gensec_set_target_service_description(auth->gensec_security,
118                                                        "DCE/RPC");
119         if (!NT_STATUS_IS_OK(status)) {
120                 DEBUG(1, ("Failed to call gensec_set_target_service_description %s\n",
121                           nt_errstr(status)));
122                 return false;
123         }
124
125         if (call->conn->remote_address != NULL) {
126                 status = gensec_set_remote_address(auth->gensec_security,
127                                                 call->conn->remote_address);
128                 if (!NT_STATUS_IS_OK(status)) {
129                         DEBUG(1, ("Failed to call gensec_set_remote_address() %s\n",
130                                   nt_errstr(status)));
131                         return false;
132                 }
133         }
134
135         if (call->conn->local_address != NULL) {
136                 status = gensec_set_local_address(auth->gensec_security,
137                                                   call->conn->local_address);
138                 if (!NT_STATUS_IS_OK(status)) {
139                         DEBUG(1, ("Failed to call gensec_set_local_address() %s\n",
140                                   nt_errstr(status)));
141                         return false;
142                 }
143         }
144
145         status = gensec_start_mech_by_authtype(auth->gensec_security, auth->auth_type,
146                                                auth->auth_level);
147         if (!NT_STATUS_IS_OK(status)) {
148                 const char *backend_name =
149                         gensec_get_name_by_authtype(auth->gensec_security,
150                                                     auth->auth_type);
151
152                 DEBUG(3, ("Failed to start GENSEC mechanism for DCERPC server: "
153                           "auth_type=%d (%s), auth_level=%d: %s\n",
154                           (int)auth->auth_type, backend_name,
155                           (int)auth->auth_level,
156                           nt_errstr(status)));
157
158                 /*
159                  * Setting DCERPC_AUTH_LEVEL_NONE,
160                  * gives the caller the reject_reason
161                  * as auth_context_id.
162                  *
163                  * Note: DCERPC_AUTH_LEVEL_NONE == 1
164                  */
165                 auth->auth_type = DCERPC_AUTH_TYPE_NONE;
166                 auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
167                 if (backend_name != NULL) {
168                         auth->auth_context_id =
169                                 DCERPC_BIND_NAK_REASON_INVALID_CHECKSUM;
170                 } else {
171                         auth->auth_context_id =
172                                 DCERPC_BIND_NAK_REASON_INVALID_AUTH_TYPE;
173                 }
174                 return false;
175         }
176
177         if (call->pkt.pfc_flags & DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN) {
178                 auth->client_hdr_signing = true;
179                 want_header_signing = true;
180         }
181
182         if (want_header_signing) {
183                 want_header_signing = gensec_have_feature(auth->gensec_security,
184                                                 GENSEC_FEATURE_SIGN_PKT_HEADER);
185         }
186
187         if (want_header_signing) {
188                 want_header_signing = lpcfg_parm_bool(dce_conn->dce_ctx->lp_ctx,
189                                                       NULL,
190                                                       "dcesrv",
191                                                       "header signing",
192                                                       true);
193         }
194
195         if (want_header_signing) {
196                 gensec_want_feature(auth->gensec_security,
197                                     GENSEC_FEATURE_SIGN_PKT_HEADER);
198                 auth->hdr_signing = true;
199         }
200
201         return true;
202 }
203
204 static void log_successful_dcesrv_authz_event(struct dcesrv_call_state *call)
205 {
206         struct dcesrv_auth *auth = call->auth_state;
207         enum dcerpc_transport_t transport =
208                 dcerpc_binding_get_transport(call->conn->endpoint->ep_description);
209         const char *auth_type = derpc_transport_string_by_transport(transport);
210         const char *transport_protection = AUTHZ_TRANSPORT_PROTECTION_NONE;
211
212         if (transport == NCACN_NP) {
213                 transport_protection = AUTHZ_TRANSPORT_PROTECTION_SMB;
214         }
215
216         /*
217          * Log the authorization to this RPC interface.  This
218          * covered ncacn_np pass-through auth, and anonymous
219          * DCE/RPC (eg epmapper, netlogon etc)
220          */
221         log_successful_authz_event(call->conn->msg_ctx,
222                                    call->conn->dce_ctx->lp_ctx,
223                                    call->conn->remote_address,
224                                    call->conn->local_address,
225                                    "DCE/RPC",
226                                    auth_type,
227                                    transport_protection,
228                                    auth->session_info);
229 }
230
231 /*
232   parse any auth information from a dcerpc bind request
233   return false if we can't handle the auth request for some
234   reason (in which case we send a bind_nak)
235 */
236 bool dcesrv_auth_bind(struct dcesrv_call_state *call)
237 {
238         struct ncacn_packet *pkt = &call->pkt;
239         struct dcesrv_auth *auth = call->auth_state;
240         NTSTATUS status;
241
242         if (pkt->auth_length == 0) {
243                 auth->auth_type = DCERPC_AUTH_TYPE_NONE;
244                 auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
245                 auth->auth_context_id = 0;
246
247                 log_successful_dcesrv_authz_event(call);
248
249                 return true;
250         }
251
252         status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.bind.auth_info,
253                                           &call->in_auth_info,
254                                           NULL, true);
255         if (!NT_STATUS_IS_OK(status)) {
256                 /*
257                  * Setting DCERPC_AUTH_LEVEL_NONE,
258                  * gives the caller the reject_reason
259                  * as auth_context_id.
260                  *
261                  * Note: DCERPC_AUTH_LEVEL_NONE == 1
262                  */
263                 auth->auth_type = DCERPC_AUTH_TYPE_NONE;
264                 auth->auth_level = DCERPC_AUTH_LEVEL_NONE;
265                 auth->auth_context_id =
266                         DCERPC_BIND_NAK_REASON_PROTOCOL_VERSION_NOT_SUPPORTED;
267                 return false;
268         }
269
270         return dcesrv_auth_prepare_gensec(call);
271 }
272
273 NTSTATUS dcesrv_auth_complete(struct dcesrv_call_state *call, NTSTATUS status)
274 {
275         struct dcesrv_connection *dce_conn = call->conn;
276         struct dcesrv_auth *auth = call->auth_state;
277         const char *pdu = "<unknown>";
278
279         switch (call->pkt.ptype) {
280         case DCERPC_PKT_BIND:
281                 pdu = "BIND";
282                 break;
283         case DCERPC_PKT_ALTER:
284                 pdu = "ALTER";
285                 break;
286         case DCERPC_PKT_AUTH3:
287                 pdu = "AUTH3";
288                 if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
289                         DEBUG(4, ("GENSEC not finished at at %s\n", pdu));
290                         return NT_STATUS_RPC_SEC_PKG_ERROR;
291                 }
292                 break;
293         default:
294                 return NT_STATUS_INTERNAL_ERROR;
295         }
296
297         if (NT_STATUS_EQUAL(status, NT_STATUS_MORE_PROCESSING_REQUIRED)) {
298                 return NT_STATUS_OK;
299         }
300
301         if (!NT_STATUS_IS_OK(status)) {
302                 DEBUG(4, ("GENSEC mech rejected the incoming authentication "
303                           "at %s: %s\n", pdu, nt_errstr(status)));
304                 return status;
305         }
306
307         status = gensec_session_info(auth->gensec_security,
308                                      auth,
309                                      &auth->session_info);
310         if (!NT_STATUS_IS_OK(status)) {
311                 DEBUG(1, ("Failed to establish session_info: %s\n",
312                           nt_errstr(status)));
313                 return status;
314         }
315         auth->auth_finished = true;
316         dce_conn->allow_request = true;
317
318         if (call->pkt.ptype != DCERPC_PKT_AUTH3) {
319                 return NT_STATUS_OK;
320         }
321
322         if (call->out_auth_info->credentials.length != 0) {
323                 DEBUG(4, ("GENSEC produced output token (len=%zu) at %s\n",
324                           call->out_auth_info->credentials.length, pdu));
325                 return NT_STATUS_RPC_SEC_PKG_ERROR;
326         }
327
328         return NT_STATUS_OK;
329 }
330
331 /*
332   add any auth information needed in a bind ack, and process the authentication
333   information found in the bind.
334 */
335 NTSTATUS dcesrv_auth_prepare_bind_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt)
336 {
337         struct dcesrv_connection *dce_conn = call->conn;
338         struct dcesrv_auth *auth = call->auth_state;
339
340         dce_conn->allow_alter = true;
341         dce_conn->allow_auth3 = true;
342
343         if (call->pkt.auth_length == 0) {
344                 auth->auth_finished = true;
345                 dce_conn->allow_request = true;
346                 return NT_STATUS_OK;
347         }
348
349         /* We can't work without an existing gensec state */
350         if (auth->gensec_security == NULL) {
351                 return NT_STATUS_INTERNAL_ERROR;
352         }
353
354         if (auth->hdr_signing) {
355                 pkt->pfc_flags |= DCERPC_PFC_FLAG_SUPPORT_HEADER_SIGN;
356         }
357
358         call->_out_auth_info = (struct dcerpc_auth) {
359                 .auth_type = auth->auth_type,
360                 .auth_level = auth->auth_level,
361                 .auth_context_id = auth->auth_context_id,
362         };
363         call->out_auth_info = &call->_out_auth_info;
364
365         return NT_STATUS_OK;
366 }
367
368 /*
369   process the final stage of a auth request
370 */
371 bool dcesrv_auth_prepare_auth3(struct dcesrv_call_state *call)
372 {
373         struct ncacn_packet *pkt = &call->pkt;
374         struct dcesrv_auth *auth = call->auth_state;
375         NTSTATUS status;
376
377         if (pkt->auth_length == 0) {
378                 return false;
379         }
380
381         if (auth->auth_finished) {
382                 return false;
383         }
384
385         /* We can't work without an existing gensec state */
386         if (auth->gensec_security == NULL) {
387                 return false;
388         }
389
390         status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.auth3.auth_info,
391                                           &call->in_auth_info, NULL, true);
392         if (!NT_STATUS_IS_OK(status)) {
393                 /*
394                  * Windows returns DCERPC_NCA_S_FAULT_REMOTE_NO_MEMORY
395                  * instead of DCERPC_NCA_S_PROTO_ERROR.
396                  */
397                 call->fault_code = DCERPC_NCA_S_FAULT_REMOTE_NO_MEMORY;
398                 return false;
399         }
400
401         if (call->in_auth_info.auth_type != auth->auth_type) {
402                 return false;
403         }
404
405         if (call->in_auth_info.auth_level != auth->auth_level) {
406                 return false;
407         }
408
409         if (call->in_auth_info.auth_context_id != auth->auth_context_id) {
410                 return false;
411         }
412
413         call->_out_auth_info = (struct dcerpc_auth) {
414                 .auth_type = auth->auth_type,
415                 .auth_level = auth->auth_level,
416                 .auth_context_id = auth->auth_context_id,
417         };
418         call->out_auth_info = &call->_out_auth_info;
419
420         return true;
421 }
422
423 /*
424   parse any auth information from a dcerpc alter request
425   return false if we can't handle the auth request for some 
426   reason (in which case we send a bind_nak (is this true for here?))
427 */
428 bool dcesrv_auth_alter(struct dcesrv_call_state *call)
429 {
430         struct ncacn_packet *pkt = &call->pkt;
431         struct dcesrv_auth *auth = call->auth_state;
432         NTSTATUS status;
433
434         /* on a pure interface change there is no auth blob */
435         if (pkt->auth_length == 0) {
436                 if (!auth->auth_finished) {
437                         return false;
438                 }
439                 return true;
440         }
441
442         if (auth->auth_finished) {
443                 call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
444                 return false;
445         }
446
447         /* We can't work without an existing gensec state */
448         if (auth->gensec_security == NULL) {
449                 return false;
450         }
451
452         status = dcerpc_pull_auth_trailer(pkt, call, &pkt->u.alter.auth_info,
453                                           &call->in_auth_info, NULL, true);
454         if (!NT_STATUS_IS_OK(status)) {
455                 call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
456                 return false;
457         }
458
459         if (call->in_auth_info.auth_type == DCERPC_AUTH_TYPE_NONE) {
460                 call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
461                 return false;
462         }
463
464         if (call->in_auth_info.auth_type != auth->auth_type) {
465                 return false;
466         }
467
468         if (call->in_auth_info.auth_level != auth->auth_level) {
469                 return false;
470         }
471
472         if (call->in_auth_info.auth_context_id != auth->auth_context_id) {
473                 return false;
474         }
475
476         return true;
477 }
478
479 /*
480   add any auth information needed in a alter ack, and process the authentication
481   information found in the alter.
482 */
483 NTSTATUS dcesrv_auth_prepare_alter_ack(struct dcesrv_call_state *call, struct ncacn_packet *pkt)
484 {
485         struct dcesrv_auth *auth = call->auth_state;
486
487         /* on a pure interface change there is no auth_info structure
488            setup */
489         if (call->pkt.auth_length == 0) {
490                 return NT_STATUS_OK;
491         }
492
493         if (auth->gensec_security == NULL) {
494                 return NT_STATUS_INTERNAL_ERROR;
495         }
496
497         call->_out_auth_info = (struct dcerpc_auth) {
498                 .auth_type = auth->auth_type,
499                 .auth_level = auth->auth_level,
500                 .auth_context_id = auth->auth_context_id,
501         };
502         call->out_auth_info = &call->_out_auth_info;
503
504         return NT_STATUS_OK;
505 }
506
507 /*
508   check credentials on a packet
509 */
510 bool dcesrv_auth_pkt_pull(struct dcesrv_call_state *call,
511                           DATA_BLOB *full_packet,
512                           uint8_t required_flags,
513                           uint8_t optional_flags,
514                           uint8_t payload_offset,
515                           DATA_BLOB *payload_and_verifier)
516 {
517         struct ncacn_packet *pkt = &call->pkt;
518         struct dcesrv_connection *dce_conn = call->conn;
519         struct dcesrv_auth *auth = call->auth_state;
520         const struct dcerpc_auth tmp_auth = {
521                 .auth_type = auth->auth_type,
522                 .auth_level = auth->auth_level,
523                 .auth_context_id = auth->auth_context_id,
524         };
525         NTSTATUS status;
526
527         if (!dce_conn->allow_request) {
528                 call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
529                 return false;
530         }
531
532         if (auth->auth_invalid) {
533                 return false;
534         }
535
536         status = dcerpc_ncacn_pull_pkt_auth(&tmp_auth,
537                                             auth->gensec_security,
538                                             call,
539                                             pkt->ptype,
540                                             required_flags,
541                                             optional_flags,
542                                             payload_offset,
543                                             payload_and_verifier,
544                                             full_packet,
545                                             pkt);
546         if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_PROTOCOL_ERROR)) {
547                 call->fault_code = DCERPC_NCA_S_PROTO_ERROR;
548                 return false;
549         }
550         if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_UNSUPPORTED_AUTHN_LEVEL)) {
551                 call->fault_code = DCERPC_NCA_S_UNSUPPORTED_AUTHN_LEVEL;
552                 return false;
553         }
554         if (NT_STATUS_EQUAL(status, NT_STATUS_RPC_SEC_PKG_ERROR)) {
555                 call->fault_code = DCERPC_FAULT_SEC_PKG_ERROR;
556                 return false;
557         }
558         if (NT_STATUS_EQUAL(status, NT_STATUS_ACCESS_DENIED)) {
559                 call->fault_code = DCERPC_FAULT_ACCESS_DENIED;
560                 return false;
561         }
562         if (!NT_STATUS_IS_OK(status)) {
563                 return false;
564         }
565
566         return true;
567 }
568
569 /* 
570    push a signed or sealed dcerpc request packet into a blob
571 */
572 bool dcesrv_auth_pkt_push(struct dcesrv_call_state *call,
573                           DATA_BLOB *blob, size_t sig_size,
574                           uint8_t payload_offset,
575                           const DATA_BLOB *payload,
576                           const struct ncacn_packet *pkt)
577 {
578         struct dcesrv_auth *auth = call->auth_state;
579         const struct dcerpc_auth tmp_auth = {
580                 .auth_type = auth->auth_type,
581                 .auth_level = auth->auth_level,
582                 .auth_context_id = auth->auth_context_id,
583         };
584         NTSTATUS status;
585
586         status = dcerpc_ncacn_push_pkt_auth(&tmp_auth,
587                                             auth->gensec_security,
588                                             call, blob, sig_size,
589                                             payload_offset,
590                                             payload,
591                                             pkt);
592         return NT_STATUS_IS_OK(status);
593 }