summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--source3/include/smb.h26
-rw-r--r--source3/smbd/password.c275
-rw-r--r--source3/smbd/reply.c11
-rw-r--r--source3/smbd/server.c158
4 files changed, 217 insertions, 253 deletions
diff --git a/source3/include/smb.h b/source3/include/smb.h
index 2b0fc44d24..7921e77108 100644
--- a/source3/include/smb.h
+++ b/source3/include/smb.h
@@ -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;
diff --git a/source3/smbd/password.c b/source3/smbd/password.c
index 311ef47679..24ee52ed69 100644
--- a/source3/smbd/password.c
+++ b/source3/smbd/password.c
@@ -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);
- }
+ return &cli;
+}
- DEBUG(3,("got session\n"));
+/****************************************************************************
+support for server level security
+****************************************************************************/
+struct cli_state *server_cryptkey(void)
+{
+ fstring desthost;
+ struct in_addr dest_ip;
+ extern fstring local_machine;
+ char *p;
+
+ 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);
+
+ dest_ip = *interpret_addr2(desthost);
+ if (zero_ip(dest_ip)) {
+ DEBUG(1,("Can't resolve address for %s\n",p));
+ continue;
+ }
- bzero(outbuf,smb_size);
+ if (ismyip(dest_ip)) {
+ DEBUG(1,("Password server loop - disabling password server %s\n",p));
+ continue;
+ }
- /* setup the protocol string */
- set_message(outbuf,0,strlen(pass_protocol)+2,True);
- p = smb_buf(outbuf);
- *p++ = 2;
- strcpy(p,pass_protocol);
+ if (cli_connect(&cli, desthost, &dest_ip)) {
+ DEBUG(3,("connected to password server %s\n",p));
+ break;
+ }
+ }
- CVAL(outbuf,smb_com) = SMBnegprot;
- CVAL(outbuf,smb_flg) = 0x8;
- SSVAL(outbuf,smb_flg2,0x1);
+ if (!p) {
+ DEBUG(1,("password server not available\n"));
+ cli_shutdown(&cli);
+ return NULL;
+ }
- send_smb(password_client,outbuf);
- ret = receive_smb(password_client,secserver_inbuf,5000);
+ if (!cli_session_request(&cli, desthost, 0x20, local_machine)) {
+ DEBUG(1,("%s rejected the session\n",desthost));
+ cli_shutdown(&cli);
+ return NULL;
+ }
- 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);
- }
+ DEBUG(3,("got session\n"));
- 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);
- }
+ if (!cli_negprot(&cli)) {
+ DEBUG(1,("%s rejected the negprot\n",desthost));
+ cli_shutdown(&cli);
+ return NULL;
+ }
- memcpy(buf,secserver_inbuf,smb_len(secserver_inbuf)+4);
+ 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 OK\n"));
+ DEBUG(3,("password server OK\n"));
- return(True);
+ return &cli;
}
/****************************************************************************
-support for server level security
+validate a password with the password server
****************************************************************************/
-BOOL server_validate(char *buf)
+BOOL server_validate(char *user, char *domain,
+ char *pass, int passlen,
+ char *ntpass, int ntpasslen)
{
- pstring outbuf;
- BOOL ret;
+ extern fstring local_machine;
+ fstring share;
- 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.initialised) {
+ DEBUG(1,("password server %s is not connected\n", cli.desthost));
+ return(False);
+ }
- if (password_client < 0) {
- DEBUG(1,("%s not connected\n",pserver));
- 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;
+ }
- bzero(secserver_inbuf,BUFFER_SIZE + SAFETY_MARGIN);
- memcpy(outbuf,buf,sizeof(outbuf));
+ /* 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);
+ }
- /* send a session setup command */
- CVAL(outbuf,smb_flg) = 0x8;
- SSVAL(outbuf,smb_flg2,0x1);
- CVAL(outbuf,smb_vwv0) = 0xFF;
- set_message(outbuf,smb_numwords(outbuf),smb_buflen(outbuf),False);
+ sprintf(share,"\\\\%s\\IPC$", cli.desthost);
- SCVAL(secserver_inbuf,smb_rcls,1);
+ if (!cli_send_tconX(&cli, share, "IPC", "", 1)) {
+ DEBUG(1,("password server %s refused IPC$ connect\n", cli.desthost));
+ return False;
+ }
- send_smb(password_client,outbuf);
- ret = receive_smb(password_client,secserver_inbuf,5000);
- if (!ret || CVAL(secserver_inbuf,smb_rcls) != 0) {
- DEBUG(1,("password server %s rejected the password\n",pserver));
- 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 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.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",pserver));
+ DEBUG(3,("password server %s accepted the password\n", cli.desthost));
-#if !KEEP_PASSWORD_SERVER_OPEN
- close(password_client); password_client= -1;
-#endif
+ cli_tdis(&cli);
- return(True);
+ return(True);
}
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 424c7d8183..3643b6eed0 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -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))
{
diff --git a/source3/smbd/server.c b/source3/smbd/server.c
index 7639c5940b..f6a43a536d 100644
--- a/source3/smbd/server.c
+++ b/source3/smbd/server.c
@@ -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 */