LCOV - code coverage report
Current view: top level - source4/librpc/rpc - dcerpc_schannel.c (source / functions) Hit Total Coverage
Test: coverage report for master 2f515e9b Lines: 219 268 81.7 %
Date: 2024-04-21 15:09:00 Functions: 12 12 100.0 %

          Line data    Source code
       1             : /* 
       2             :    Unix SMB/CIFS implementation.
       3             : 
       4             :    dcerpc schannel operations
       5             : 
       6             :    Copyright (C) Andrew Tridgell 2004
       7             :    Copyright (C) Andrew Bartlett <abartlet@samba.org> 2004-2005
       8             :    Copyright (C) Rafal Szczesniak 2006
       9             : 
      10             :    This program is free software; you can redistribute it and/or modify
      11             :    it under the terms of the GNU General Public License as published by
      12             :    the Free Software Foundation; either version 3 of the License, or
      13             :    (at your option) any later version.
      14             :    
      15             :    This program is distributed in the hope that it will be useful,
      16             :    but WITHOUT ANY WARRANTY; without even the implied warranty of
      17             :    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
      18             :    GNU General Public License for more details.
      19             :    
      20             :    You should have received a copy of the GNU General Public License
      21             :    along with this program.  If not, see <http://www.gnu.org/licenses/>.
      22             : */
      23             : 
      24             : #include "includes.h"
      25             : #include <tevent.h>
      26             : #include "auth/auth.h"
      27             : #include "libcli/composite/composite.h"
      28             : #include "libcli/auth/libcli_auth.h"
      29             : #include "librpc/gen_ndr/ndr_netlogon.h"
      30             : #include "librpc/gen_ndr/ndr_netlogon_c.h"
      31             : #include "auth/credentials/credentials.h"
      32             : #include "librpc/rpc/dcerpc_proto.h"
      33             : #include "param/param.h"
      34             : #include "lib/param/loadparm.h"
      35             : 
      36             : struct schannel_key_state {
      37             :         struct dcerpc_pipe *pipe;
      38             :         struct dcerpc_pipe *pipe2;
      39             :         struct dcerpc_binding *binding;
      40             :         bool dcerpc_schannel_auto;
      41             :         struct cli_credentials *credentials;
      42             :         struct netlogon_creds_CredentialState *creds;
      43             :         uint32_t local_negotiate_flags;
      44             :         uint32_t remote_negotiate_flags;
      45             :         struct netr_Credential credentials1;
      46             :         struct netr_Credential credentials2;
      47             :         struct netr_Credential credentials3;
      48             :         struct netr_ServerReqChallenge r;
      49             :         struct netr_ServerAuthenticate2 a;
      50             :         const struct samr_Password *mach_pwd;
      51             : };
      52             : 
      53             : 
      54             : static void continue_secondary_connection(struct composite_context *ctx);
      55             : static void continue_bind_auth_none(struct composite_context *ctx);
      56             : static void continue_srv_challenge(struct tevent_req *subreq);
      57             : static void continue_srv_auth2(struct tevent_req *subreq);
      58             : static void continue_get_capabilities(struct tevent_req *subreq);
      59             : 
      60             : 
      61             : /*
      62             :   Stage 2 of schannel_key: Receive endpoint mapping and request secondary
      63             :   rpc connection
      64             : */
      65         473 : static void continue_epm_map_binding(struct composite_context *ctx)
      66             : {
      67          56 :         struct composite_context *c;
      68          56 :         struct schannel_key_state *s;
      69          56 :         struct composite_context *sec_conn_req;
      70             : 
      71         473 :         c = talloc_get_type(ctx->async.private_data, struct composite_context);
      72         473 :         s = talloc_get_type(c->private_data, struct schannel_key_state);
      73             : 
      74             :         /* receive endpoint mapping */
      75         473 :         c->status = dcerpc_epm_map_binding_recv(ctx);
      76         473 :         if (!NT_STATUS_IS_OK(c->status)) {
      77           0 :                 DEBUG(0,("Failed to map DCERPC/TCP NCACN_NP pipe for '%s' - %s\n",
      78             :                          NDR_NETLOGON_UUID, nt_errstr(c->status)));
      79           0 :                 composite_error(c, c->status);
      80           0 :                 return;
      81             :         }
      82             : 
      83             :         /* send a request for secondary rpc connection */
      84         529 :         sec_conn_req = dcerpc_secondary_connection_send(s->pipe,
      85         473 :                                                         s->binding);
      86         473 :         if (composite_nomem(sec_conn_req, c)) return;
      87             : 
      88         473 :         composite_continue(c, sec_conn_req, continue_secondary_connection, c);
      89             : }
      90             : 
      91             : 
      92             : /*
      93             :   Stage 3 of schannel_key: Receive secondary rpc connection and perform
      94             :   non-authenticated bind request
      95             : */
      96         473 : static void continue_secondary_connection(struct composite_context *ctx)
      97             : {
      98          56 :         struct composite_context *c;
      99          56 :         struct schannel_key_state *s;
     100          56 :         struct composite_context *auth_none_req;
     101             : 
     102         473 :         c = talloc_get_type(ctx->async.private_data, struct composite_context);
     103         473 :         s = talloc_get_type(c->private_data, struct schannel_key_state);
     104             : 
     105             :         /* receive secondary rpc connection */
     106         473 :         c->status = dcerpc_secondary_connection_recv(ctx, &s->pipe2);
     107         473 :         if (!composite_is_ok(c)) return;
     108             : 
     109         473 :         talloc_steal(s, s->pipe2);
     110             : 
     111             :         /* initiate a non-authenticated bind */
     112         473 :         auth_none_req = dcerpc_bind_auth_none_send(c, s->pipe2, &ndr_table_netlogon);
     113         473 :         if (composite_nomem(auth_none_req, c)) return;
     114             : 
     115         473 :         composite_continue(c, auth_none_req, continue_bind_auth_none, c);
     116             : }
     117             : 
     118             : 
     119             : /*
     120             :   Stage 4 of schannel_key: Receive non-authenticated bind and get
     121             :   a netlogon challenge
     122             : */
     123         473 : static void continue_bind_auth_none(struct composite_context *ctx)
     124             : {
     125          56 :         struct composite_context *c;
     126          56 :         struct schannel_key_state *s;
     127          56 :         struct tevent_req *subreq;
     128             : 
     129         473 :         c = talloc_get_type(ctx->async.private_data, struct composite_context);
     130         473 :         s = talloc_get_type(c->private_data, struct schannel_key_state);
     131             : 
     132             :         /* receive result of non-authenticated bind request */
     133         473 :         c->status = dcerpc_bind_auth_none_recv(ctx);
     134         473 :         if (!composite_is_ok(c)) return;
     135             :         
     136             :         /* prepare a challenge request */
     137         473 :         s->r.in.server_name   = talloc_asprintf(c, "\\\\%s", dcerpc_server_name(s->pipe));
     138         473 :         if (composite_nomem(s->r.in.server_name, c)) return;
     139         473 :         s->r.in.computer_name = cli_credentials_get_workstation(s->credentials);
     140         473 :         s->r.in.credentials   = &s->credentials1;
     141         473 :         s->r.out.return_credentials  = &s->credentials2;
     142             :         
     143         473 :         generate_random_buffer(s->credentials1.data, sizeof(s->credentials1.data));
     144             : 
     145             :         /*
     146             :           request a netlogon challenge - a rpc request over opened secondary pipe
     147             :         */
     148         529 :         subreq = dcerpc_netr_ServerReqChallenge_r_send(s, c->event_ctx,
     149         473 :                                                        s->pipe2->binding_handle,
     150             :                                                        &s->r);
     151         473 :         if (composite_nomem(subreq, c)) return;
     152             : 
     153         473 :         tevent_req_set_callback(subreq, continue_srv_challenge, c);
     154             : }
     155             : 
     156             : 
     157             : /*
     158             :   Stage 5 of schannel_key: Receive a challenge and perform authentication
     159             :   on the netlogon pipe
     160             : */
     161         473 : static void continue_srv_challenge(struct tevent_req *subreq)
     162             : {
     163          56 :         struct composite_context *c;
     164          56 :         struct schannel_key_state *s;
     165             : 
     166         473 :         c = tevent_req_callback_data(subreq, struct composite_context);
     167         473 :         s = talloc_get_type(c->private_data, struct schannel_key_state);
     168             : 
     169             :         /* receive rpc request result - netlogon challenge */
     170         473 :         c->status = dcerpc_netr_ServerReqChallenge_r_recv(subreq, s);
     171         473 :         TALLOC_FREE(subreq);
     172         473 :         if (!composite_is_ok(c)) return;
     173             : 
     174             :         /* prepare credentials for auth2 request */
     175         473 :         s->mach_pwd = cli_credentials_get_nt_hash(s->credentials, c);
     176         473 :         if (s->mach_pwd == NULL) {
     177           0 :                 return composite_error(c, NT_STATUS_INTERNAL_ERROR);
     178             :         }
     179             : 
     180             :         /* auth2 request arguments */
     181         473 :         s->a.in.server_name      = s->r.in.server_name;
     182         473 :         s->a.in.account_name     = cli_credentials_get_username(s->credentials);
     183         529 :         s->a.in.secure_channel_type =
     184         473 :                 cli_credentials_get_secure_channel_type(s->credentials);
     185         473 :         s->a.in.computer_name    = cli_credentials_get_workstation(s->credentials);
     186         473 :         s->a.in.negotiate_flags  = &s->local_negotiate_flags;
     187         473 :         s->a.in.credentials      = &s->credentials3;
     188         473 :         s->a.out.negotiate_flags = &s->remote_negotiate_flags;
     189         473 :         s->a.out.return_credentials     = &s->credentials3;
     190             : 
     191         946 :         s->creds = netlogon_creds_client_init(s, 
     192             :                                               s->a.in.account_name, 
     193             :                                               s->a.in.computer_name,
     194         473 :                                               s->a.in.secure_channel_type,
     195         473 :                                               &s->credentials1, &s->credentials2,
     196             :                                               s->mach_pwd, &s->credentials3,
     197             :                                               s->local_negotiate_flags);
     198         473 :         if (composite_nomem(s->creds, c)) {
     199           0 :                 return;
     200             :         }
     201             :         /*
     202             :           authenticate on the netlogon pipe - a rpc request over secondary pipe
     203             :         */
     204         529 :         subreq = dcerpc_netr_ServerAuthenticate2_r_send(s, c->event_ctx,
     205         473 :                                                         s->pipe2->binding_handle,
     206             :                                                         &s->a);
     207         473 :         if (composite_nomem(subreq, c)) return;
     208             : 
     209         473 :         tevent_req_set_callback(subreq, continue_srv_auth2, c);
     210             : }
     211             : 
     212             : 
     213             : /*
     214             :   Stage 6 of schannel_key: Receive authentication request result and verify
     215             :   received credentials
     216             : */
     217         473 : static void continue_srv_auth2(struct tevent_req *subreq)
     218             : {
     219          56 :         struct composite_context *c;
     220          56 :         struct schannel_key_state *s;
     221             : 
     222         473 :         c = tevent_req_callback_data(subreq, struct composite_context);
     223         473 :         s = talloc_get_type(c->private_data, struct schannel_key_state);
     224             : 
     225             :         /* receive rpc request result - auth2 credentials */ 
     226         473 :         c->status = dcerpc_netr_ServerAuthenticate2_r_recv(subreq, s);
     227         473 :         TALLOC_FREE(subreq);
     228         473 :         if (!composite_is_ok(c)) return;
     229             : 
     230         473 :         if (!NT_STATUS_EQUAL(s->a.out.result, NT_STATUS_ACCESS_DENIED) &&
     231         471 :             !NT_STATUS_IS_OK(s->a.out.result)) {
     232           2 :                 composite_error(c, s->a.out.result);
     233           2 :                 return;
     234             :         }
     235             : 
     236             :         /*
     237             :          * Strong keys could be unsupported (NT4) or disabled. So retry with the
     238             :          * flags returned by the server. - asn
     239             :          */
     240         471 :         if (NT_STATUS_EQUAL(s->a.out.result, NT_STATUS_ACCESS_DENIED)) {
     241           2 :                 uint32_t lf = s->local_negotiate_flags;
     242           2 :                 const char *ln = NULL;
     243           2 :                 uint32_t rf = s->remote_negotiate_flags;
     244           2 :                 const char *rn = NULL;
     245             : 
     246           2 :                 if (!s->dcerpc_schannel_auto) {
     247           0 :                         composite_error(c, s->a.out.result);
     248           2 :                         return;
     249             :                 }
     250           2 :                 s->dcerpc_schannel_auto = false;
     251             : 
     252           2 :                 if (lf & NETLOGON_NEG_SUPPORTS_AES)  {
     253           2 :                         ln = "aes";
     254           2 :                         if (rf & NETLOGON_NEG_SUPPORTS_AES) {
     255           2 :                                 composite_error(c, s->a.out.result);
     256           2 :                                 return;
     257             :                         }
     258           0 :                 } else if (lf & NETLOGON_NEG_STRONG_KEYS) {
     259           0 :                         ln = "strong";
     260           0 :                         if (rf & NETLOGON_NEG_STRONG_KEYS) {
     261           0 :                                 composite_error(c, s->a.out.result);
     262           0 :                                 return;
     263             :                         }
     264             :                 } else {
     265           0 :                         ln = "des";
     266             :                 }
     267             : 
     268           0 :                 if (rf & NETLOGON_NEG_SUPPORTS_AES)  {
     269           0 :                         rn = "aes";
     270           0 :                 } else if (rf & NETLOGON_NEG_STRONG_KEYS) {
     271           0 :                         rn = "strong";
     272             :                 } else {
     273           0 :                         rn = "des";
     274             :                 }
     275             : 
     276           0 :                 DEBUG(3, ("Server doesn't support %s keys, downgrade to %s"
     277             :                           "and retry! local[0x%08X] remote[0x%08X]\n",
     278             :                           ln, rn, lf, rf));
     279             : 
     280           0 :                 s->local_negotiate_flags = s->remote_negotiate_flags;
     281             : 
     282           0 :                 generate_random_buffer(s->credentials1.data,
     283             :                                        sizeof(s->credentials1.data));
     284             : 
     285           0 :                 subreq = dcerpc_netr_ServerReqChallenge_r_send(s,
     286             :                                                                c->event_ctx,
     287           0 :                                                                s->pipe2->binding_handle,
     288             :                                                                &s->r);
     289           0 :                 if (composite_nomem(subreq, c)) return;
     290             : 
     291           0 :                 tevent_req_set_callback(subreq, continue_srv_challenge, c);
     292           0 :                 return;
     293             :         }
     294             : 
     295         469 :         s->creds->negotiate_flags = s->remote_negotiate_flags;
     296             : 
     297             :         /* verify credentials */
     298         469 :         if (!netlogon_creds_client_check(s->creds, s->a.out.return_credentials)) {
     299           0 :                 composite_error(c, NT_STATUS_UNSUCCESSFUL);
     300           0 :                 return;
     301             :         }
     302             : 
     303         469 :         composite_done(c);
     304             : }
     305             : 
     306             : /*
     307             :   Initiate establishing a schannel key using netlogon challenge
     308             :   on a secondary pipe
     309             : */
     310         473 : static struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx,
     311             :                                                    struct dcerpc_pipe *p,
     312             :                                                    struct cli_credentials *credentials,
     313             :                                                    struct loadparm_context *lp_ctx)
     314             : {
     315          56 :         struct composite_context *c;
     316          56 :         struct schannel_key_state *s;
     317          56 :         struct composite_context *epm_map_req;
     318         473 :         enum netr_SchannelType schannel_type = cli_credentials_get_secure_channel_type(credentials);
     319         473 :         struct cli_credentials *epm_creds = NULL;
     320             : 
     321             :         /* composite context allocation and setup */
     322         473 :         c = composite_create(mem_ctx, p->conn->event_ctx);
     323         473 :         if (c == NULL) return NULL;
     324             : 
     325         473 :         s = talloc_zero(c, struct schannel_key_state);
     326         473 :         if (composite_nomem(s, c)) return c;
     327         473 :         c->private_data = s;
     328             : 
     329             :         /* store parameters in the state structure */
     330         473 :         s->pipe        = p;
     331         473 :         s->credentials = credentials;
     332         473 :         s->local_negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS;
     333             : 
     334             :         /* allocate credentials */
     335         473 :         if (s->pipe->conn->flags & DCERPC_SCHANNEL_128) {
     336          93 :                 s->local_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
     337             :         }
     338         473 :         if (s->pipe->conn->flags & DCERPC_SCHANNEL_AES) {
     339          92 :                 s->local_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
     340          92 :                 s->local_negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES;
     341             :         }
     342         473 :         if (s->pipe->conn->flags & DCERPC_SCHANNEL_AUTO) {
     343         288 :                 s->local_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
     344         288 :                 s->local_negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES;
     345         288 :                 s->dcerpc_schannel_auto = true;
     346             :         }
     347             : 
     348             :         /* type of authentication depends on schannel type */
     349         473 :         if (schannel_type == SEC_CHAN_RODC) {
     350           0 :                 s->local_negotiate_flags |= NETLOGON_NEG_RODC_PASSTHROUGH;
     351             :         }
     352             : 
     353         473 :         if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) {
     354           0 :                 s->local_negotiate_flags &= ~NETLOGON_NEG_ARCFOUR;
     355             :         }
     356             : 
     357         473 :         epm_creds = cli_credentials_init_anon(s);
     358         473 :         if (composite_nomem(epm_creds, c)) return c;
     359             : 
     360             :         /* allocate binding structure */
     361         473 :         s->binding = dcerpc_binding_dup(s, s->pipe->binding);
     362         473 :         if (composite_nomem(s->binding, c)) return c;
     363             : 
     364             :         /* request the netlogon endpoint mapping */
     365         529 :         epm_map_req = dcerpc_epm_map_binding_send(c, s->binding,
     366             :                                                   &ndr_table_netlogon,
     367             :                                                   epm_creds,
     368         473 :                                                   s->pipe->conn->event_ctx,
     369             :                                                   lp_ctx);
     370         473 :         if (composite_nomem(epm_map_req, c)) return c;
     371             : 
     372         473 :         composite_continue(c, epm_map_req, continue_epm_map_binding, c);
     373         473 :         return c;
     374             : }
     375             : 
     376             : 
     377             : /*
     378             :   Receive result of schannel key request
     379             :  */
     380         473 : static NTSTATUS dcerpc_schannel_key_recv(struct composite_context *c,
     381             :                                 TALLOC_CTX *mem_ctx,
     382             :                                 struct netlogon_creds_CredentialState **creds)
     383             : {
     384         473 :         NTSTATUS status = composite_wait(c);
     385             : 
     386         473 :         if (NT_STATUS_IS_OK(status)) {
     387          56 :                 struct schannel_key_state *s =
     388         469 :                         talloc_get_type_abort(c->private_data,
     389             :                         struct schannel_key_state);
     390         469 :                 *creds = talloc_move(mem_ctx, &s->creds);
     391             :         }
     392             : 
     393         473 :         talloc_free(c);
     394         473 :         return status;
     395             : }
     396             : 
     397             : 
     398             : struct auth_schannel_state {
     399             :         struct dcerpc_pipe *pipe;
     400             :         struct cli_credentials *credentials;
     401             :         const struct ndr_interface_table *table;
     402             :         struct loadparm_context *lp_ctx;
     403             :         uint8_t auth_level;
     404             :         struct netlogon_creds_CredentialState *creds_state;
     405             :         struct netlogon_creds_CredentialState save_creds_state;
     406             :         struct netr_Authenticator auth;
     407             :         struct netr_Authenticator return_auth;
     408             :         union netr_Capabilities capabilities;
     409             :         struct netr_LogonGetCapabilities c;
     410             : };
     411             : 
     412             : 
     413             : static void continue_bind_auth(struct composite_context *ctx);
     414             : 
     415             : 
     416             : /*
     417             :   Stage 2 of auth_schannel: Receive schannel key and initiate an
     418             :   authenticated bind using received credentials
     419             :  */
     420         473 : static void continue_schannel_key(struct composite_context *ctx)
     421             : {
     422          56 :         struct composite_context *auth_req;
     423         473 :         struct composite_context *c = talloc_get_type(ctx->async.private_data,
     424             :                                                       struct composite_context);
     425         473 :         struct auth_schannel_state *s = talloc_get_type(c->private_data,
     426             :                                                         struct auth_schannel_state);
     427          56 :         NTSTATUS status;
     428             : 
     429             :         /* receive schannel key */
     430         473 :         status = c->status = dcerpc_schannel_key_recv(ctx, s, &s->creds_state);
     431         473 :         if (!composite_is_ok(c)) {
     432           4 :                 DEBUG(1, ("Failed to setup credentials: %s\n", nt_errstr(status)));
     433           4 :                 return;
     434             :         }
     435             : 
     436             :         /* send bind auth request with received creds */
     437         469 :         cli_credentials_set_netlogon_creds(s->credentials, s->creds_state);
     438             : 
     439         469 :         auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table, s->credentials, 
     440             :                                          lpcfg_gensec_settings(c, s->lp_ctx),
     441         469 :                                          DCERPC_AUTH_TYPE_SCHANNEL, s->auth_level,
     442             :                                          NULL);
     443         469 :         if (composite_nomem(auth_req, c)) return;
     444             :         
     445         469 :         composite_continue(c, auth_req, continue_bind_auth, c);
     446             : }
     447             : 
     448             : 
     449             : /*
     450             :   Stage 3 of auth_schannel: Receive result of authenticated bind
     451             :   and say if we're done ok.
     452             : */
     453         469 : static void continue_bind_auth(struct composite_context *ctx)
     454             : {
     455         469 :         struct composite_context *c = talloc_get_type(ctx->async.private_data,
     456             :                                                       struct composite_context);
     457         469 :         struct auth_schannel_state *s = talloc_get_type(c->private_data,
     458             :                                                         struct auth_schannel_state);
     459          56 :         struct tevent_req *subreq;
     460             : 
     461         469 :         c->status = dcerpc_bind_auth_recv(ctx);
     462         469 :         if (!composite_is_ok(c)) return;
     463             : 
     464             :         /* if we have a AES encrypted connection, verify the capabilities */
     465         469 :         if (ndr_syntax_id_equal(&s->table->syntax_id,
     466             :                                 &ndr_table_netlogon.syntax_id)) {
     467           8 :                 NTSTATUS status;
     468         187 :                 ZERO_STRUCT(s->return_auth);
     469             : 
     470         187 :                 s->save_creds_state = *s->creds_state;
     471         187 :                 status = netlogon_creds_client_authenticator(&s->save_creds_state,
     472             :                                                              &s->auth);
     473         187 :                 if (!NT_STATUS_IS_OK(status)) {
     474           0 :                         composite_error(c, status);
     475           0 :                         return;
     476             :                 }
     477             : 
     478         187 :                 s->c.in.server_name = talloc_asprintf(c,
     479             :                                                       "\\\\%s",
     480             :                                                       dcerpc_server_name(s->pipe));
     481         187 :                 if (composite_nomem(s->c.in.server_name, c)) return;
     482         187 :                 s->c.in.computer_name         = cli_credentials_get_workstation(s->credentials);
     483         187 :                 s->c.in.credential            = &s->auth;
     484         187 :                 s->c.in.return_authenticator  = &s->return_auth;
     485         187 :                 s->c.in.query_level           = 1;
     486             : 
     487         187 :                 s->c.out.capabilities         = &s->capabilities;
     488         187 :                 s->c.out.return_authenticator = &s->return_auth;
     489             : 
     490         187 :                 DEBUG(5, ("We established a AES connection, verifying logon "
     491             :                           "capabilities\n"));
     492             : 
     493         195 :                 subreq = dcerpc_netr_LogonGetCapabilities_r_send(s,
     494             :                                                                  c->event_ctx,
     495         187 :                                                                  s->pipe->binding_handle,
     496             :                                                                  &s->c);
     497         187 :                 if (composite_nomem(subreq, c)) return;
     498             : 
     499         187 :                 tevent_req_set_callback(subreq, continue_get_capabilities, c);
     500         187 :                 return;
     501             :         }
     502             : 
     503         282 :         composite_done(c);
     504             : }
     505             : 
     506             : /*
     507             :   Stage 4 of auth_schannel: Get the Logon Capabilities and verify them.
     508             : */
     509         187 : static void continue_get_capabilities(struct tevent_req *subreq)
     510             : {
     511           8 :         struct composite_context *c;
     512           8 :         struct auth_schannel_state *s;
     513             : 
     514         187 :         c = tevent_req_callback_data(subreq, struct composite_context);
     515         187 :         s = talloc_get_type(c->private_data, struct auth_schannel_state);
     516             : 
     517             :         /* receive rpc request result */
     518         187 :         c->status = dcerpc_netr_LogonGetCapabilities_r_recv(subreq, s);
     519         187 :         TALLOC_FREE(subreq);
     520         187 :         if (NT_STATUS_EQUAL(c->status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
     521           0 :                 if (s->creds_state->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     522           0 :                         composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
     523           0 :                         return;
     524             :                 } else {
     525             :                         /* This is probably NT */
     526           0 :                         composite_done(c);
     527           0 :                         return;
     528             :                 }
     529         187 :         } else if (!composite_is_ok(c)) {
     530           0 :                 return;
     531             :         }
     532             : 
     533         187 :         if (NT_STATUS_EQUAL(s->c.out.result, NT_STATUS_NOT_IMPLEMENTED)) {
     534           0 :                 if (s->creds_state->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     535             :                         /* This means AES isn't supported. */
     536           0 :                         composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
     537           0 :                         return;
     538             :                 }
     539             : 
     540             :                 /* This is probably an old Samba version */
     541           0 :                 composite_done(c);
     542           0 :                 return;
     543             :         }
     544             : 
     545             :         /* verify credentials */
     546         187 :         if (!netlogon_creds_client_check(&s->save_creds_state,
     547         187 :                                          &s->c.out.return_authenticator->cred)) {
     548           0 :                 composite_error(c, NT_STATUS_UNSUCCESSFUL);
     549           0 :                 return;
     550             :         }
     551             : 
     552         187 :         *s->creds_state = s->save_creds_state;
     553         187 :         cli_credentials_set_netlogon_creds(s->credentials, s->creds_state);
     554             : 
     555         187 :         if (!NT_STATUS_IS_OK(s->c.out.result)) {
     556           0 :                 composite_error(c, s->c.out.result);
     557           0 :                 return;
     558             :         }
     559             : 
     560             :         /* compare capabilities */
     561         187 :         if (s->creds_state->negotiate_flags != s->capabilities.server_capabilities) {
     562           0 :                 DEBUG(2, ("The client capabilities don't match the server "
     563             :                           "capabilities: local[0x%08X] remote[0x%08X]\n",
     564             :                           s->creds_state->negotiate_flags,
     565             :                           s->capabilities.server_capabilities));
     566           0 :                 composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
     567           0 :                 return;
     568             :         }
     569             : 
     570             :         /* TODO: Add downgrade detection. */
     571             : 
     572         187 :         composite_done(c);
     573             : }
     574             : 
     575             : 
     576             : /*
     577             :   Initiate schannel authentication request
     578             : */
     579         473 : struct composite_context *dcerpc_bind_auth_schannel_send(TALLOC_CTX *tmp_ctx, 
     580             :                                                          struct dcerpc_pipe *p,
     581             :                                                          const struct ndr_interface_table *table,
     582             :                                                          struct cli_credentials *credentials,
     583             :                                                          struct loadparm_context *lp_ctx,
     584             :                                                          uint8_t auth_level)
     585             : {
     586          56 :         struct composite_context *c;
     587          56 :         struct auth_schannel_state *s;
     588          56 :         struct composite_context *schan_key_req;
     589             : 
     590             :         /* composite context allocation and setup */
     591         473 :         c = composite_create(tmp_ctx, p->conn->event_ctx);
     592         473 :         if (c == NULL) return NULL;
     593             :         
     594         473 :         s = talloc_zero(c, struct auth_schannel_state);
     595         473 :         if (composite_nomem(s, c)) return c;
     596         473 :         c->private_data = s;
     597             : 
     598             :         /* store parameters in the state structure */
     599         473 :         s->pipe        = p;
     600         473 :         s->credentials = credentials;
     601         473 :         s->table       = table;
     602         473 :         s->auth_level  = auth_level;
     603         473 :         s->lp_ctx      = lp_ctx;
     604             : 
     605             :         /* start getting schannel key first */
     606         473 :         schan_key_req = dcerpc_schannel_key_send(c, p, credentials, lp_ctx);
     607         473 :         if (composite_nomem(schan_key_req, c)) return c;
     608             : 
     609         473 :         composite_continue(c, schan_key_req, continue_schannel_key, c);
     610         473 :         return c;
     611             : }
     612             : 
     613             : 
     614             : /*
     615             :   Receive result of schannel authentication request
     616             : */
     617         473 : NTSTATUS dcerpc_bind_auth_schannel_recv(struct composite_context *c)
     618             : {
     619         473 :         NTSTATUS status = composite_wait(c);
     620             :         
     621         473 :         talloc_free(c);
     622         473 :         return status;
     623             : }

Generated by: LCOV version 1.14