LCOV - code coverage report
Current view: top level - source4/librpc/rpc - dcerpc_schannel.c (source / functions) Hit Total Coverage
Test: coverage report for v4-17-test 1498b464 Lines: 192 241 79.7 %
Date: 2024-06-13 04:01:37 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         195 : static void continue_epm_map_binding(struct composite_context *ctx)
      66             : {
      67             :         struct composite_context *c;
      68             :         struct schannel_key_state *s;
      69             :         struct composite_context *sec_conn_req;
      70             : 
      71         195 :         c = talloc_get_type(ctx->async.private_data, struct composite_context);
      72         195 :         s = talloc_get_type(c->private_data, struct schannel_key_state);
      73             : 
      74             :         /* receive endpoint mapping */
      75         195 :         c->status = dcerpc_epm_map_binding_recv(ctx);
      76         195 :         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         195 :         sec_conn_req = dcerpc_secondary_connection_send(s->pipe,
      85         195 :                                                         s->binding);
      86         195 :         if (composite_nomem(sec_conn_req, c)) return;
      87             : 
      88         195 :         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         195 : static void continue_secondary_connection(struct composite_context *ctx)
      97             : {
      98             :         struct composite_context *c;
      99             :         struct schannel_key_state *s;
     100             :         struct composite_context *auth_none_req;
     101             : 
     102         195 :         c = talloc_get_type(ctx->async.private_data, struct composite_context);
     103         195 :         s = talloc_get_type(c->private_data, struct schannel_key_state);
     104             : 
     105             :         /* receive secondary rpc connection */
     106         195 :         c->status = dcerpc_secondary_connection_recv(ctx, &s->pipe2);
     107         195 :         if (!composite_is_ok(c)) return;
     108             : 
     109         195 :         talloc_steal(s, s->pipe2);
     110             : 
     111             :         /* initiate a non-authenticated bind */
     112         195 :         auth_none_req = dcerpc_bind_auth_none_send(c, s->pipe2, &ndr_table_netlogon);
     113         195 :         if (composite_nomem(auth_none_req, c)) return;
     114             : 
     115         195 :         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         195 : static void continue_bind_auth_none(struct composite_context *ctx)
     124             : {
     125             :         struct composite_context *c;
     126             :         struct schannel_key_state *s;
     127             :         struct tevent_req *subreq;
     128             : 
     129         195 :         c = talloc_get_type(ctx->async.private_data, struct composite_context);
     130         195 :         s = talloc_get_type(c->private_data, struct schannel_key_state);
     131             : 
     132             :         /* receive result of non-authenticated bind request */
     133         195 :         c->status = dcerpc_bind_auth_none_recv(ctx);
     134         195 :         if (!composite_is_ok(c)) return;
     135             :         
     136             :         /* prepare a challenge request */
     137         195 :         s->r.in.server_name   = talloc_asprintf(c, "\\\\%s", dcerpc_server_name(s->pipe));
     138         195 :         if (composite_nomem(s->r.in.server_name, c)) return;
     139         195 :         s->r.in.computer_name = cli_credentials_get_workstation(s->credentials);
     140         195 :         s->r.in.credentials   = &s->credentials1;
     141         195 :         s->r.out.return_credentials  = &s->credentials2;
     142             :         
     143         195 :         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         390 :         subreq = dcerpc_netr_ServerReqChallenge_r_send(s, c->event_ctx,
     149         195 :                                                        s->pipe2->binding_handle,
     150             :                                                        &s->r);
     151         195 :         if (composite_nomem(subreq, c)) return;
     152             : 
     153         195 :         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         195 : static void continue_srv_challenge(struct tevent_req *subreq)
     162             : {
     163             :         struct composite_context *c;
     164             :         struct schannel_key_state *s;
     165             : 
     166         195 :         c = tevent_req_callback_data(subreq, struct composite_context);
     167         195 :         s = talloc_get_type(c->private_data, struct schannel_key_state);
     168             : 
     169             :         /* receive rpc request result - netlogon challenge */
     170         195 :         c->status = dcerpc_netr_ServerReqChallenge_r_recv(subreq, s);
     171         195 :         TALLOC_FREE(subreq);
     172         195 :         if (!composite_is_ok(c)) return;
     173             : 
     174             :         /* prepare credentials for auth2 request */
     175         195 :         s->mach_pwd = cli_credentials_get_nt_hash(s->credentials, c);
     176             : 
     177             :         /* auth2 request arguments */
     178         195 :         s->a.in.server_name      = s->r.in.server_name;
     179         195 :         s->a.in.account_name     = cli_credentials_get_username(s->credentials);
     180         195 :         s->a.in.secure_channel_type =
     181         195 :                 cli_credentials_get_secure_channel_type(s->credentials);
     182         195 :         s->a.in.computer_name    = cli_credentials_get_workstation(s->credentials);
     183         195 :         s->a.in.negotiate_flags  = &s->local_negotiate_flags;
     184         195 :         s->a.in.credentials      = &s->credentials3;
     185         195 :         s->a.out.negotiate_flags = &s->remote_negotiate_flags;
     186         195 :         s->a.out.return_credentials     = &s->credentials3;
     187             : 
     188         390 :         s->creds = netlogon_creds_client_init(s, 
     189             :                                               s->a.in.account_name, 
     190             :                                               s->a.in.computer_name,
     191         195 :                                               s->a.in.secure_channel_type,
     192         195 :                                               &s->credentials1, &s->credentials2,
     193             :                                               s->mach_pwd, &s->credentials3,
     194             :                                               s->local_negotiate_flags);
     195         195 :         if (composite_nomem(s->creds, c)) {
     196           0 :                 return;
     197             :         }
     198             :         /*
     199             :           authenticate on the netlogon pipe - a rpc request over secondary pipe
     200             :         */
     201         390 :         subreq = dcerpc_netr_ServerAuthenticate2_r_send(s, c->event_ctx,
     202         195 :                                                         s->pipe2->binding_handle,
     203             :                                                         &s->a);
     204         195 :         if (composite_nomem(subreq, c)) return;
     205             : 
     206         195 :         tevent_req_set_callback(subreq, continue_srv_auth2, c);
     207             : }
     208             : 
     209             : 
     210             : /*
     211             :   Stage 6 of schannel_key: Receive authentication request result and verify
     212             :   received credentials
     213             : */
     214         195 : static void continue_srv_auth2(struct tevent_req *subreq)
     215             : {
     216             :         struct composite_context *c;
     217             :         struct schannel_key_state *s;
     218             : 
     219         195 :         c = tevent_req_callback_data(subreq, struct composite_context);
     220         195 :         s = talloc_get_type(c->private_data, struct schannel_key_state);
     221             : 
     222             :         /* receive rpc request result - auth2 credentials */ 
     223         195 :         c->status = dcerpc_netr_ServerAuthenticate2_r_recv(subreq, s);
     224         195 :         TALLOC_FREE(subreq);
     225         195 :         if (!composite_is_ok(c)) return;
     226             : 
     227         389 :         if (!NT_STATUS_EQUAL(s->a.out.result, NT_STATUS_ACCESS_DENIED) &&
     228         194 :             !NT_STATUS_IS_OK(s->a.out.result)) {
     229           1 :                 composite_error(c, s->a.out.result);
     230           1 :                 return;
     231             :         }
     232             : 
     233             :         /*
     234             :          * Strong keys could be unsupported (NT4) or disables. So retry with the
     235             :          * flags returned by the server. - asn
     236             :          */
     237         194 :         if (NT_STATUS_EQUAL(s->a.out.result, NT_STATUS_ACCESS_DENIED)) {
     238           1 :                 uint32_t lf = s->local_negotiate_flags;
     239           1 :                 const char *ln = NULL;
     240           1 :                 uint32_t rf = s->remote_negotiate_flags;
     241           1 :                 const char *rn = NULL;
     242             : 
     243           1 :                 if (!s->dcerpc_schannel_auto) {
     244           0 :                         composite_error(c, s->a.out.result);
     245           0 :                         return;
     246             :                 }
     247           1 :                 s->dcerpc_schannel_auto = false;
     248             : 
     249           1 :                 if (lf & NETLOGON_NEG_SUPPORTS_AES)  {
     250           1 :                         ln = "aes";
     251           1 :                         if (rf & NETLOGON_NEG_SUPPORTS_AES) {
     252           1 :                                 composite_error(c, s->a.out.result);
     253           1 :                                 return;
     254             :                         }
     255           0 :                 } else if (lf & NETLOGON_NEG_STRONG_KEYS) {
     256           0 :                         ln = "strong";
     257           0 :                         if (rf & NETLOGON_NEG_STRONG_KEYS) {
     258           0 :                                 composite_error(c, s->a.out.result);
     259           0 :                                 return;
     260             :                         }
     261             :                 } else {
     262           0 :                         ln = "des";
     263             :                 }
     264             : 
     265           0 :                 if (rf & NETLOGON_NEG_SUPPORTS_AES)  {
     266           0 :                         rn = "aes";
     267           0 :                 } else if (rf & NETLOGON_NEG_STRONG_KEYS) {
     268           0 :                         rn = "strong";
     269             :                 } else {
     270           0 :                         rn = "des";
     271             :                 }
     272             : 
     273           0 :                 DEBUG(3, ("Server doesn't support %s keys, downgrade to %s"
     274             :                           "and retry! local[0x%08X] remote[0x%08X]\n",
     275             :                           ln, rn, lf, rf));
     276             : 
     277           0 :                 s->local_negotiate_flags = s->remote_negotiate_flags;
     278             : 
     279           0 :                 generate_random_buffer(s->credentials1.data,
     280             :                                        sizeof(s->credentials1.data));
     281             : 
     282           0 :                 subreq = dcerpc_netr_ServerReqChallenge_r_send(s,
     283             :                                                                c->event_ctx,
     284           0 :                                                                s->pipe2->binding_handle,
     285             :                                                                &s->r);
     286           0 :                 if (composite_nomem(subreq, c)) return;
     287             : 
     288           0 :                 tevent_req_set_callback(subreq, continue_srv_challenge, c);
     289           0 :                 return;
     290             :         }
     291             : 
     292         193 :         s->creds->negotiate_flags = s->remote_negotiate_flags;
     293             : 
     294             :         /* verify credentials */
     295         193 :         if (!netlogon_creds_client_check(s->creds, s->a.out.return_credentials)) {
     296           0 :                 composite_error(c, NT_STATUS_UNSUCCESSFUL);
     297           0 :                 return;
     298             :         }
     299             : 
     300         193 :         composite_done(c);
     301             : }
     302             : 
     303             : /*
     304             :   Initiate establishing a schannel key using netlogon challenge
     305             :   on a secondary pipe
     306             : */
     307         195 : static struct composite_context *dcerpc_schannel_key_send(TALLOC_CTX *mem_ctx,
     308             :                                                    struct dcerpc_pipe *p,
     309             :                                                    struct cli_credentials *credentials,
     310             :                                                    struct loadparm_context *lp_ctx)
     311             : {
     312             :         struct composite_context *c;
     313             :         struct schannel_key_state *s;
     314             :         struct composite_context *epm_map_req;
     315         195 :         enum netr_SchannelType schannel_type = cli_credentials_get_secure_channel_type(credentials);
     316         195 :         struct cli_credentials *epm_creds = NULL;
     317             : 
     318             :         /* composite context allocation and setup */
     319         195 :         c = composite_create(mem_ctx, p->conn->event_ctx);
     320         195 :         if (c == NULL) return NULL;
     321             : 
     322         195 :         s = talloc_zero(c, struct schannel_key_state);
     323         195 :         if (composite_nomem(s, c)) return c;
     324         195 :         c->private_data = s;
     325             : 
     326             :         /* store parameters in the state structure */
     327         195 :         s->pipe        = p;
     328         195 :         s->credentials = credentials;
     329         195 :         s->local_negotiate_flags = NETLOGON_NEG_AUTH2_FLAGS;
     330             : 
     331             :         /* allocate credentials */
     332         195 :         if (s->pipe->conn->flags & DCERPC_SCHANNEL_128) {
     333          37 :                 s->local_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
     334             :         }
     335         195 :         if (s->pipe->conn->flags & DCERPC_SCHANNEL_AES) {
     336          36 :                 s->local_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
     337          36 :                 s->local_negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES;
     338             :         }
     339         195 :         if (s->pipe->conn->flags & DCERPC_SCHANNEL_AUTO) {
     340         122 :                 s->local_negotiate_flags = NETLOGON_NEG_AUTH2_ADS_FLAGS;
     341         122 :                 s->local_negotiate_flags |= NETLOGON_NEG_SUPPORTS_AES;
     342         122 :                 s->dcerpc_schannel_auto = true;
     343             :         }
     344             : 
     345             :         /* type of authentication depends on schannel type */
     346         195 :         if (schannel_type == SEC_CHAN_RODC) {
     347           0 :                 s->local_negotiate_flags |= NETLOGON_NEG_RODC_PASSTHROUGH;
     348             :         }
     349             : 
     350         195 :         if (lpcfg_weak_crypto(lp_ctx) == SAMBA_WEAK_CRYPTO_DISALLOWED) {
     351           0 :                 s->local_negotiate_flags &= ~NETLOGON_NEG_ARCFOUR;
     352             :         }
     353             : 
     354         195 :         epm_creds = cli_credentials_init_anon(s);
     355         195 :         if (composite_nomem(epm_creds, c)) return c;
     356             : 
     357             :         /* allocate binding structure */
     358         195 :         s->binding = dcerpc_binding_dup(s, s->pipe->binding);
     359         195 :         if (composite_nomem(s->binding, c)) return c;
     360             : 
     361             :         /* request the netlogon endpoint mapping */
     362         195 :         epm_map_req = dcerpc_epm_map_binding_send(c, s->binding,
     363             :                                                   &ndr_table_netlogon,
     364             :                                                   epm_creds,
     365         195 :                                                   s->pipe->conn->event_ctx,
     366             :                                                   lp_ctx);
     367         195 :         if (composite_nomem(epm_map_req, c)) return c;
     368             : 
     369         195 :         composite_continue(c, epm_map_req, continue_epm_map_binding, c);
     370         195 :         return c;
     371             : }
     372             : 
     373             : 
     374             : /*
     375             :   Receive result of schannel key request
     376             :  */
     377         195 : static NTSTATUS dcerpc_schannel_key_recv(struct composite_context *c,
     378             :                                 TALLOC_CTX *mem_ctx,
     379             :                                 struct netlogon_creds_CredentialState **creds)
     380             : {
     381         195 :         NTSTATUS status = composite_wait(c);
     382             : 
     383         195 :         if (NT_STATUS_IS_OK(status)) {
     384         193 :                 struct schannel_key_state *s =
     385         193 :                         talloc_get_type_abort(c->private_data,
     386             :                         struct schannel_key_state);
     387         193 :                 *creds = talloc_move(mem_ctx, &s->creds);
     388             :         }
     389             : 
     390         195 :         talloc_free(c);
     391         195 :         return status;
     392             : }
     393             : 
     394             : 
     395             : struct auth_schannel_state {
     396             :         struct dcerpc_pipe *pipe;
     397             :         struct cli_credentials *credentials;
     398             :         const struct ndr_interface_table *table;
     399             :         struct loadparm_context *lp_ctx;
     400             :         uint8_t auth_level;
     401             :         struct netlogon_creds_CredentialState *creds_state;
     402             :         struct netlogon_creds_CredentialState save_creds_state;
     403             :         struct netr_Authenticator auth;
     404             :         struct netr_Authenticator return_auth;
     405             :         union netr_Capabilities capabilities;
     406             :         struct netr_LogonGetCapabilities c;
     407             : };
     408             : 
     409             : 
     410             : static void continue_bind_auth(struct composite_context *ctx);
     411             : 
     412             : 
     413             : /*
     414             :   Stage 2 of auth_schannel: Receive schannel key and intitiate an
     415             :   authenticated bind using received credentials
     416             :  */
     417         195 : static void continue_schannel_key(struct composite_context *ctx)
     418             : {
     419             :         struct composite_context *auth_req;
     420         195 :         struct composite_context *c = talloc_get_type(ctx->async.private_data,
     421             :                                                       struct composite_context);
     422         195 :         struct auth_schannel_state *s = talloc_get_type(c->private_data,
     423             :                                                         struct auth_schannel_state);
     424             :         NTSTATUS status;
     425             : 
     426             :         /* receive schannel key */
     427         195 :         status = c->status = dcerpc_schannel_key_recv(ctx, s, &s->creds_state);
     428         195 :         if (!composite_is_ok(c)) {
     429           2 :                 DEBUG(1, ("Failed to setup credentials: %s\n", nt_errstr(status)));
     430           4 :                 return;
     431             :         }
     432             : 
     433             :         /* send bind auth request with received creds */
     434         193 :         cli_credentials_set_netlogon_creds(s->credentials, s->creds_state);
     435             : 
     436         193 :         auth_req = dcerpc_bind_auth_send(c, s->pipe, s->table, s->credentials, 
     437             :                                          lpcfg_gensec_settings(c, s->lp_ctx),
     438         193 :                                          DCERPC_AUTH_TYPE_SCHANNEL, s->auth_level,
     439             :                                          NULL);
     440         193 :         if (composite_nomem(auth_req, c)) return;
     441             :         
     442         193 :         composite_continue(c, auth_req, continue_bind_auth, c);
     443             : }
     444             : 
     445             : 
     446             : /*
     447             :   Stage 3 of auth_schannel: Receivce result of authenticated bind
     448             :   and say if we're done ok.
     449             : */
     450         193 : static void continue_bind_auth(struct composite_context *ctx)
     451             : {
     452         193 :         struct composite_context *c = talloc_get_type(ctx->async.private_data,
     453             :                                                       struct composite_context);
     454         193 :         struct auth_schannel_state *s = talloc_get_type(c->private_data,
     455             :                                                         struct auth_schannel_state);
     456             :         struct tevent_req *subreq;
     457             : 
     458         193 :         c->status = dcerpc_bind_auth_recv(ctx);
     459         193 :         if (!composite_is_ok(c)) return;
     460             : 
     461             :         /* if we have a AES encrypted connection, verify the capabilities */
     462         193 :         if (ndr_syntax_id_equal(&s->table->syntax_id,
     463             :                                 &ndr_table_netlogon.syntax_id)) {
     464             :                 NTSTATUS status;
     465          79 :                 ZERO_STRUCT(s->return_auth);
     466             : 
     467          79 :                 s->save_creds_state = *s->creds_state;
     468          79 :                 status = netlogon_creds_client_authenticator(&s->save_creds_state,
     469             :                                                              &s->auth);
     470          79 :                 if (!NT_STATUS_IS_OK(status)) {
     471           0 :                         composite_error(c, status);
     472           0 :                         return;
     473             :                 }
     474             : 
     475          79 :                 s->c.in.server_name = talloc_asprintf(c,
     476             :                                                       "\\\\%s",
     477             :                                                       dcerpc_server_name(s->pipe));
     478          79 :                 if (composite_nomem(s->c.in.server_name, c)) return;
     479          79 :                 s->c.in.computer_name         = cli_credentials_get_workstation(s->credentials);
     480          79 :                 s->c.in.credential            = &s->auth;
     481          79 :                 s->c.in.return_authenticator  = &s->return_auth;
     482          79 :                 s->c.in.query_level           = 1;
     483             : 
     484          79 :                 s->c.out.capabilities         = &s->capabilities;
     485          79 :                 s->c.out.return_authenticator = &s->return_auth;
     486             : 
     487          79 :                 DEBUG(5, ("We established a AES connection, verifying logon "
     488             :                           "capabilities\n"));
     489             : 
     490         158 :                 subreq = dcerpc_netr_LogonGetCapabilities_r_send(s,
     491             :                                                                  c->event_ctx,
     492          79 :                                                                  s->pipe->binding_handle,
     493             :                                                                  &s->c);
     494          79 :                 if (composite_nomem(subreq, c)) return;
     495             : 
     496          79 :                 tevent_req_set_callback(subreq, continue_get_capabilities, c);
     497          79 :                 return;
     498             :         }
     499             : 
     500         114 :         composite_done(c);
     501             : }
     502             : 
     503             : /*
     504             :   Stage 4 of auth_schannel: Get the Logon Capablities and verify them.
     505             : */
     506          79 : static void continue_get_capabilities(struct tevent_req *subreq)
     507             : {
     508             :         struct composite_context *c;
     509             :         struct auth_schannel_state *s;
     510             : 
     511          79 :         c = tevent_req_callback_data(subreq, struct composite_context);
     512          79 :         s = talloc_get_type(c->private_data, struct auth_schannel_state);
     513             : 
     514             :         /* receive rpc request result */
     515          79 :         c->status = dcerpc_netr_LogonGetCapabilities_r_recv(subreq, s);
     516          79 :         TALLOC_FREE(subreq);
     517          79 :         if (NT_STATUS_EQUAL(c->status, NT_STATUS_RPC_PROCNUM_OUT_OF_RANGE)) {
     518           0 :                 if (s->creds_state->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     519           0 :                         composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
     520           0 :                         return;
     521             :                 } else {
     522             :                         /* This is probably NT */
     523           0 :                         composite_done(c);
     524           0 :                         return;
     525             :                 }
     526          79 :         } else if (!composite_is_ok(c)) {
     527           0 :                 return;
     528             :         }
     529             : 
     530          79 :         if (NT_STATUS_EQUAL(s->c.out.result, NT_STATUS_NOT_IMPLEMENTED)) {
     531           0 :                 if (s->creds_state->negotiate_flags & NETLOGON_NEG_SUPPORTS_AES) {
     532             :                         /* This means AES isn't supported. */
     533           0 :                         composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
     534           0 :                         return;
     535             :                 }
     536             : 
     537             :                 /* This is probably an old Samba version */
     538           0 :                 composite_done(c);
     539           0 :                 return;
     540             :         }
     541             : 
     542             :         /* verify credentials */
     543          79 :         if (!netlogon_creds_client_check(&s->save_creds_state,
     544          79 :                                          &s->c.out.return_authenticator->cred)) {
     545           0 :                 composite_error(c, NT_STATUS_UNSUCCESSFUL);
     546           0 :                 return;
     547             :         }
     548             : 
     549          79 :         *s->creds_state = s->save_creds_state;
     550          79 :         cli_credentials_set_netlogon_creds(s->credentials, s->creds_state);
     551             : 
     552          79 :         if (!NT_STATUS_IS_OK(s->c.out.result)) {
     553           0 :                 composite_error(c, s->c.out.result);
     554           0 :                 return;
     555             :         }
     556             : 
     557             :         /* compare capabilities */
     558          79 :         if (s->creds_state->negotiate_flags != s->capabilities.server_capabilities) {
     559           0 :                 DEBUG(2, ("The client capabilities don't match the server "
     560             :                           "capabilities: local[0x%08X] remote[0x%08X]\n",
     561             :                           s->creds_state->negotiate_flags,
     562             :                           s->capabilities.server_capabilities));
     563           0 :                 composite_error(c, NT_STATUS_INVALID_NETWORK_RESPONSE);
     564           0 :                 return;
     565             :         }
     566             : 
     567             :         /* TODO: Add downgrade dectection. */
     568             : 
     569          79 :         composite_done(c);
     570             : }
     571             : 
     572             : 
     573             : /*
     574             :   Initiate schannel authentication request
     575             : */
     576         195 : struct composite_context *dcerpc_bind_auth_schannel_send(TALLOC_CTX *tmp_ctx, 
     577             :                                                          struct dcerpc_pipe *p,
     578             :                                                          const struct ndr_interface_table *table,
     579             :                                                          struct cli_credentials *credentials,
     580             :                                                          struct loadparm_context *lp_ctx,
     581             :                                                          uint8_t auth_level)
     582             : {
     583             :         struct composite_context *c;
     584             :         struct auth_schannel_state *s;
     585             :         struct composite_context *schan_key_req;
     586             : 
     587             :         /* composite context allocation and setup */
     588         195 :         c = composite_create(tmp_ctx, p->conn->event_ctx);
     589         195 :         if (c == NULL) return NULL;
     590             :         
     591         195 :         s = talloc_zero(c, struct auth_schannel_state);
     592         195 :         if (composite_nomem(s, c)) return c;
     593         195 :         c->private_data = s;
     594             : 
     595             :         /* store parameters in the state structure */
     596         195 :         s->pipe        = p;
     597         195 :         s->credentials = credentials;
     598         195 :         s->table       = table;
     599         195 :         s->auth_level  = auth_level;
     600         195 :         s->lp_ctx      = lp_ctx;
     601             : 
     602             :         /* start getting schannel key first */
     603         195 :         schan_key_req = dcerpc_schannel_key_send(c, p, credentials, lp_ctx);
     604         195 :         if (composite_nomem(schan_key_req, c)) return c;
     605             : 
     606         195 :         composite_continue(c, schan_key_req, continue_schannel_key, c);
     607         195 :         return c;
     608             : }
     609             : 
     610             : 
     611             : /*
     612             :   Receive result of schannel authentication request
     613             : */
     614         195 : NTSTATUS dcerpc_bind_auth_schannel_recv(struct composite_context *c)
     615             : {
     616         195 :         NTSTATUS status = composite_wait(c);
     617             :         
     618         195 :         talloc_free(c);
     619         195 :         return status;
     620             : }

Generated by: LCOV version 1.13