summaryrefslogtreecommitdiff
path: root/source3/smbd/reply.c
diff options
context:
space:
mode:
authorAndrew Tridgell <tridge@samba.org>2001-10-15 07:50:21 +0000
committerAndrew Tridgell <tridge@samba.org>2001-10-15 07:50:21 +0000
commit0c0dd06dbd558254ebb048223b0396454f7ee1dd (patch)
treedb0c03b641899dc2842f9f8a5db89961e80e0d18 /source3/smbd/reply.c
parent59efa068bd3d2f920a40b3333d09a22beb8dedb3 (diff)
downloadsamba-0c0dd06dbd558254ebb048223b0396454f7ee1dd.tar.gz
samba-0c0dd06dbd558254ebb048223b0396454f7ee1dd.tar.bz2
samba-0c0dd06dbd558254ebb048223b0396454f7ee1dd.zip
split session setup code out of reply.c in preparation for adding
NTLMSSP and kerberos support in smbd (This used to be commit 38a43d75e25bbebe0f6cdfcf389129a842ede842)
Diffstat (limited to 'source3/smbd/reply.c')
-rw-r--r--source3/smbd/reply.c345
1 files changed, 1 insertions, 344 deletions
diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c
index 334a48e338..8b6e754549 100644
--- a/source3/smbd/reply.c
+++ b/source3/smbd/reply.c
@@ -44,20 +44,6 @@ unsigned int smb_echo_count = 0;
extern fstring remote_machine;
extern BOOL global_encrypted_passwords_negotiated;
-/****************************************************************************
-report a possible attack via the password buffer overflow bug
-****************************************************************************/
-
-static void overflow_attack(int len)
-{
- if( DEBUGLVL( 0 ) ) {
- dbgtext( "ERROR: Invalid password length %d.\n", len );
- dbgtext( "Your machine may be under attack by someone " );
- dbgtext( "attempting to exploit an old bug.\n" );
- dbgtext( "Attack was from IP = %s.\n", client_addr() );
- }
-}
-
/****************************************************************************
reply to an special message
@@ -231,8 +217,7 @@ int reply_tcon_and_X(connection_struct *conn, char *inbuf,char *outbuf,int lengt
}
if (passlen > MAX_PASS_LEN) {
- overflow_attack(passlen);
- return(ERROR_DOS(ERRDOS,ERRbuftoosmall));
+ return ERROR_DOS(ERRDOS,ERRbuftoosmall);
}
memcpy(password,smb_buf(inbuf),passlen);
@@ -373,334 +358,6 @@ int reply_ioctl(connection_struct *conn,
}
/****************************************************************************
-reply to a session setup command
-****************************************************************************/
-
-int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize)
-{
- int sess_vuid;
- gid_t gid;
- uid_t uid;
- char* full_name;
- int smb_bufsize;
- int smb_apasslen = 0;
- pstring smb_apasswd;
- int smb_ntpasslen = 0;
- pstring smb_ntpasswd;
- pstring user;
- pstring orig_user;
- fstring domain;
- fstring native_os;
- fstring native_lanman;
- BOOL guest=False;
- static BOOL done_sesssetup = False;
- BOOL doencrypt = global_encrypted_passwords_negotiated;
- START_PROFILE(SMBsesssetupX);
-
- *smb_apasswd = *smb_ntpasswd = 0;
-
- smb_bufsize = SVAL(inbuf,smb_vwv2);
-
- if (Protocol < PROTOCOL_NT1) {
- smb_apasslen = SVAL(inbuf,smb_vwv7);
- if (smb_apasslen > MAX_PASS_LEN) {
- overflow_attack(smb_apasslen);
- return(ERROR_DOS(ERRDOS,ERRbuftoosmall));
- }
-
- memcpy(smb_apasswd,smb_buf(inbuf),smb_apasslen);
- srvstr_pull(inbuf, user, smb_buf(inbuf)+smb_apasslen, sizeof(user), -1, STR_TERMINATE);
-
- if (!doencrypt && (lp_security() != SEC_SERVER)) {
- smb_apasslen = strlen(smb_apasswd);
- }
- } else {
- uint16 passlen1 = SVAL(inbuf,smb_vwv7);
- uint16 passlen2 = SVAL(inbuf,smb_vwv8);
- enum remote_arch_types ra_type = get_remote_arch();
- char *p = smb_buf(inbuf);
-
- if(global_client_caps == 0)
- global_client_caps = IVAL(inbuf,smb_vwv11);
-
- /* client_caps is used as final determination if client is NT or Win95.
- This is needed to return the correct error codes in some
- circumstances.
- */
-
- if(ra_type == RA_WINNT || ra_type == RA_WIN2K || ra_type == RA_WIN95) {
- if(!(global_client_caps & (CAP_NT_SMBS | CAP_STATUS32))) {
- set_remote_arch( RA_WIN95);
- }
- }
-
- if (passlen1 != 24 && passlen2 < 24)
- doencrypt = False;
-
- if (passlen1 > MAX_PASS_LEN) {
- overflow_attack(passlen1);
- return ERROR_DOS(ERRDOS,ERRbuftoosmall);
- }
-
- passlen1 = MIN(passlen1, MAX_PASS_LEN);
- passlen2 = MIN(passlen2, MAX_PASS_LEN);
-
- if (!doencrypt) {
- /* both Win95 and WinNT stuff up the password lengths for
- non-encrypting systems. Uggh.
-
- if passlen1==24 its a win95 system, and its setting the
- password length incorrectly. Luckily it still works with the
- default code because Win95 will null terminate the password
- anyway
-
- if passlen1>0 and passlen2>0 then maybe its a NT box and its
- setting passlen2 to some random value which really stuffs
- things up. we need to fix that one. */
-
- if (passlen1 > 0 && passlen2 > 0 && passlen2 != 24 && passlen2 != 1)
- passlen2 = 0;
- }
-
- if (lp_restrict_anonymous()) {
- /* there seems to be no reason behind the differences in MS clients formatting
- * various info like the domain, NativeOS, and NativeLanMan fields. Win95
- * in particular seems to have an extra null byte between the username and the
- * domain, or the password length calculation is wrong, which throws off the
- * string extraction routines below. This makes the value of domain be the
- * empty string, which fails the restrict anonymous check further down.
- * This compensates for that, and allows browsing to work in mixed NT and
- * win95 environments even when restrict anonymous is true. AAB
- */
- dump_data(100, p, 0x70);
- DEBUG(9, ("passlen1=%d, passlen2=%d\n", passlen1, passlen2));
- if (ra_type == RA_WIN95 && !passlen1 && !passlen2 && p[0] == 0 && p[1] == 0) {
- DEBUG(0, ("restrict anonymous parameter used in a win95 environment!\n"));
- DEBUG(0, ("client is win95 and broken passlen1 offset -- attempting fix\n"));
- DEBUG(0, ("if win95 cilents are having difficulty browsing, you will be unable to use restrict anonymous\n"));
- passlen1 = 1;
- }
- }
-
- /* Save the lanman2 password and the NT md4 password. */
- smb_apasslen = passlen1;
- memcpy(smb_apasswd,p,smb_apasslen);
-
- smb_ntpasslen = passlen2;
- memcpy(smb_ntpasswd,p+passlen1,smb_ntpasslen);
-
- if (smb_apasslen != 24 || !doencrypt) {
- /* trim the password */
- smb_apasslen = strlen(smb_apasswd);
-
- /* wfwg sometimes uses a space instead of a null */
- if (strequal(smb_apasswd," ")) {
- smb_apasslen = 0;
- *smb_apasswd = 0;
- }
- }
-
- p += passlen1 + passlen2;
- p += srvstr_pull(inbuf, user, p, sizeof(user), -1,
- STR_TERMINATE);
- /*
- * Incoming user and domain are in DOS codepage format. Convert
- * to UNIX.
- */
- p += srvstr_pull(inbuf, domain, p, sizeof(domain),
- -1, STR_TERMINATE);
- p += srvstr_pull(inbuf, native_os, p, sizeof(native_os),
- -1, STR_TERMINATE);
- p += srvstr_pull(inbuf, native_lanman, p, sizeof(native_lanman),
- -1, STR_TERMINATE);
- DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s]\n",
- domain,native_os,native_lanman));
- }
-
- /* don't allow for weird usernames or domains */
- alpha_strcpy(user, user, ". _-$", sizeof(user));
- alpha_strcpy(domain, domain, ". _-", sizeof(domain));
- if (strstr(user, "..") || strstr(domain,"..")) {
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
- }
-
- if (lp_security() == SEC_SHARE) {
- /* in share level we should ignore any passwords */
- smb_ntpasslen = 0;
- smb_apasslen = 0;
- guest = True;
- }
-
-
- DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n",user, domain, remote_machine));
-
- if (done_sesssetup && lp_restrict_anonymous()) {
- /* tests show that even if browsing is done over already validated connections
- * without a username and password the domain is still provided, which it
- * wouldn't be if it was a purely anonymous connection. So, in order to
- * restrict anonymous, we only deny connections that have no session
- * information. If a domain has been provided, then it's not a purely
- * anonymous connection. AAB
- */
- if (!*user && !*smb_apasswd && !*domain) {
- DEBUG(0, ("restrict anonymous is True and anonymous connection attempted. Denying access.\n"));
- END_PROFILE(SMBsesssetupX);
- return ERROR_DOS(ERRDOS,ERRnoaccess);
- }
- }
-
- /* If no username is sent use the guest account */
- if (!*user) {
- pstrcpy(user,lp_guestaccount(-1));
- guest = True;
- }
-
- pstrcpy(current_user_info.smb_name,user);
-
- reload_services(True);
-
- /*
- * Save the username before mapping. We will use
- * the original username sent to us for security=server
- * and security=domain checking.
- */
-
- pstrcpy( orig_user, user);
-
- /*
- * Always try the "DOMAIN\user" lookup first, as this is the most
- * specific case. If this fails then try the simple "user" lookup.
- * But don't do this for guests, as this is always a local user.
- */
-
- if (!guest) {
- pstring dom_user;
-
- /* Work out who's who */
-
- slprintf(dom_user, sizeof(dom_user) - 1,"%s%s%s",
- domain, lp_winbind_separator(), user);
-
- if (sys_getpwnam(dom_user) != NULL) {
- pstrcpy(user, dom_user);
- DEBUG(3,("Using unix username %s\n", dom_user));
- }
-
- /*
- * Pass the user through the NT -> unix user mapping
- * function.
- */
-
- (void)map_username(user);
-
- /*
- * Do any UNIX username case mangling.
- */
- smb_getpwnam(user, True);
- }
-
- add_session_user(user);
-
- if (!guest) {
- NTSTATUS nt_status;
- nt_status = pass_check_smb(orig_user, user,
- domain, remote_machine,
- (unsigned char *)smb_apasswd,
- smb_apasslen,
- (unsigned char *)smb_ntpasswd,
- smb_ntpasslen);
-
- if NT_STATUS_IS_OK(nt_status) {
-
- } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_NO_SUCH_USER) {
- if ((lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_USER) ||
- (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD)) {
- DEBUG(3,("No such user %s [%s] - using guest account\n",user, domain));
- pstrcpy(user,lp_guestaccount(-1));
- guest = True;
- } else {
- /* Match WinXP and don't give the game away */
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
- }
- } else if NT_STATUS_EQUAL(nt_status, NT_STATUS_WRONG_PASSWORD) {
- if (lp_map_to_guest() == MAP_TO_GUEST_ON_BAD_PASSWORD) {
- pstrcpy(user,lp_guestaccount(-1));
- DEBUG(3,("Registered username %s for guest access\n",user));
- guest = True;
- } else {
- /* Match WinXP and don't give the game away */
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
- }
- } else {
- return ERROR_NT(nt_status);
- }
- }
-
- if (!strequal(user,lp_guestaccount(-1)) &&
- lp_servicenumber(user) < 0)
- {
- add_home_service(user,get_user_home_dir(user));
- }
-
-
- /* it's ok - setup a reply */
- if (Protocol < PROTOCOL_NT1) {
- set_message(outbuf,3,0,True);
- } else {
- char *p;
- set_message(outbuf,3,0,True);
- p = smb_buf(outbuf);
- p += srvstr_push(outbuf, p, "Unix", -1, STR_TERMINATE);
- p += srvstr_push(outbuf, p, "Samba", -1, STR_TERMINATE);
- p += srvstr_push(outbuf, p, lp_workgroup(), -1, STR_TERMINATE);
- set_message_end(outbuf,p);
- /* perhaps grab OS version here?? */
- }
-
- /* Set the correct uid in the outgoing and incoming packets
- We will use this on future requests to determine which
- user we should become.
- */
- {
- const struct passwd *pw = smb_getpwnam(user,False);
- if (!pw) {
- DEBUG(1,("Username %s is invalid on this system\n",user));
- END_PROFILE(SMBsesssetupX);
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
- }
- gid = pw->pw_gid;
- uid = pw->pw_uid;
- full_name = pw->pw_gecos;
- }
-
- if (guest)
- SSVAL(outbuf,smb_vwv2,1);
-
- /* register the name and uid as being validated, so further connections
- to a uid can get through without a password, on the same VC */
-
- sess_vuid = register_vuid(uid,gid,user,orig_user,domain,guest, full_name);
-
- if (sess_vuid == -1) {
- return ERROR_NT(NT_STATUS_LOGON_FAILURE);
- }
-
-
- SSVAL(outbuf,smb_uid,sess_vuid);
- SSVAL(inbuf,smb_uid,sess_vuid);
-
- if (!done_sesssetup)
- max_send = MIN(max_send,smb_bufsize);
-
- DEBUG(6,("Client requested max send size of %d\n", max_send));
-
- done_sesssetup = True;
-
- END_PROFILE(SMBsesssetupX);
- return chain_reply(inbuf,outbuf,length,bufsize);
-}
-
-/****************************************************************************
reply to a chkpth
****************************************************************************/
int reply_chkpth(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize)