1
0
mirror of https://github.com/samba-team/samba.git synced 2025-03-25 14:50:24 +03:00

rewrote the password server code using the new clientgen.c client

interface

The new code uses a source netbios name equal to the Samba servers
name, not the client name. It also uses NetWkstaUserLogon to do a full
network logon. This means it will honour the servers logon
restrictions (such as login times etc).
(This used to be commit 11de90f972f6d83974425e80014f54e15d495413)
This commit is contained in:
Andrew Tridgell 1997-10-21 09:34:33 +00:00
parent 8adc95a55a
commit 0891bb6a91
4 changed files with 226 additions and 262 deletions

View File

@ -989,6 +989,32 @@ struct smb_passwd
};
struct cli_state {
int fd;
int cnum;
int pid;
int mid;
int uid;
int protocol;
int sec_mode;
int error;
int privilages;
fstring eff_name;
fstring desthost;
char cryptkey[8];
uint32 sesskey;
int serverzone;
uint32 servertime;
int readbraw_supported;
int writebraw_supported;
int timeout;
int max_xmit;
char *outbuf;
char *inbuf;
int bufsize;
int initialised;
};
struct current_user
{
int cnum, id;

View File

@ -1475,206 +1475,143 @@ BOOL check_hosts_equiv(char *user)
}
int password_client = -1;
static fstring pserver;
static char *secserver_inbuf = NULL;
static struct cli_state cli;
/****************************************************************************
attempted support for server level security
return the client state structure
****************************************************************************/
BOOL server_cryptkey(char *buf)
struct cli_state *server_client(void)
{
pstring outbuf;
fstring pass_protocol;
extern fstring remote_machine;
char *p;
int len;
fstring desthost;
struct in_addr dest_ip;
int port = SMB_PORT;
BOOL ret;
if(secserver_inbuf == NULL) {
secserver_inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
if(secserver_inbuf == NULL) {
DEBUG(0,("server_cryptkey: malloc fail for input buffer.\n"));
return False;
}
}
if (password_client >= 0)
close(password_client);
password_client = -1;
if (Protocol < PROTOCOL_NT1) {
strcpy(pass_protocol,"LM1.2X002");
} else {
strcpy(pass_protocol,"NT LM 0.12");
}
bzero(secserver_inbuf,BUFFER_SIZE + SAFETY_MARGIN);
bzero(outbuf,sizeof(outbuf));
for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) {
strcpy(desthost,p);
standard_sub_basic(desthost);
strupper(desthost);
dest_ip = *interpret_addr2(desthost);
if (zero_ip(dest_ip)) {
DEBUG(1,("Can't resolve address for %s\n",p));
continue;
}
if (ismyip(dest_ip)) {
DEBUG(1,("Password server loop - disabling password server %s\n",p));
continue;
}
password_client = open_socket_out(SOCK_STREAM, &dest_ip, port, SHORT_CONNECT_TIMEOUT);
if (password_client >= 0) {
DEBUG(3,("connected to password server %s\n",p));
StrnCpy(pserver,p,sizeof(pserver)-1);
break;
}
}
if (password_client < 0) {
DEBUG(1,("password server not available\n"));
return(False);
}
/* send a session request (RFC 8002) */
/* put in the destination name */
len = 4;
p = outbuf+len;
name_mangle(desthost,p,' ');
len += name_len(p);
p = outbuf+len;
/* and my name */
/* Fix from Frank Varnavas <varnavas@ny.ubs.com>.
We cannot use the same name as the client to
the NT password server, as NT will drop client
connections if the same client name connects
twice. Instead, synthesize a name from our pid.
and the remote machine name.
*/
{
char buf2[32]; /* create name as PIDname */
sprintf(buf2,"%d", getpid());
strncpy(&buf2[strlen(buf2)], remote_machine, 31 - strlen(buf2));
buf2[31] = '\0';
DEBUG(1,("negprot w/password server as %s\n",buf2));
name_mangle(buf2,p,' ');
len += name_len(p);
}
_smb_setlen(outbuf,len);
CVAL(outbuf,0) = 0x81;
send_smb(password_client,outbuf);
if (!receive_smb(password_client,secserver_inbuf,5000) ||
CVAL(secserver_inbuf,0) != 0x82) {
DEBUG(1,("%s rejected the session\n",pserver));
close(password_client); password_client = -1;
return(False);
}
DEBUG(3,("got session\n"));
bzero(outbuf,smb_size);
/* setup the protocol string */
set_message(outbuf,0,strlen(pass_protocol)+2,True);
p = smb_buf(outbuf);
*p++ = 2;
strcpy(p,pass_protocol);
CVAL(outbuf,smb_com) = SMBnegprot;
CVAL(outbuf,smb_flg) = 0x8;
SSVAL(outbuf,smb_flg2,0x1);
send_smb(password_client,outbuf);
ret = receive_smb(password_client,secserver_inbuf,5000);
if (!ret || CVAL(secserver_inbuf,smb_rcls) || SVAL(secserver_inbuf,smb_vwv0)) {
DEBUG(1,("%s rejected the protocol\n",pserver));
close(password_client); password_client= -1;
return(False);
}
if (!(CVAL(secserver_inbuf,smb_vwv1) & 1)) {
DEBUG(1,("%s isn't in user level security mode\n",pserver));
close(password_client); password_client= -1;
return(False);
}
memcpy(buf,secserver_inbuf,smb_len(secserver_inbuf)+4);
DEBUG(3,("password server OK\n"));
return(True);
return &cli;
}
/****************************************************************************
support for server level security
****************************************************************************/
BOOL server_validate(char *buf)
struct cli_state *server_cryptkey(void)
{
pstring outbuf;
BOOL ret;
fstring desthost;
struct in_addr dest_ip;
extern fstring local_machine;
char *p;
if(secserver_inbuf == NULL) {
secserver_inbuf = (char *)malloc(BUFFER_SIZE + SAFETY_MARGIN);
if(secserver_inbuf == NULL) {
DEBUG(0,("server_validate: malloc fail for input buffer.\n"));
return False;
}
}
if (!cli_initialise(&cli))
return NULL;
for (p=strtok(lp_passwordserver(),LIST_SEP); p ; p = strtok(NULL,LIST_SEP)) {
fstrcpy(desthost,p);
standard_sub_basic(desthost);
strupper(desthost);
if (password_client < 0) {
DEBUG(1,("%s not connected\n",pserver));
return(False);
}
dest_ip = *interpret_addr2(desthost);
if (zero_ip(dest_ip)) {
DEBUG(1,("Can't resolve address for %s\n",p));
continue;
}
bzero(secserver_inbuf,BUFFER_SIZE + SAFETY_MARGIN);
memcpy(outbuf,buf,sizeof(outbuf));
if (ismyip(dest_ip)) {
DEBUG(1,("Password server loop - disabling password server %s\n",p));
continue;
}
/* send a session setup command */
CVAL(outbuf,smb_flg) = 0x8;
SSVAL(outbuf,smb_flg2,0x1);
CVAL(outbuf,smb_vwv0) = 0xFF;
if (cli_connect(&cli, desthost, &dest_ip)) {
DEBUG(3,("connected to password server %s\n",p));
break;
}
}
set_message(outbuf,smb_numwords(outbuf),smb_buflen(outbuf),False);
if (!p) {
DEBUG(1,("password server not available\n"));
cli_shutdown(&cli);
return NULL;
}
SCVAL(secserver_inbuf,smb_rcls,1);
if (!cli_session_request(&cli, desthost, 0x20, local_machine)) {
DEBUG(1,("%s rejected the session\n",desthost));
cli_shutdown(&cli);
return NULL;
}
send_smb(password_client,outbuf);
ret = receive_smb(password_client,secserver_inbuf,5000);
DEBUG(3,("got session\n"));
if (!ret || CVAL(secserver_inbuf,smb_rcls) != 0) {
DEBUG(1,("password server %s rejected the password\n",pserver));
return(False);
}
if (!cli_negprot(&cli)) {
DEBUG(1,("%s rejected the negprot\n",desthost));
cli_shutdown(&cli);
return NULL;
}
/* if logged in as guest then reject */
if ((SVAL(secserver_inbuf,smb_vwv2) & 1) != 0) {
DEBUG(1,("password server %s gave us guest only\n",pserver));
return(False);
}
if (cli.protocol < PROTOCOL_LANMAN2 ||
!(cli.sec_mode & 1)) {
DEBUG(1,("%s isn't in user level security mode\n",desthost));
cli_shutdown(&cli);
return NULL;
}
DEBUG(3,("password server %s accepted the password\n",pserver));
DEBUG(3,("password server OK\n"));
#if !KEEP_PASSWORD_SERVER_OPEN
close(password_client); password_client= -1;
#endif
return &cli;
}
return(True);
/****************************************************************************
validate a password with the password server
****************************************************************************/
BOOL server_validate(char *user, char *domain,
char *pass, int passlen,
char *ntpass, int ntpasslen)
{
extern fstring local_machine;
fstring share;
if (!cli.initialised) {
DEBUG(1,("password server %s is not connected\n", cli.desthost));
return(False);
}
if (!cli_session_setup(&cli, user, pass, passlen, ntpass, ntpasslen, domain)) {
DEBUG(1,("password server %s rejected the password\n", cli.desthost));
return False;
}
/* if logged in as guest then reject */
if ((SVAL(cli.inbuf,smb_vwv2) & 1) != 0) {
DEBUG(1,("password server %s gave us guest only\n", cli.desthost));
return(False);
}
sprintf(share,"\\\\%s\\IPC$", cli.desthost);
if (!cli_send_tconX(&cli, share, "IPC", "", 1)) {
DEBUG(1,("password server %s refused IPC$ connect\n", cli.desthost));
return False;
}
if (!cli_NetWkstaUserLogon(&cli,user,local_machine)) {
DEBUG(1,("password server %s failed NetWkstaUserLogon\n", cli.desthost));
cli_tdis(&cli);
return False;
}
if (cli.privilages == 0) {
DEBUG(1,("password server %s gave guest privilages\n", cli.desthost));
cli_tdis(&cli);
return False;
}
if (!strequal(cli.eff_name, user)) {
DEBUG(1,("password server %s gave different username %s\n",
cli.desthost,
cli.eff_name));
cli_tdis(&cli);
return False;
}
DEBUG(3,("password server %s accepted the password\n", cli.desthost));
cli_tdis(&cli);
return(True);
}

