diff options
Diffstat (limited to 'source4/auth')
-rw-r--r-- | source4/auth/auth_winbind.c | 129 | ||||
-rw-r--r-- | source4/auth/config.mk | 2 |
2 files changed, 124 insertions, 7 deletions
diff --git a/source4/auth/auth_winbind.c b/source4/auth/auth_winbind.c index 3783d0f975..209f8dc858 100644 --- a/source4/auth/auth_winbind.c +++ b/source4/auth/auth_winbind.c @@ -26,6 +26,8 @@ #include "auth/auth.h" #include "nsswitch/winbind_client.h" #include "librpc/gen_ndr/ndr_netlogon.h" +#include "librpc/gen_ndr/ndr_winbind.h" +#include "lib/messaging/irpc.h" static NTSTATUS get_info3_from_ndr(TALLOC_CTX *mem_ctx, struct winbindd_response *response, struct netr_SamInfo3 *info3) { @@ -58,11 +60,14 @@ static NTSTATUS winbind_want_check(struct auth_method_context *ctx, return NT_STATUS_OK; } -/* Authenticate a user with a challenge/response */ -static NTSTATUS winbind_check_password(struct auth_method_context *ctx, - TALLOC_CTX *mem_ctx, - const struct auth_usersupplied_info *user_info, - struct auth_serversupplied_info **server_info) +/* + Authenticate a user with a challenge/response + using the samba3 winbind protocol +*/ +static NTSTATUS winbind_check_password_samba3(struct auth_method_context *ctx, + TALLOC_CTX *mem_ctx, + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) { struct winbindd_request request; struct winbindd_response response; @@ -138,6 +143,111 @@ static NTSTATUS winbind_check_password(struct auth_method_context *ctx, return nt_status; } +struct winbind_check_password_state { + struct winbind_SamLogon req; +}; + +/* + Authenticate a user with a challenge/response + using IRPC to the winbind task +*/ +static NTSTATUS winbind_check_password(struct auth_method_context *ctx, + TALLOC_CTX *mem_ctx, + const struct auth_usersupplied_info *user_info, + struct auth_serversupplied_info **server_info) +{ + NTSTATUS status; + uint32_t *winbind_servers; + struct winbind_check_password_state *s; + const struct auth_usersupplied_info *user_info_new; + struct netr_IdentityInfo *identity_info; + + winbind_servers = irpc_servers_byname(ctx->auth_ctx->msg_ctx, "winbind_server"); + if ((winbind_servers == NULL) || (winbind_servers[0] == 0)) { + DEBUG(0, ("Winbind authentication for [%s]\\[%s] failed, " + "no winbind_server running!\n", + user_info->client.domain_name, user_info->client.account_name)); + return NT_STATUS_NO_LOGON_SERVERS; + } + + s = talloc(mem_ctx, struct winbind_check_password_state); + NT_STATUS_HAVE_NO_MEMORY(s); + + if (user_info->flags & USER_INFO_INTERACTIVE_LOGON) { + struct netr_PasswordInfo *password_info; + + status = encrypt_user_info(s, ctx->auth_ctx, AUTH_PASSWORD_HASH, + user_info, &user_info_new); + NT_STATUS_NOT_OK_RETURN(status); + user_info = user_info_new; + + password_info = talloc(s, struct netr_PasswordInfo); + NT_STATUS_HAVE_NO_MEMORY(password_info); + + password_info->lmpassword = *user_info->password.hash.lanman; + password_info->ntpassword = *user_info->password.hash.nt; + + identity_info = &password_info->identity_info; + s->req.in.logon_level = 1; + s->req.in.logon.password= password_info; + } else { + struct netr_NetworkInfo *network_info; + const uint8_t *challenge; + + status = encrypt_user_info(s, ctx->auth_ctx, AUTH_PASSWORD_RESPONSE, + user_info, &user_info_new); + NT_STATUS_NOT_OK_RETURN(status); + user_info = user_info_new; + + network_info = talloc(s, struct netr_NetworkInfo); + NT_STATUS_HAVE_NO_MEMORY(network_info); + + status = auth_get_challenge(ctx->auth_ctx, &challenge); + NT_STATUS_NOT_OK_RETURN(status); + + memcpy(network_info->challenge, challenge, sizeof(network_info->challenge)); + + network_info->nt.length = user_info->password.response.nt.length; + network_info->nt.data = user_info->password.response.nt.data; + + network_info->nt.length = user_info->password.response.lanman.length; + network_info->nt.data = user_info->password.response.lanman.data; + + identity_info = &network_info->identity_info; + s->req.in.logon_level = 2; + s->req.in.logon.network = network_info; + } + + identity_info->domain_name.string = user_info->client.domain_name; + identity_info->parameter_control = user_info->logon_parameters; /* see MSV1_0_* */ + identity_info->logon_id_low = 0; + identity_info->logon_id_high = 0; + identity_info->account_name.string = user_info->client.account_name; + identity_info->workstation.string = user_info->workstation_name; + + s->req.in.validation_level = 3; + status = IRPC_CALL(ctx->auth_ctx->msg_ctx, winbind_servers[0], + winbind, WINBIND_SAMLOGON, + &s->req, s); + NT_STATUS_NOT_OK_RETURN(status); + + status = make_server_info_netlogon_validation(mem_ctx, + user_info->client.account_name, + s->req.in.validation_level, + &s->req.out.validation, + server_info); + NT_STATUS_NOT_OK_RETURN(status); + + return NT_STATUS_OK; +} + +static const struct auth_operations winbind_samba3_ops = { + .name = "winbind_samba3", + .get_challenge = auth_get_challenge_not_implemented, + .want_check = winbind_want_check, + .check_password = winbind_check_password_samba3 +}; + static const struct auth_operations winbind_ops = { .name = "winbind", .get_challenge = auth_get_challenge_not_implemented, @@ -149,10 +259,17 @@ NTSTATUS auth_winbind_init(void) { NTSTATUS ret; + ret = auth_register(&winbind_samba3_ops); + if (!NT_STATUS_IS_OK(ret)) { + DEBUG(0,("Failed to register 'winbind_samba3' auth backend!\n")); + return ret; + } + ret = auth_register(&winbind_ops); if (!NT_STATUS_IS_OK(ret)) { DEBUG(0,("Failed to register 'winbind' auth backend!\n")); return ret; } - return ret; + + return NT_STATUS_OK; } diff --git a/source4/auth/config.mk b/source4/auth/config.mk index 9534f23023..d692115321 100644 --- a/source4/auth/config.mk +++ b/source4/auth/config.mk @@ -36,7 +36,7 @@ OBJ_FILES = auth_anonymous.o INIT_FUNCTION = auth_winbind_init SUBSYSTEM = auth OBJ_FILES = auth_winbind.o -PUBLIC_DEPENDENCIES = LIBWINBIND-CLIENT NDR_NETLOGON LIBNDR +PUBLIC_DEPENDENCIES = NDR_WINBIND MESSAGING LIBWINBIND-CLIENT # End MODULE auth_winbind ####################### |