1
0
mirror of https://github.com/samba-team/samba.git synced 2024-12-25 23:21:54 +03:00
samba-mirror/source3/nsswitch/winbindd_pam.c
Andrew Bartlett 60f0627afb This is a farily large patch (3300 lines) and reworks most of the AuthRewrite
code.

In particular this assists tpot in some of his work, becouse it provides the
connection between the authenticaion and the vuid generation.

Major Changes:
	- Fully malloc'ed structures.
	  - Massive rework of the code so that all structures are made and destroyed
	    using malloc and free, rather than hanging around on the stack.
	- SAM_ACCOUNT unix uids and gids are now pointers to the same, to allow them
	   to be declared 'invalid' without the chance that people might get ROOT by
	   default.

	- kill off some of the "DOMAIN\user" lookups.  These can be readded at a more
	  appropriate place (probably domain_client_validate.c) in the future. They
	  don't belong in session setups.

	- Massive introduction of DATA_BLOB structures, particularly for passwords.

	- Use NTLMSSP flags to tell the backend what its getting, rather than magic
	  lenghths.

	- Fix winbind back up again, but tpot is redoing this soon anyway.

	- Abstract much of the work in srv_netlog_nt back into auth helper functions.

This is a LARGE change, and any assistance is testing it is appriciated.

Domain logons are still broken (as far as I can tell) but other functionality
seems
intact.

Needs testing with a wide variety of MS clients.

Andrew Bartlett
(This used to be commit f70fb819b2)
2001-10-31 10:46:25 +00:00

209 lines
6.2 KiB
C

/*
Unix SMB/Netbios implementation.
Version 3.0
Winbind daemon - pam auuth funcions
Copyright (C) Andrew Tridgell 2000
Copyright (C) Tim Potter 2001
Copyright (C) Andrew Bartlett 2001
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
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
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.
*/
#include "winbindd.h"
extern pstring global_myname;
/* Copy of parse_domain_user from winbindd_util.c. Parse a string of the
form DOMAIN/user into a domain and a user */
static void parse_domain_user(char *domuser, fstring domain, fstring user)
{
char *p;
char *sep = lp_winbind_separator();
if (!sep) sep = "\\";
p = strchr(domuser,*sep);
if (!p) p = strchr(domuser,'\\');
if (!p) {
fstrcpy(domain,"");
fstrcpy(user, domuser);
return;
}
fstrcpy(user, p+1);
fstrcpy(domain, domuser);
domain[PTR_DIFF(p, domuser)] = 0;
strupper(domain);
}
/* Return a password structure from a username. Specify whether cached data
can be returned. */
enum winbindd_result winbindd_pam_auth(struct winbindd_cli_state *state)
{
NTSTATUS result;
fstring name_domain, name_user, auth_dc;
int passlen;
unsigned char trust_passwd[16];
time_t last_change_time;
auth_usersupplied_info *user_info;
auth_serversupplied_info *server_info;
DEBUG(3, ("[%5d]: pam auth %s\n", state->pid,
state->request.data.auth.user));
/* Parse domain and username */
parse_domain_user(state->request.data.auth.user, name_domain,
name_user);
/* don't allow the null domain */
if (strcmp(name_domain,"") == 0)
return WINBINDD_ERROR;
passlen = strlen(state->request.data.auth.pass);
if (state->request.data.auth.pass[0]) {
make_user_info_for_winbind(&user_info,
name_user, name_domain,
state->request.data.auth.pass);
} else {
return WINBINDD_ERROR;
}
/*
* Get the machine account password for our primary domain
*/
if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, &last_change_time))
{
DEBUG(0, ("winbindd_pam_auth: could not fetch trust account password for domain %s\n", lp_workgroup()));
return WINBINDD_ERROR;
}
if (!cm_get_dc_name(lp_workgroup(), auth_dc)) {
DEBUG(3, ("Could not find dc for workgroup %s\n",
lp_workgroup()));
return WINBINDD_ERROR;
}
/* So domain_client_validate() actually opens a new connection
for each authentication performed. This can theoretically
be optimised to use an already open IPC$ connection. */
result = domain_client_validate(user_info, &server_info,
auth_dc, trust_passwd,
last_change_time);
free_server_info(&server_info); /* No info needed */
return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
/* Challenge Response Authentication Protocol */
enum winbindd_result winbindd_pam_auth_crap(struct winbindd_cli_state *state)
{
NTSTATUS result;
fstring name_domain, name_user, auth_dc;
unsigned char trust_passwd[16];
time_t last_change_time;
auth_usersupplied_info *user_info;
auth_serversupplied_info *server_info;
DEBUG(3, ("[%5d]: pam auth crap %s\n", state->pid,
state->request.data.auth_crap.user));
/* Parse domain and username */
parse_domain_user(state->request.data.auth_crap.user, name_domain,
name_user);
make_user_info_winbind_crap(&user_info, name_user,
name_domain, state->request.data.auth_crap.chal,
(uchar *)state->request.data.auth_crap.lm_resp, 24,
(uchar *)state->request.data.auth_crap.nt_resp, 24);
/*
* Get the machine account password for our primary domain
*/
if (!secrets_fetch_trust_account_password(lp_workgroup(), trust_passwd, &last_change_time))
{
DEBUG(0, ("winbindd_pam_auth: could not fetch trust account password for domain %s\n", lp_workgroup()));
return WINBINDD_ERROR;
}
if (!cm_get_dc_name(lp_workgroup(), auth_dc)) {
DEBUG(3, ("Could not find dc for workgroup %s\n",
lp_workgroup()));
return WINBINDD_ERROR;
}
/* So domain_client_validate() actually opens a new connection
for each authentication performed. This can theoretically
be optimised to use an already open IPC$ connection. */
result = domain_client_validate(user_info, &server_info,
auth_dc, trust_passwd,
last_change_time);
free_server_info(&server_info); /* No info needed */
return NT_STATUS_IS_OK(result) ? WINBINDD_OK : WINBINDD_ERROR;
}
/* Change a user password */
enum winbindd_result winbindd_pam_chauthtok(struct winbindd_cli_state *state)
{
char *oldpass, *newpass;
fstring domain, user;
uchar nt_oldhash[16];
uchar lm_oldhash[16];
DEBUG(3, ("[%5d]: pam chauthtok %s\n", state->pid,
state->request.data.chauthtok.user));
/* Setup crap */
if (state == NULL) return WINBINDD_ERROR;
parse_domain_user(state->request.data.chauthtok.user, domain, user);
oldpass = state->request.data.chauthtok.oldpass;
newpass = state->request.data.chauthtok.newpass;
nt_lm_owf_gen(oldpass, nt_oldhash, lm_oldhash);
/* Change password */
#if 0
/* XXX */
if (!msrpc_sam_ntchange_pwd(server_state.controller, domain, user,
lm_oldhash, nt_oldhash, newpass)) {
DEBUG(0, ("password change failed for user %s/%s\n", domain, user));
return WINBINDD_ERROR;
}
#endif
return WINBINDD_OK;
}