View File

@ -379,8 +379,10 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
BOOL computer_id=False;
static BOOL done_sesssetup = False;
BOOL doencrypt = SMBENCRYPT();
char *domain = "";
*smb_apasswd = 0;
*smb_ntpasswd = 0;
smb_bufsize = SVAL(inbuf,smb_vwv2);
smb_mpxmax = SVAL(inbuf,smb_vwv3);
@ -469,8 +471,10 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
p += passlen1 + passlen2;
fstrcpy(user,p); p = skip_string(p,1);
domain = p;
DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
p,skip_string(p,1),skip_string(p,2)));
domain,skip_string(p,1),skip_string(p,2)));
}
@ -533,7 +537,10 @@ int reply_sesssetup_and_X(char *inbuf,char *outbuf,int length,int bufsize)
if(!guest && strequal(user,lp_guestaccount(-1)) && (*smb_apasswd == 0))
guest = True;
if (!guest && !(lp_security() == SEC_SERVER && server_validate(inbuf)) &&
if (!guest && !(lp_security() == SEC_SERVER &&
server_validate(user, domain,
smb_apasswd, smb_apasslen,
smb_ntpasswd, smb_ntpasslen)) &&
!check_hosts_equiv(user))
{

View File

@ -2320,22 +2320,21 @@ static int sig_cld()
**************************************************************************/
static int sig_pipe()
{
extern int password_client;
BlockSignals(True,SIGPIPE);
struct cli_state *cli;
BlockSignals(True,SIGPIPE);
if (password_client != -1) {
DEBUG(3,("lost connection to password server\n"));
close(password_client);
password_client = -1;
if ((cli = server_client()) && cli->initialised) {
DEBUG(3,("lost connection to password server\n"));
cli_shutdown(cli);
#ifndef DONT_REINSTALL_SIG
signal(SIGPIPE, SIGNAL_CAST sig_pipe);
signal(SIGPIPE, SIGNAL_CAST sig_pipe);
#endif
BlockSignals(False,SIGPIPE);
return 0;
}
BlockSignals(False,SIGPIPE);
return 0;
}
exit_server("Got sigpipe\n");
return(0);
exit_server("Got sigpipe\n");
return(0);
}
/****************************************************************************
@ -3564,11 +3563,6 @@ int reply_lanman1(char *outbuf)
Protocol = PROTOCOL_LANMAN1;
if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
DEBUG(3,("using password server validation\n"));
if (doencrypt) set_challenge(smb_buf(outbuf));
}
CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
SSVAL(outbuf,smb_vwv2,max_recv);
@ -3594,32 +3588,42 @@ int reply_lanman2(char *outbuf)
int secword=0;
BOOL doencrypt = SMBENCRYPT();
time_t t = time(NULL);
/* We need to save and restore this as it can be destroyed
if we call another server if security=server
Thanks to Paul Nelson @ Thursby for pointing this out.
*/
uint16 mid = SVAL(outbuf, smb_mid);
struct cli_state *cli = NULL;
char cryptkey[8];
char crypt_len = 0;
if (lp_security() == SEC_SERVER) {
cli = server_cryptkey();
}
if (cli) {
DEBUG(3,("using password server validation\n"));
doencrypt = ((cli->sec_mode & 2) != 0);
}
if (lp_security()>=SEC_USER) secword |= 1;
if (doencrypt) secword |= 2;
set_message(outbuf,13,doencrypt?8:0,True);
if (doencrypt) {
crypt_len = 8;
if (!cli) {
generate_next_challenge(cryptkey);
} else {
memcpy(cryptkey, cli->cryptkey, 8);
set_challenge(cli->cryptkey);
}
}
set_message(outbuf,13,crypt_len,True);
SSVAL(outbuf,smb_vwv1,secword);
/* Create a token value and add it to the outgoing packet. */
if (doencrypt)
generate_next_challenge(smb_buf(outbuf));
memcpy(smb_buf(outbuf), cryptkey, 8);
SIVAL(outbuf,smb_vwv6,getpid());
Protocol = PROTOCOL_LANMAN2;
if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
DEBUG(3,("using password server validation\n"));
if (doencrypt) set_challenge(smb_buf(outbuf));
}
CVAL(outbuf,smb_flg) = 0x81; /* Reply, SMBlockread, SMBwritelock supported */
SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
SSVAL(outbuf,smb_vwv2,max_recv);
SSVAL(outbuf,smb_vwv3,lp_maxmux());
SSVAL(outbuf,smb_vwv4,1);
@ -3641,67 +3645,58 @@ int reply_nt1(char *outbuf)
/*
other valid capabilities which we may support at some time...
CAP_LARGE_FILES|CAP_NT_SMBS|CAP_RPC_REMOTE_APIS;
CAP_LARGE_FILES|CAP_LARGE_READX|
CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
CAP_LARGE_READX|CAP_STATUS32|CAP_LEVEL_II_OPLOCKS;
*/
int secword=0;
BOOL doencrypt = SMBENCRYPT();
time_t t = time(NULL);
int data_len;
int encrypt_len;
char challenge_len = 8;
/* We need to save and restore this as it can be destroyed
if we call another server if security=server
Thanks to Paul Nelson @ Thursby for pointing this out.
*/
uint16 mid = SVAL(outbuf, smb_mid);
struct cli_state *cli = NULL;
char cryptkey[8];
char crypt_len = 0;
if (lp_readraw() && lp_writeraw())
{
capabilities |= CAP_RAW_MODE;
if (lp_security() == SEC_SERVER) {
cli = server_cryptkey();
}
if (lp_security()>=SEC_USER) secword |= 1;
if (cli) {
DEBUG(3,("using password server validation\n"));
doencrypt = ((cli->sec_mode & 2) != 0);
}
if (doencrypt) {
crypt_len = 8;
if (!cli) {
generate_next_challenge(cryptkey);
} else {
memcpy(cryptkey, cli->cryptkey, 8);
set_challenge(cli->cryptkey);
}
}
if (lp_readraw() && lp_writeraw()) {
capabilities |= CAP_RAW_MODE;
}
if (lp_security() >= SEC_USER) secword |= 1;
if (doencrypt) secword |= 2;
/* decide where (if) to put the encryption challenge, and
follow it with the OEM'd domain name
*/
encrypt_len = doencrypt?challenge_len:0;
#if UNICODE
data_len = encrypt_len + 2*(strlen(myworkgroup)+1);
#else
data_len = encrypt_len + strlen(myworkgroup) + 1;
#endif
data_len = crypt_len + strlen(myworkgroup) + 1;
set_message(outbuf,17,data_len,True);
#if UNICODE
/* put the OEM'd domain name */
PutUniCode(smb_buf(outbuf)+encrypt_len,myworkgroup);
#else
strcpy(smb_buf(outbuf)+encrypt_len, myworkgroup);
#endif
strcpy(smb_buf(outbuf)+crypt_len, myworkgroup);
CVAL(outbuf,smb_vwv1) = secword;
/* Create a token value and add it to the outgoing packet. */
if (doencrypt)
{
generate_next_challenge(smb_buf(outbuf));
/* Tell the nt machine how long the challenge is. */
SSVALS(outbuf,smb_vwv16+1,challenge_len);
}
SSVALS(outbuf,smb_vwv16+1,crypt_len);
if (doencrypt)
memcpy(smb_buf(outbuf), cryptkey, 8);
Protocol = PROTOCOL_NT1;
if (lp_security() == SEC_SERVER && server_cryptkey(outbuf)) {
DEBUG(3,("using password server validation\n"));
if (doencrypt) set_challenge(smb_buf(outbuf));
}
SSVAL(outbuf,smb_mid,mid); /* Restore possibly corrupted mid */
SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
SIVAL(outbuf,smb_vwv3+1,0xffff); /* max buffer. LOTS! */
@ -4766,17 +4761,16 @@ static void process(void)
if (keepalive && (counter-last_keepalive)>keepalive)
{
extern int password_client;
if (!send_keepalive(Client))
{
DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
return;
}
/* also send a keepalive to the password server if its still
connected */
if (password_client != -1)
send_keepalive(password_client);
last_keepalive = counter;
struct cli_state *cli = server_client();
if (!send_keepalive(Client)) {
DEBUG(2,("%s Keepalive failed - exiting\n",timestring()));
return;
}
/* also send a keepalive to the password server if its still
connected */
if (cli && cli->initialised)
send_keepalive(cli->fd);
last_keepalive = counter;
}
/* check for connection timeouts */