s4-idmap: Add mapping using uidNumber and gidNumber like idmap_ad
[samba.git] / source4 / winbind / wb_pam_auth.c
index c89870c3a285c74444cb41d290cd2b497705e80e..bcbc6286b58d75aaa7614912746c09dca9c26e1a 100644 (file)
@@ -8,7 +8,7 @@
    
    This program is free software; you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
-   the Free Software Foundation; either version 2 of the License, or
+   the Free Software Foundation; either version 3 of the License, or
    (at your option) any later version.
    
    This program is distributed in the hope that it will be useful,
@@ -17,8 +17,7 @@
    GNU General Public License for more details.
    
    You should have received a copy of the GNU General Public License
-   along with this program; if not, write to the Free Software
-   Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+   along with this program.  If not, see <http://www.gnu.org/licenses/>.
 */
 
 #include "includes.h"
 #include "auth/credentials/credentials.h"
 #include "libcli/auth/libcli_auth.h"
 #include "librpc/gen_ndr/ndr_netlogon.h"
-#include "librpc/gen_ndr/ndr_netlogon_c.h"
+#include "librpc/gen_ndr/winbind.h"
+#include "param/param.h"
 
 /* Oh, there is so much to keep an eye on when authenticating a user.  Oh my! */
 struct pam_auth_crap_state {
        struct composite_context *ctx;
-       struct event_context *event_ctx;
-       uint32_t logon_parameters;
-       const char *domain_name;
-       const char *user_name;
+       struct tevent_context *event_ctx;
+       struct loadparm_context *lp_ctx;
+
+       struct winbind_SamLogon *req;
        char *unix_username;
-       const char *workstation;
-       DATA_BLOB chal, nt_resp, lm_resp;
 
-        struct creds_CredentialState *creds_state;
-        struct netr_Authenticator auth, auth2;
         struct netr_NetworkInfo ninfo;
         struct netr_LogonSamLogon r;
 
+       const char *user_name;
+       const char *domain_name;
+
        struct netr_UserSessionKey user_session_key;
        struct netr_LMSessionKey lm_key;
        DATA_BLOB info3;
@@ -55,8 +54,7 @@ struct pam_auth_crap_state {
  * NTLM authentication.
 */
 
-static void pam_auth_crap_recv_domain(struct composite_context *ctx);
-static void pam_auth_crap_recv_samlogon(struct rpc_request *req);
+static void pam_auth_crap_recv_logon(struct composite_context *ctx);
 
 struct composite_context *wb_cmd_pam_auth_crap_send(TALLOC_CTX *mem_ctx,
                                                    struct wbsrv_service *service,
@@ -70,6 +68,8 @@ struct composite_context *wb_cmd_pam_auth_crap_send(TALLOC_CTX *mem_ctx,
 {
        struct composite_context *result, *ctx;
        struct pam_auth_crap_state *state;
+       struct netr_NetworkInfo *ninfo;
+       DATA_BLOB tmp_nt_resp, tmp_lm_resp;
 
        result = composite_create(mem_ctx, service->task->event_ctx);
        if (result == NULL) goto failed;
@@ -77,37 +77,46 @@ struct composite_context *wb_cmd_pam_auth_crap_send(TALLOC_CTX *mem_ctx,
        state = talloc(result, struct pam_auth_crap_state);
        if (state == NULL) goto failed;
        state->ctx = result;
+       state->lp_ctx = service->task->lp_ctx;
        result->private_data = state;
 
-       state->logon_parameters = logon_parameters;
+       state->req = talloc(state, struct winbind_SamLogon);
+
+       state->req->in.logon_level = 2;
+       state->req->in.validation_level = 3;
+       ninfo = state->req->in.logon.network = talloc(state, struct netr_NetworkInfo);
+       if (ninfo == NULL) goto failed;
+       
+       ninfo->identity_info.account_name.string =  talloc_strdup(state, user);
+       ninfo->identity_info.domain_name.string =  talloc_strdup(state, domain);
+       ninfo->identity_info.parameter_control = logon_parameters;
+       ninfo->identity_info.logon_id_low = 0;
+       ninfo->identity_info.logon_id_high = 0;
+       ninfo->identity_info.workstation.string = talloc_strdup(state, workstation);
+
+       SMB_ASSERT(chal.length == sizeof(ninfo->challenge));
+       memcpy(ninfo->challenge, chal.data,
+              sizeof(ninfo->challenge));
+
+       tmp_nt_resp = data_blob_talloc(ninfo, nt_resp.data, nt_resp.length);
+       if ((nt_resp.data != NULL) &&
+           (tmp_nt_resp.data == NULL)) goto failed;
 
-       state->domain_name = talloc_strdup(state, domain);
-       if (state->domain_name == NULL) goto failed;
+       tmp_lm_resp = data_blob_talloc(ninfo, lm_resp.data, lm_resp.length);
+       if ((lm_resp.data != NULL) &&
+           (tmp_lm_resp.data == NULL)) goto failed;
 
-       state->user_name = talloc_strdup(state, user);
-       if (state->user_name == NULL) goto failed;
+       ninfo->nt.length = tmp_nt_resp.length;
+       ninfo->nt.data = tmp_nt_resp.data;
+       ninfo->lm.length = tmp_lm_resp.length;
+       ninfo->lm.data = tmp_lm_resp.data;
 
        state->unix_username = NULL;
 
-       state->workstation = talloc_strdup(state, workstation);
-       if (state->workstation == NULL) goto failed;
-
-       state->chal = data_blob_talloc(state, chal.data, chal.length);
-       if ((chal.data != NULL) && (state->chal.data == NULL)) goto failed;
-
-       state->nt_resp = data_blob_talloc(state, nt_resp.data, nt_resp.length);
-       if ((nt_resp.data != NULL) &&
-           (state->nt_resp.data == NULL)) goto failed;
-
-       state->lm_resp = data_blob_talloc(state, lm_resp.data, lm_resp.length);
-       if ((lm_resp.data != NULL) &&
-           (state->lm_resp.data == NULL)) goto failed;
-
-       ctx = wb_sid2domain_send(state, service, service->primary_sid);
+       ctx = wb_sam_logon_send(mem_ctx, service, state->req);
        if (ctx == NULL) goto failed;
 
-       ctx->async.fn = pam_auth_crap_recv_domain;
-       ctx->async.private_data = state;
+       composite_continue(result, ctx, pam_auth_crap_recv_logon, state);
        return result;
 
  failed:
@@ -120,96 +129,25 @@ struct composite_context *wb_cmd_pam_auth_crap_send(TALLOC_CTX *mem_ctx,
 
     Send of a SamLogon request to authenticate a user.
 */
-static void pam_auth_crap_recv_domain(struct composite_context *ctx)
+static void pam_auth_crap_recv_logon(struct composite_context *ctx)
 {
+       DATA_BLOB tmp_blob;
+       enum ndr_err_code ndr_err;
+       struct netr_SamBaseInfo *base;
        struct pam_auth_crap_state *state =
                talloc_get_type(ctx->async.private_data,
                                struct pam_auth_crap_state);
-       struct rpc_request *req;
-       struct wbsrv_domain *domain;
-
-       state->ctx->status = wb_sid2domain_recv(ctx, &domain);
-       state->creds_state =
-               cli_credentials_get_netlogon_creds(domain->schannel_creds);
-
-       creds_client_authenticator(state->creds_state, &state->auth);
-
-       state->ninfo.identity_info.account_name.string = state->user_name;
-       state->ninfo.identity_info.domain_name.string =  state->domain_name;
-       state->ninfo.identity_info.parameter_control = state->logon_parameters;
-       state->ninfo.identity_info.logon_id_low = 0;
-       state->ninfo.identity_info.logon_id_high = 0;
-       state->ninfo.identity_info.workstation.string = state->workstation;
-
-       SMB_ASSERT(state->chal.length == sizeof(state->ninfo.challenge));
-       memcpy(state->ninfo.challenge, state->chal.data,
-              sizeof(state->ninfo.challenge));
-
-       state->ninfo.nt.length = state->nt_resp.length;
-       state->ninfo.nt.data = state->nt_resp.data;
-       state->ninfo.lm.length = state->lm_resp.length;
-       state->ninfo.lm.data = state->lm_resp.data;
-
-       state->r.in.server_name = talloc_asprintf(
-               state, "\\\\%s", dcerpc_server_name(domain->netlogon_pipe));
-       if (composite_nomem(state->r.in.server_name, state->ctx)) return;
-
-       ZERO_STRUCT(state->auth2);
-
-       state->r.in.computer_name =
-               cli_credentials_get_workstation(domain->schannel_creds);
-       state->r.in.credential = &state->auth;
-       state->r.in.return_authenticator = &state->auth2;
-       state->r.in.logon_level = 2;
-       state->r.in.validation_level = 3;
-       state->r.in.logon.network = &state->ninfo;
-       state->r.out.return_authenticator = NULL;
-
-       req = dcerpc_netr_LogonSamLogon_send(domain->netlogon_pipe, state,
-                                            &state->r);
-       composite_continue_rpc(state->ctx, req, pam_auth_crap_recv_samlogon,
-                              state);
-}
-
-/* 
-   NTLM Authentication 
-   
-   Check the SamLogon reply, decrypt and parse out the session keys and the
-   info3 structure.
-*/
-static void pam_auth_crap_recv_samlogon(struct rpc_request *req)
-{
-       struct pam_auth_crap_state *state =
-               talloc_get_type(req->async.private,
-                               struct pam_auth_crap_state);
-       struct netr_SamBaseInfo *base;
-       DATA_BLOB tmp_blob;
-
-       state->ctx->status = dcerpc_ndr_request_recv(req);
-       if (!composite_is_ok(state->ctx)) return;
-
-       if ((state->r.out.return_authenticator == NULL) ||
-           (!creds_client_check(state->creds_state,
-                                &state->r.out.return_authenticator->cred))) {
-               DEBUG(0, ("Credentials check failed!\n"));
-               composite_error(state->ctx, NT_STATUS_ACCESS_DENIED);
-               return;
-       }
 
-       state->ctx->status = state->r.out.result;
+       state->ctx->status = wb_sam_logon_recv(ctx, state, state->req);
        if (!composite_is_ok(state->ctx)) return;
 
-       /* Decrypt the session keys before we reform the info3, so the
-        * person on the other end of winbindd pipe doesn't have to.
-        * They won't have the encryption key anyway */
-       creds_decrypt_samlogon(state->creds_state,
-                              state->r.in.validation_level,
-                              &state->r.out.validation);
-
-       state->ctx->status = ndr_push_struct_blob(
-               &tmp_blob, state, state->r.out.validation.sam3,
+       ndr_err = ndr_push_struct_blob(
+               &tmp_blob, state, state->req->out.validation.sam3,
                (ndr_push_flags_fn_t)ndr_push_netr_SamInfo3);
-       if (!composite_is_ok(state->ctx)) return;
+       if (!NDR_ERR_CODE_IS_SUCCESS(ndr_err)) {
+               state->ctx->status = ndr_map_error2ntstatus(ndr_err);
+               if (!composite_is_ok(state->ctx)) return;
+       }
 
        /* The Samba3 protocol is a bit broken (due to non-IDL
         * heritage, so for compatability we must add a non-zero 4
@@ -220,25 +158,7 @@ static void pam_auth_crap_recv_samlogon(struct rpc_request *req)
        SIVAL(state->info3.data, 0, 1);
        memcpy(state->info3.data+4, tmp_blob.data, tmp_blob.length);
 
-       /* We actually only ask for level 3, and assume it above, but 
-         * anyway... */
-
-       base = NULL;
-       switch(state->r.in.validation_level) {
-       case 2:
-               base = &state->r.out.validation.sam2->base;
-               break;
-       case 3:
-               base = &state->r.out.validation.sam3->base;
-               break;
-       case 6:
-               base = &state->r.out.validation.sam6->base;
-               break;
-       }
-       if (base == NULL) {
-               composite_error(state->ctx, NT_STATUS_INTERNAL_ERROR);
-               return;
-       }
+       base = &state->req->out.validation.sam3->base;
 
        state->user_session_key = base->key;
        state->lm_key = base->LMSessKey;
@@ -250,14 +170,14 @@ static void pam_auth_crap_recv_samlogon(struct rpc_request *req)
                state->user_name = base->account_name.string;
                talloc_steal(state, base->account_name.string);
        }
-       if (base->domain.string) {
-               state->domain_name = base->domain.string;
-               talloc_steal(state, base->domain.string);
+       if (base->logon_domain.string) {
+               state->domain_name = base->logon_domain.string;
+               talloc_steal(state, base->logon_domain.string);
        }
 
        state->unix_username = talloc_asprintf(state, "%s%s%s", 
                                               state->domain_name,
-                                              lp_winbind_separator(),
+                                              lpcfg_winbind_separator(state->lp_ctx),
                                               state->user_name);
        if (composite_nomem(state->unix_username, state->ctx)) return;
 
@@ -292,36 +212,23 @@ NTSTATUS wb_cmd_pam_auth_crap_recv(struct composite_context *c,
 
 struct composite_context *wb_cmd_pam_auth_send(TALLOC_CTX *mem_ctx,
                                               struct wbsrv_service *service,
-                                              const char *domain,
-                                              const char *user,
-                                              const char *password)
+                                              struct cli_credentials *credentials)
 {
-       struct cli_credentials *credentials;
        const char *workstation;
        NTSTATUS status;
-
+       const char *user, *domain;
        DATA_BLOB chal, nt_resp, lm_resp, names_blob;
        int flags = CLI_CRED_NTLM_AUTH;
-       if (lp_client_lanman_auth()) {
+       if (lpcfg_client_lanman_auth(service->task->lp_ctx)) {
                flags |= CLI_CRED_LANMAN_AUTH;
        }
 
-       if (lp_client_ntlmv2_auth()) {
+       if (lpcfg_client_ntlmv2_auth(service->task->lp_ctx)) {
                flags |= CLI_CRED_NTLMv2_AUTH;
        }
 
        DEBUG(5, ("wbsrv_samba3_pam_auth called\n"));
 
-       credentials = cli_credentials_init(mem_ctx);
-       if (!credentials) {
-               return NULL;
-       }
-       cli_credentials_set_conf(credentials);
-       cli_credentials_set_domain(credentials, domain, CRED_SPECIFIED);
-       cli_credentials_set_username(credentials, user, CRED_SPECIFIED);
-
-       cli_credentials_set_password(credentials, password, CRED_SPECIFIED);
-
        chal = data_blob_talloc(mem_ctx, NULL, 8);
        if (!chal.data) {
                return NULL;
@@ -346,16 +253,36 @@ struct composite_context *wb_cmd_pam_auth_send(TALLOC_CTX *mem_ctx,
                return NULL;
        }
        return wb_cmd_pam_auth_crap_send(mem_ctx, service,
-                                        0 /* logon parameters */, 
+                                        MSV1_0_ALLOW_WORKSTATION_TRUST_ACCOUNT|MSV1_0_ALLOW_SERVER_TRUST_ACCOUNT /* logon parameters */, 
                                         domain, user, workstation,
                                         chal, nt_resp, lm_resp);
 }
 
-NTSTATUS wb_cmd_pam_auth_recv(struct composite_context *c)
+NTSTATUS wb_cmd_pam_auth_recv(struct composite_context *c,
+                             TALLOC_CTX *mem_ctx,
+                             DATA_BLOB *info3,
+                             struct netr_UserSessionKey *user_session_key,
+                             struct netr_LMSessionKey *lm_key,
+                             char **unix_username)
 {
-       struct pam_auth_crap_state *state =
-               talloc_get_type(c->private_data, struct pam_auth_crap_state);
-       NTSTATUS status = composite_wait(c);
-       talloc_free(state);
-       return status;
+       struct pam_auth_crap_state *state =
+               talloc_get_type(c->private_data, struct pam_auth_crap_state);
+       NTSTATUS status = composite_wait(c);
+       if (NT_STATUS_IS_OK(status)) {
+               if (info3) {
+                       info3->length = state->info3.length;
+                       info3->data = talloc_steal(mem_ctx, state->info3.data);
+               }
+               if (user_session_key) {
+                       *user_session_key = state->user_session_key;
+               }
+               if (lm_key) {
+                       *lm_key = state->lm_key;
+               }
+               if (unix_username) {
+                       *unix_username = talloc_steal(mem_ctx, state->unix_username);
+               }
+       }
+       talloc_free(state);
+       return status;
 }