s3-dcerpc: Add next authentication step with gssapi
authorSimo Sorce <idra@samba.org>
Sat, 24 Jul 2010 14:35:25 +0000 (10:35 -0400)
committerSimo Sorce <idra@samba.org>
Wed, 28 Jul 2010 16:24:44 +0000 (12:24 -0400)
source3/librpc/rpc/dcerpc_gssapi.c
source3/librpc/rpc/dcerpc_gssapi.h
source3/rpc_client/cli_pipe.c

index e3e5eedac4d09b3c9721ed5fa96488e4b2ac1be2..d4153692079cec14defb16e02a02261cfac0ca9e 100644 (file)
@@ -240,7 +240,7 @@ NTSTATUS gse_init_client(TALLOC_CTX *mem_ctx,
        mech_set.elements = &gse_ctx->gss_mech;
 
        gss_maj = gss_acquire_cred(&gss_min,
-                                  gse_ctx->server_name,
+                                  GSS_C_NO_NAME,
                                   GSS_C_INDEFINITE,
                                   &mech_set,
                                   GSS_C_INITIATE,
@@ -296,7 +296,8 @@ NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx,
        case GSS_S_CONTINUE_NEEDED:
                /* we will need a third leg */
                gse_ctx->more_processing = true;
-               status = NT_STATUS_MORE_PROCESSING_REQUIRED;
+               /* status = NT_STATUS_MORE_PROCESSING_REQUIRED; */
+               status = NT_STATUS_OK;
                break;
        default:
                DEBUG(0, ("gss_init_sec_context failed with [%s]\n",
@@ -368,6 +369,11 @@ done:
        return errstr;
 }
 
+bool gse_require_more_processing(struct gse_context *gse_ctx)
+{
+       return gse_ctx->more_processing;
+}
+
 DATA_BLOB gse_get_session_key(struct gse_context *gse_ctx)
 {
        return gse_ctx->session_key;
@@ -396,6 +402,11 @@ NTSTATUS gse_gen_client_auth_token(TALLOC_CTX *mem_ctx,
        return NT_STATUS_NOT_IMPLEMENTED;
 }
 
+bool gse_require_more_processing(struct gse_context *gse_ctx)
+{
+       return NT_STATUS_NOT_IMPLEMENTED;
+}
+
 DATA_BLOB gse_get_session_key(struct gse_context *gse_ctx)
 {
        return data_blob_null;
index c172cacc14edf0c80343283e4949427333b9c3d6..ea44e9e383eb43d01b334c1c59d487cf46baaaa0 100644 (file)
@@ -42,6 +42,7 @@ NTSTATUS gse_get_client_auth_token(TALLOC_CTX *mem_ctx,
                                   DATA_BLOB *token_in,
                                   DATA_BLOB *token_out);
 
+bool gse_require_more_processing(struct gse_context *gse_ctx);
 DATA_BLOB gse_get_session_key(struct gse_context *gse_ctx);
 
 #endif /* _CLI_PIPE_GSSAPI_H_ */
index 2d4ee562ad8c40b964548cb878c116c530558ac9..4a3229d7cc16b65df78662ac1b07943cf408ac7e 100644 (file)
@@ -1714,10 +1714,11 @@ static NTSTATUS create_rpc_bind_auth3(TALLOC_CTX *mem_ctx,
  ********************************************************************/
 
 static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
+                                       enum dcerpc_AuthType auth_type,
+                                       enum dcerpc_AuthLevel auth_level,
                                        uint32 rpc_call_id,
                                        const struct ndr_syntax_id *abstract,
                                        const struct ndr_syntax_id *transfer,
-                                       enum dcerpc_AuthLevel auth_level,
                                        const DATA_BLOB *pauth_blob, /* spnego auth blob already created. */
                                        DATA_BLOB *rpc_out)
 {
@@ -1725,7 +1726,7 @@ static NTSTATUS create_rpc_alter_context(TALLOC_CTX *mem_ctx,
        NTSTATUS status;
 
        status = dcerpc_push_dcerpc_auth(mem_ctx,
-                                        DCERPC_AUTH_TYPE_SPNEGO,
+                                        auth_type,
                                         auth_level,
                                         0, /* auth_pad_length */
                                         1, /* auth_context_id */
@@ -1766,6 +1767,12 @@ static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
                                        struct rpc_pipe_bind_state *state,
                                        DATA_BLOB *credentials);
 static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq);
+static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
+                                  struct rpc_pipe_bind_state *state,
+                                  DATA_BLOB *credentials);
+static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
+                                    struct rpc_pipe_bind_state *state,
+                                    DATA_BLOB *credentials);
 
 struct tevent_req *rpc_pipe_bind_send(TALLOC_CTX *mem_ctx,
                                      struct event_context *ev,
@@ -1828,9 +1835,11 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
                subreq, struct tevent_req);
        struct rpc_pipe_bind_state *state = tevent_req_data(
                req, struct rpc_pipe_bind_state);
+       struct pipe_auth_data *pauth = state->cli->auth;
        DATA_BLOB reply_pdu;
        struct ncacn_packet *pkt;
        struct dcerpc_auth auth;
+       DATA_BLOB auth_token = data_blob_null;
        NTSTATUS status;
 
        status = rpc_api_pipe_recv(subreq, talloc_tos(), &pkt, &reply_pdu);
@@ -1915,7 +1924,19 @@ static void rpc_pipe_bind_step_one_done(struct tevent_req *subreq)
                break;
 
        case DCERPC_AUTH_TYPE_KRB5:
-               status = NT_STATUS_NOT_IMPLEMENTED;
+               status = gse_get_client_auth_token(state,
+                                                  pauth->a_u.gssapi_state,
+                                                  &auth.credentials,
+                                                  &auth_token);
+               if (!NT_STATUS_IS_OK(status)) {
+                       break;
+               }
+
+               if (gse_require_more_processing(pauth->a_u.gssapi_state)) {
+                       status = rpc_bind_next_send(req, state, &auth_token);
+               } else {
+                       status = rpc_bind_finish_send(req, state, &auth_token);
+               }
                break;
 
        default:
@@ -2041,10 +2062,11 @@ static NTSTATUS rpc_finish_spnego_ntlmssp_bind_send(struct tevent_req *req,
        data_blob_free(&state->rpc_out);
 
        status = create_rpc_alter_context(state,
+                                         auth->auth_type,
+                                         auth->auth_level,
                                          state->rpc_call_id,
                                          &state->cli->abstract_syntax,
                                          &state->cli->transfer_syntax,
-                                         auth->auth_level,
                                          &client_reply,
                                          &state->rpc_out);
        data_blob_free(&client_reply);
@@ -2104,6 +2126,68 @@ static void rpc_bind_ntlmssp_api_done(struct tevent_req *subreq)
        tevent_req_done(req);
 }
 
+static NTSTATUS rpc_bind_next_send(struct tevent_req *req,
+                                  struct rpc_pipe_bind_state *state,
+                                  DATA_BLOB *auth_token)
+{
+       struct pipe_auth_data *auth = state->cli->auth;
+       struct tevent_req *subreq;
+       NTSTATUS status;
+
+       /* Now prepare the alter context pdu. */
+       data_blob_free(&state->rpc_out);
+
+       status = create_rpc_alter_context(state,
+                                         auth->auth_type,
+                                         auth->auth_level,
+                                         state->rpc_call_id,
+                                         &state->cli->abstract_syntax,
+                                         &state->cli->transfer_syntax,
+                                         auth_token,
+                                         &state->rpc_out);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       subreq = rpc_api_pipe_send(state, state->ev, state->cli,
+                                  &state->rpc_out, DCERPC_PKT_ALTER_RESP);
+       if (subreq == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       tevent_req_set_callback(subreq, rpc_pipe_bind_step_one_done, req);
+       return NT_STATUS_OK;
+}
+
+static NTSTATUS rpc_bind_finish_send(struct tevent_req *req,
+                                    struct rpc_pipe_bind_state *state,
+                                    DATA_BLOB *auth_token)
+{
+       struct pipe_auth_data *auth = state->cli->auth;
+       struct tevent_req *subreq;
+       NTSTATUS status;
+
+       /* Now prepare the auth3 context pdu. */
+       data_blob_free(&state->rpc_out);
+
+       status = create_rpc_bind_auth3(state, state->cli,
+                                       state->rpc_call_id,
+                                       auth->auth_type,
+                                       auth->auth_level,
+                                       auth_token,
+                                       &state->rpc_out);
+       if (!NT_STATUS_IS_OK(status)) {
+               return status;
+       }
+
+       subreq = rpc_write_send(state, state->ev, state->cli->transport,
+                               state->rpc_out.data, state->rpc_out.length);
+       if (subreq == NULL) {
+               return NT_STATUS_NO_MEMORY;
+       }
+       tevent_req_set_callback(subreq, rpc_bind_auth3_write_done, req);
+       return NT_STATUS_OK;
+}
+
 NTSTATUS rpc_pipe_bind_recv(struct tevent_req *req)
 {
        return tevent_req_simple_recv_ntstatus(req);