diff options
Diffstat (limited to 'source4')
-rw-r--r-- | source4/nsswitch/winbindd_nss.h | 3 | ||||
-rw-r--r-- | source4/winbind/wb_samba3_cmd.c | 120 | ||||
-rw-r--r-- | source4/winbind/wb_samba3_protocol.c | 6 |
3 files changed, 128 insertions, 1 deletions
diff --git a/source4/nsswitch/winbindd_nss.h b/source4/nsswitch/winbindd_nss.h index 34a6dc4a42..a8830a2379 100644 --- a/source4/nsswitch/winbindd_nss.h +++ b/source4/nsswitch/winbindd_nss.h @@ -186,7 +186,6 @@ struct winbindd_request { pid_t pid; /* pid of calling process */ uint32_t flags; /* flags relavant to a given request */ winbind_string domain_name; /* name of domain for which the request applies */ - int msgid; union { winbind_string winsreq; /* WINS request */ @@ -247,6 +246,8 @@ struct winbindd_request { winbind_string cache_key; } dual_sidaliases; } data; + char *extra_data; + size_t extra_len; char null_term; }; diff --git a/source4/winbind/wb_samba3_cmd.c b/source4/winbind/wb_samba3_cmd.c index 6687c861af..525ed06e30 100644 --- a/source4/winbind/wb_samba3_cmd.c +++ b/source4/winbind/wb_samba3_cmd.c @@ -33,6 +33,7 @@ #include "libcli/smb_composite/smb_composite.h" #include "include/version.h" #include "lib/events/events.h" +#include "librpc/gen_ndr/ndr_netlogon.h" NTSTATUS wbsrv_samba3_interface_version(struct wbsrv_samba3_call *s3call) { @@ -175,3 +176,122 @@ static void lookupname_recv_sid(struct composite_context *ctx) return; } } + +NTSTATUS wbsrv_samba3_pam_auth(struct wbsrv_samba3_call *s3call) +{ + struct wbsrv_service *service = + s3call->call->wbconn->listen_socket->service; + + s3call->response.result = WINBINDD_ERROR; + return NT_STATUS_OK; +} + +NTSTATUS wbsrv_samba3_pam_auth_crap(struct wbsrv_samba3_call *s3call) +{ + struct wbsrv_service *service = + s3call->call->wbconn->listen_socket->service; + struct creds_CredentialState *creds_state; + struct netr_Authenticator auth, auth2; + struct netr_NetworkInfo ninfo; + struct netr_LogonSamLogon r; + NTSTATUS status; + TALLOC_CTX *mem_ctx = talloc_new(s3call); + if (!mem_ctx) { + return NT_STATUS_NO_MEMORY; + } + + ZERO_STRUCT(auth2); + creds_state = cli_credentials_get_netlogon_creds(service->schannel_creds); + + creds_client_authenticator(creds_state, &auth); + + ninfo.identity_info.account_name.string = s3call->request.data.auth_crap.user; + ninfo.identity_info.domain_name.string = s3call->request.data.auth_crap.domain; + ninfo.identity_info.parameter_control = 0; + ninfo.identity_info.logon_id_low = 0; + ninfo.identity_info.logon_id_high = 0; + ninfo.identity_info.workstation.string = s3call->request.data.auth_crap.workstation; + memcpy(ninfo.challenge, s3call->request.data.auth_crap.chal, + sizeof(ninfo.challenge)); + ninfo.nt.length = s3call->request.data.auth_crap.nt_resp_len; + ninfo.nt.data = s3call->request.data.auth_crap.nt_resp; + ninfo.lm.length = s3call->request.data.auth_crap.lm_resp_len; + ninfo.lm.data = s3call->request.data.auth_crap.lm_resp; + + r.in.server_name = talloc_asprintf(mem_ctx, "\\\\%s", dcerpc_server_name(service->netlogon_pipe)); + r.in.workstation = cli_credentials_get_workstation(service->schannel_creds); + r.in.credential = &auth; + r.in.return_authenticator = &auth2; + r.in.logon_level = 2; + r.in.validation_level = 3; + r.in.logon.network = &ninfo; + + r.out.return_authenticator = NULL; + status = dcerpc_netr_LogonSamLogon(service->netlogon_pipe, mem_ctx, &r); + if (!r.out.return_authenticator || + !creds_client_check(creds_state, &r.out.return_authenticator->cred)) { + DEBUG(0, ("Credentials check failed!\n")); + status = NT_STATUS_ACCESS_DENIED; + } + if (NT_STATUS_IS_OK(status)) { + struct netr_SamBaseInfo *base; + switch (r.in.validation_level) { + case 2: + base = &r.out.validation.sam2->base; + break; + case 3: + base = &r.out.validation.sam3->base; + break; + case 6: + base = &r.out.validation.sam6->base; + break; + } + + creds_decrypt_samlogon(creds_state, + r.in.validation_level, + &r.out.validation); + + if ((s3call->request.flags & WBFLAG_PAM_INFO3_NDR) + && (r.in.validation_level == 3)) { + DATA_BLOB tmp_blob, tmp_blob2; + status = ndr_push_struct_blob(&tmp_blob, mem_ctx, r.out.validation.sam3, + (ndr_push_flags_fn_t)ndr_push_netr_SamInfo3); + if (NT_STATUS_IS_OK(status)) { + tmp_blob2 = data_blob_talloc(mem_ctx, NULL, tmp_blob.length + 4); + if (!tmp_blob2.data) { + status = NT_STATUS_NO_MEMORY; + } + } + /* Ugly Samba3 winbind pipe compatability */ + if (NT_STATUS_IS_OK(status)) { + SIVAL(tmp_blob2.data, 0, 1); + memcpy(tmp_blob2.data + 4, tmp_blob.data, tmp_blob.length); + } + s3call->response.extra_data = talloc_steal(s3call, tmp_blob2.data); + s3call->response.length += tmp_blob2.length; + } + if (s3call->request.flags & WBFLAG_PAM_USER_SESSION_KEY) { + memcpy(s3call->response.data.auth.user_session_key, + base->key.key, sizeof(s3call->response.data.auth.user_session_key) /* 16 */); + } + if (s3call->request.flags & WBFLAG_PAM_LMKEY) { + memcpy(s3call->response.data.auth.first_8_lm_hash, + base->LMSessKey.key, sizeof(s3call->response.data.auth.first_8_lm_hash) /* 8 */); + } + } + + if (!NT_STATUS_IS_OK(status)) { + struct winbindd_response *resp = &s3call->response; + resp->result = WINBINDD_ERROR; + } else { + struct winbindd_response *resp = &s3call->response; + resp->result = WINBINDD_OK; + } + + WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.nt_status_string, + nt_errstr(status)); + WBSRV_SAMBA3_SET_STRING(s3call->response.data.auth.error_string, + nt_errstr(status)); + s3call->response.data.auth.pam_error = nt_status_to_pam(status); + return NT_STATUS_OK; +} diff --git a/source4/winbind/wb_samba3_protocol.c b/source4/winbind/wb_samba3_protocol.c index f5e6fb71cf..e99952be96 100644 --- a/source4/winbind/wb_samba3_protocol.c +++ b/source4/winbind/wb_samba3_protocol.c @@ -93,6 +93,12 @@ NTSTATUS wbsrv_samba3_handle_call(struct wbsrv_call *call) case WINBINDD_LOOKUPNAME: return wbsrv_samba3_lookupname(s3call); + + case WINBINDD_PAM_AUTH: + return wbsrv_samba3_pam_auth(s3call); + + case WINBINDD_PAM_AUTH_CRAP: + return wbsrv_samba3_pam_auth_crap(s3call); } s3call->response.result = WINBINDD_ERROR; |