Example #1
0
void smb_signing_sign_pdu(struct smb_signing_state *si,
			  uint8_t *outbuf, uint32_t seqnum)
{
	uint8_t calc_md5_mac[16];
	uint8_t com;
	uint8_t flags;

	if (si->mac_key.length == 0) {
		if (!si->negotiated) {
			return;
		}
	}

	/* JRA Paranioa test - we should be able to get rid of this... */
	if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
		DEBUG(1,("smb_signing_sign_pdu: Logic error. "
			 "Can't check signature on short packet! smb_len = %u\n",
			 smb_len(outbuf)));
		abort();
	}

	com = SVAL(outbuf,smb_com);
	flags = SVAL(outbuf,smb_flg);

	if (!(flags & FLAG_REPLY)) {
		uint16_t flags2 = SVAL(outbuf,smb_flg2);
		/*
		 * If this is a request, specify what is
		 * supported or required by the client
		 */
		if (si->negotiated && si->desired) {
			flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
		}
		if (si->negotiated && si->mandatory) {
			flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED;
		}
		SSVAL(outbuf, smb_flg2, flags2);
	}

	if (si->mac_key.length == 0) {
		/* I wonder what BSRSPYL stands for - but this is what MS
		   actually sends! */
		if (com == SMBsesssetupX) {
			memcpy(calc_md5_mac, "BSRSPYL ", 8);
		} else {
			memset(calc_md5_mac, 0, 8);
		}
	} else {
		smb_signing_md5(&si->mac_key, outbuf,
				seqnum, calc_md5_mac);
	}

	DEBUG(10, ("smb_signing_sign_pdu: sent SMB signature of\n"));
	dump_data(10, calc_md5_mac, 8);

	memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);

/*	outbuf[smb_ss_field+2]=0;
	Uncomment this to test if the remote server actually verifies signatures...*/
}
Example #2
0
bool smb_signing_check_pdu(struct smb_signing_state *si,
			   const uint8_t *inbuf, uint32_t seqnum)
{
	bool good;
	uint8_t calc_md5_mac[16];
	const uint8_t *reply_sent_mac;

	if (si->mac_key.length == 0) {
		return true;
	}

	if (smb_len(inbuf) < (smb_ss_field + 8 - 4)) {
		DEBUG(1,("smb_signing_check_pdu: Can't check signature "
			 "on short packet! smb_len = %u\n",
			 smb_len(inbuf)));
		return False;
	}

	smb_signing_md5(&si->mac_key, inbuf,
			seqnum, calc_md5_mac);

	reply_sent_mac = &inbuf[smb_ss_field];
	good = (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0);

	if (!good) {
		int i;
		const int sign_range = 5;

		DEBUG(5, ("smb_signing_check_pdu: BAD SIG: wanted SMB signature of\n"));
		dump_data(5, calc_md5_mac, 8);

		DEBUG(5, ("smb_signing_check_pdu: BAD SIG: got SMB signature of\n"));
		dump_data(5, reply_sent_mac, 8);

		for (i = -sign_range; i < sign_range; i++) {
			smb_signing_md5(&si->mac_key, inbuf,
					seqnum+i, calc_md5_mac);
			if (memcmp(reply_sent_mac, calc_md5_mac, 8) == 0) {
				DEBUG(0,("smb_signing_check_pdu: "
					 "out of seq. seq num %u matches. "
					 "We were expecting seq %u\n",
					 (unsigned int)seqnum+i,
					 (unsigned int)seqnum));
				break;
			}
		}
	} else {
		DEBUG(10, ("smb_signing_check_pdu: seq %u: "
			   "got good SMB signature of\n",
			   (unsigned int)seqnum));
		dump_data(10, reply_sent_mac, 8);
	}

	return smb_signing_good(si, good, seqnum);
}
Example #3
0
BOOL cli_send_smb(struct cli_state *cli)
{
	size_t len;
	size_t nwritten=0;
	ssize_t ret;

	/* fd == -1 causes segfaults -- Tom ([email protected]) */
	if (cli->fd == -1)
		return False;

	len = smb_len(cli->outbuf) + 4;

	while (nwritten < len) {
		ret = write_socket(cli->fd,cli->outbuf+nwritten,len - nwritten);
		if (ret <= 0) {
                        close(cli->fd);
                        cli->fd = -1;
			cli->smb_rw_error = WRITE_ERROR;
			DEBUG(0,("Error writing %d bytes to client. %d (%s)\n",
				 (int)len,(int)ret, strerror(errno) ));
			return False;
		}
		nwritten += ret;
	}
	
	return True;
}
ssize_t message_push_string(uint8 **outbuf, const char *str, int flags)
{
	size_t buf_size = smb_len(*outbuf) + 4;
	size_t grow_size;
	size_t result = 0;
	uint8 *tmp;
	NTSTATUS status;

	/*
	 * We need to over-allocate, now knowing what srvstr_push will
	 * actually use. This is very generous by incorporating potential
	 * padding, the terminating 0 and at most 4 chars per UTF-16 code
	 * point.
	 */
	grow_size = (strlen(str) + 2) * 4;

	if (!(tmp = talloc_realloc(NULL, *outbuf, uint8,
					 buf_size + grow_size))) {
		DEBUG(0, ("talloc failed\n"));
		return -1;
	}

	status = srvstr_push((char *)tmp, SVAL(tmp, smb_flg2),
			     tmp + buf_size, str, grow_size, flags, &result);

	if (!NT_STATUS_IS_OK(status)) {
		DEBUG(0, ("srvstr_push failed\n"));
		return -1;
	}
	set_message_bcc((char *)tmp, smb_buflen(tmp) + result);

	*outbuf = tmp;

	return result;
}
Example #5
0
static ssize_t read_smb_length_return_keepalive(int fd,char *inbuf,unsigned int timeout)
{
  ssize_t len=0;
  int msg_type;
  BOOL ok = False;

  while (!ok)
  {
    if (timeout > 0)
      ok = (read_socket_with_timeout(fd,inbuf,4,4,timeout) == 4);
    else 
      ok = (read_socket_data(fd,inbuf,4) == 4);

    if (!ok)
      return(-1);

    len = smb_len(inbuf);
    msg_type = CVAL(inbuf,0);

    if (msg_type == 0x85) 
      DEBUG(5,("Got keepalive packet\n"));
  }

  DEBUG(10,("got smb length of %d\n",len));

  return(len);
}
Example #6
0
BOOL push_deferred_smb_message(uint16 mid,
			       struct timeval request_time,
			       struct timeval timeout,
			       char *private_data, size_t priv_len)
{
	struct timeval end_time;

	end_time = timeval_sum(&request_time, &timeout);

	DEBUG(10,("push_deferred_open_smb_message: pushing message len %u mid %u "
		  "timeout time [%u.%06u]\n",
		  (unsigned int) smb_len(current_inbuf)+4, (unsigned int)mid,
		  (unsigned int)end_time.tv_sec,
		  (unsigned int)end_time.tv_usec));

	return push_queued_message(current_inbuf, smb_len(current_inbuf)+4,
				   request_time, end_time,
				   private_data, priv_len);
}
Example #7
0
bool cli_send_smb(struct cli_state *cli)
{
	size_t len;
	size_t nwritten=0;
	ssize_t ret;
	char *buf_out = cli->outbuf;
	bool enc_on = cli_encryption_on(cli);

	/* fd == -1 causes segfaults -- Tom ([email protected]) */
	if (cli->fd == -1)
		return false;

	cli_calculate_sign_mac(cli, cli->outbuf);

	if (enc_on) {
		NTSTATUS status = cli_encrypt_message(cli, cli->outbuf,
						      &buf_out);
		if (!NT_STATUS_IS_OK(status)) {
			close(cli->fd);
			cli->fd = -1;
			cli->smb_rw_error = SMB_WRITE_ERROR;
			DEBUG(0,("Error in encrypting client message. Error %s\n",
				nt_errstr(status) ));
			return false;
		}
	}

	len = smb_len(buf_out) + 4;

	while (nwritten < len) {
		ret = write_socket(cli->fd,buf_out+nwritten,len - nwritten);
		if (ret <= 0) {
			if (enc_on) {
				cli_free_enc_buffer(cli, buf_out);
			}
			close(cli->fd);
			cli->fd = -1;
			cli->smb_rw_error = SMB_WRITE_ERROR;
			DEBUG(0,("Error writing %d bytes to client. %d (%s)\n",
				(int)len,(int)ret, strerror(errno) ));
			return false;
		}
		nwritten += ret;
	}

	if (enc_on) {
		cli_free_enc_buffer(cli, buf_out);
	}

	/* Increment the mid so we can tell between responses. */
	cli->mid++;
	if (!cli->mid)
		cli->mid++;
	return true;
}
Example #8
0
void smb_signing_sign_pdu(struct smb_signing_state *si,
			  uint8_t *outbuf, uint32_t seqnum)
{
	uint8_t calc_md5_mac[16];
	uint16_t flags2;

	if (si->mac_key.length == 0) {
		if (!si->bsrspyl) {
			return;
		}
	}

	/* JRA Paranioa test - we should be able to get rid of this... */
	if (smb_len(outbuf) < (smb_ss_field + 8 - 4)) {
		DEBUG(1,("smb_signing_sign_pdu: Logic error. "
			 "Can't check signature on short packet! smb_len = %u\n",
			 smb_len(outbuf)));
		abort();
	}

	/* mark the packet as signed - BEFORE we sign it...*/
	flags2 = SVAL(outbuf,smb_flg2);
	flags2 |= FLAGS2_SMB_SECURITY_SIGNATURES;
	SSVAL(outbuf, smb_flg2, flags2);

	if (si->bsrspyl) {
		/* I wonder what BSRSPYL stands for - but this is what MS
		   actually sends! */
		memcpy(calc_md5_mac, "BSRSPYL ", 8);
	} else {
		smb_signing_md5(&si->mac_key, outbuf,
				seqnum, calc_md5_mac);
	}

	DEBUG(10, ("smb_signing_sign_pdu: sent SMB signature of\n"));
	dump_data(10, calc_md5_mac, 8);

	memcpy(&outbuf[smb_ss_field], calc_md5_mac, 8);

/*	outbuf[smb_ss_field+2]=0;
	Uncomment this to test if the remote server actually verifies signatures...*/
}
/****************************************************************************
  process an smb from the client - split out from the process() code so
  it can be used by the oplock break code.
****************************************************************************/
void process_smb(char *inbuf, char *outbuf, int ProcSockID, int threadid)
{
//  extern int Client;
#ifdef WITH_SSL
#endif /* WITH_SSL */
  int msg_type = CVAL(inbuf,0);
  int32 len = smb_len(inbuf);
  int nread = len + 4;

#ifdef WITH_PROFILE
  profile_p->smb_count++;
#endif

#ifdef WITH_VTP
  if(trans_num == 1 && VT_Check(inbuf)) 
  {
    VT_Process();
    return;
  }
#endif
  if(msg_type == 0x85)
    return; /* Keepalive packet. */

  nread = construct_reply(inbuf,outbuf,nread,max_send[threadid], ProcSockID
  					,threadid );
      
  if(nread > 0) 
  {
	
    if (nread != smb_len(outbuf) + 4) 
    {
    }
    else 
      send_smb(ProcSockID,outbuf);
  }
}
Example #10
0
void srv_calculate_sign_mac(struct smbd_server_connection *conn,
                            char *outbuf, uint32_t seqnum)
{
    uint8_t *outhdr;
    size_t len;

    /* Check if it's a non-session message. */
    if(CVAL(outbuf,0)) {
        return;
    }

    len = smb_len(outbuf);
    outhdr = (uint8_t *)outbuf + NBT_HDR_SIZE;

    smb_signing_sign_pdu(conn->smb1.signing_state, outhdr, len, seqnum);
}
Example #11
0
/* setup to receive the data part of the SMB */
static int smb_setup_bcc(struct smb_request *req)
{
	int result = 0;
	req->rq_rlen = smb_len(req->rq_header) + 4 - req->rq_bytes_recvd;

	if (req->rq_rlen > req->rq_bufsize) {
		PARANOIA("Packet too large %d > %d\n",
			 req->rq_rlen, req->rq_bufsize);
		return -ENOBUFS;
	}

	req->rq_iov[0].iov_base = req->rq_buffer;
	req->rq_iov[0].iov_len  = req->rq_rlen;
	req->rq_iovlen = 1;

	return result;
}
Example #12
0
static int
smb_get_length(struct socket *socket, unsigned char *header)
{
	int result;
	unsigned char peek_buf[4];
	mm_segment_t fs;

      re_recv:
	fs = get_fs();
	set_fs(get_ds());
	result = smb_receive_raw(socket, peek_buf, 4);
	set_fs(fs);

	if (result < 0)
	{
#ifdef SMBFS_PARANOIA
printk("smb_get_length: recv error = %d\n", -result);
#endif
		return result;
	}
	switch (peek_buf[0])
	{
	case 0x00:
	case 0x82:
		break;

	case 0x85:
		pr_debug("smb_get_length: Got SESSION KEEP ALIVE\n");
		goto re_recv;

	default:
#ifdef SMBFS_PARANOIA
printk("smb_get_length: Invalid NBT packet, code=%x\n", peek_buf[0]);
#endif
		return -EIO;
	}

	if (header != NULL)
	{
		memcpy(header, peek_buf, 4);
	}
	/* The length in the RFC NB header is the raw data length */
	return smb_len(peek_buf);
}
Example #13
0
/*
 * Prepare a "normal" request structure.
 */
static int smb_setup_request(struct smb_request *req)
{
    int len = smb_len(req->rq_header) + 4;
    req->rq_slen = len;

    /* if we expect a data part in the reply we set the iov's to read it */
    if (req->rq_resp_bcc)
        req->rq_setup_read = smb_setup_bcc;

    /* This tries to support re-using the same request */
    req->rq_bytes_sent = 0;
    req->rq_rcls = 0;
    req->rq_err = 0;
    req->rq_errno = 0;
    req->rq_fragment = 0;
    kfree(req->rq_trans2buffer);

    return 0;
}
Example #14
0
static void smb_signing_md5(const DATA_BLOB *mac_key,
			    const uint8_t *buf, uint32_t seq_number,
			    uint8_t calc_md5_mac[16])
{
	const size_t offset_end_of_sig = (smb_ss_field + 8);
	uint8_t sequence_buf[8];
	struct MD5Context md5_ctx;

	/*
	 * Firstly put the sequence number into the first 4 bytes.
	 * and zero out the next 4 bytes.
	 *
	 * We do this here, to avoid modifying the packet.
	 */

	DEBUG(10,("smb_signing_md5: sequence number %u\n", seq_number ));

	SIVAL(sequence_buf, 0, seq_number);
	SIVAL(sequence_buf, 4, 0);

	/* Calculate the 16 byte MAC - but don't alter the data in the
	   incoming packet.

	   This makes for a bit of fussing about, but it's not too bad.
	*/
	MD5Init(&md5_ctx);

	/* intialise with the key */
	MD5Update(&md5_ctx, mac_key->data, mac_key->length);

	/* copy in the first bit of the SMB header */
	MD5Update(&md5_ctx, buf + 4, smb_ss_field - 4);

	/* copy in the sequence number, instead of the signature */
	MD5Update(&md5_ctx, sequence_buf, sizeof(sequence_buf));

	/* copy in the rest of the packet in, skipping the signature */
	MD5Update(&md5_ctx, buf + offset_end_of_sig, 
		  smb_len(buf) - (offset_end_of_sig - 4));

	/* calculate the MD5 sig */
	MD5Final(calc_md5_mac, &md5_ctx);
}
static bool send_smb(int fd, char *buffer)
{
	size_t len;
	size_t nwritten=0;
	ssize_t ret;

        len = smb_len(buffer) + 4;

	while (nwritten < len) {
		ret = write_data(fd,buffer+nwritten,len - nwritten);
		if (ret <= 0) {
			DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
				(int)len,(int)ret, strerror(errno) ));
			return false;
		}
		nwritten += ret;
	}

	return true;
}
Example #16
0
bool srv_check_sign_mac(struct smbd_server_connection *conn,
                        const char *inbuf, uint32_t *seqnum,
                        bool trusted_channel)
{
    const uint8_t *inhdr;
    size_t len;

    /* Check if it's a non-session message. */
    if(CVAL(inbuf,0)) {
        return true;
    }

    len = smb_len(inbuf);
    inhdr = (const uint8_t *)inbuf + NBT_HDR_SIZE;

    if (trusted_channel) {
        NTSTATUS status;

        if (len < (HDR_SS_FIELD + 8)) {
            DEBUG(1,("smb_signing_check_pdu: Can't check signature "
                     "on short packet! smb_len = %u\n",
                     (unsigned)len));
            return false;
        }

        status = NT_STATUS(IVAL(inhdr, HDR_SS_FIELD + 4));
        if (!NT_STATUS_IS_OK(status)) {
            DEBUG(1,("smb_signing_check_pdu: trusted channel passed %s\n",
                     nt_errstr(status)));
            return false;
        }

        *seqnum = IVAL(inhdr, HDR_SS_FIELD);
        return true;
    }

    *seqnum = smb_signing_next_seqnum(conn->smb1.signing_state, false);
    return smb_signing_check_pdu(conn->smb1.signing_state,
                                 inhdr, len,
                                 *seqnum);
}
Example #17
0
BOOL send_smb(int fd,char *buffer)
{
  size_t len;
  size_t nwritten=0;
  ssize_t ret;
  len = smb_len(buffer) + 4;

  while (nwritten < len)
  {
    ret = write_socket(fd,buffer+nwritten,len - nwritten);
    if (ret <= 0)
    {
      DEBUG(0,("Error writing %d bytes to client. %d. Exiting\n",(int)len,(int)ret));
      close_sockets();
      exit(1);
    }
    nwritten += ret;
  }

  return True;
}
Example #18
0
BOOL send_smb(int fd,char *buffer)
{
	size_t len;
	size_t nwritten=0;
	ssize_t ret;

	/* Sign the outgoing packet if required. */
	srv_calculate_sign_mac(buffer);

	len = smb_len(buffer) + 4;

	while (nwritten < len) {
		ret = write_socket(fd,buffer+nwritten,len - nwritten);
		if (ret <= 0) {
			DEBUG(0,("Error writing %d bytes to client. %d. (%s)\n",
				(int)len,(int)ret, strerror(errno) ));
			return False;
		}
		nwritten += ret;
	}

	return True;
}
Example #19
0
File: negprot.c Project: aosm/samba
static int reply_lanman1(char *inbuf, char *outbuf)
{
	int raw = (lp_readraw()?1:0) | (lp_writeraw()?2:0);
	int secword=0;
	time_t t = time(NULL);

	global_encrypted_passwords_negotiated = lp_encrypted_passwords();

	if (lp_security()>=SEC_USER)
		secword |= NEGOTIATE_SECURITY_USER_LEVEL;
	if (global_encrypted_passwords_negotiated)
		secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;

	set_message(outbuf,13,global_encrypted_passwords_negotiated?8:0,True);
	SSVAL(outbuf,smb_vwv1,secword); 
	/* Create a token value and add it to the outgoing packet. */
	if (global_encrypted_passwords_negotiated) {
		get_challenge(smb_buf(outbuf));
		SSVAL(outbuf,smb_vwv11, 8);
	}

	Protocol = PROTOCOL_LANMAN1;

	/* Reply, SMBlockread, SMBwritelock supported. */
	SCVAL(outbuf,smb_flg,FLAG_REPLY|FLAG_SUPPORT_LOCKREAD);
	SSVAL(outbuf,smb_vwv2,max_recv);
	SSVAL(outbuf,smb_vwv3,lp_maxmux()); /* maxmux */
	SSVAL(outbuf,smb_vwv4,1);
	SSVAL(outbuf,smb_vwv5,raw); /* tell redirector we support
		readbraw writebraw (possibly) */
	SIVAL(outbuf,smb_vwv6,sys_getpid());
	SSVAL(outbuf,smb_vwv10, set_server_zone_offset(t)/60);

	srv_put_dos_date(outbuf,smb_vwv8,t);

	return (smb_len(outbuf)+4);
}
Example #20
0
NTSTATUS read_smb_length_return_keepalive(int fd, char *inbuf,
					  unsigned int timeout,
					  size_t *len)
{
	int msg_type;
	NTSTATUS status;

	status = read_fd_with_timeout(fd, inbuf, 4, 4, timeout, NULL);

	if (!NT_STATUS_IS_OK(status)) {
		return status;
	}

	*len = smb_len(inbuf);
	msg_type = CVAL(inbuf,0);

	if (msg_type == NBSSkeepalive) {
		DEBUG(5,("Got keepalive packet\n"));
	}

	DEBUG(10,("got smb length of %lu\n",(unsigned long)(*len)));

	return NT_STATUS_OK;
}
Example #21
0
File: negprot.c Project: aosm/samba
static int reply_nt1(char *inbuf, char *outbuf)
{
	/* dual names + lock_and_read + nt SMBs + remote API calls */
	int capabilities = CAP_NT_FIND|CAP_LOCK_AND_READ|
		CAP_LEVEL_II_OPLOCKS;

	int secword=0;
	char *p, *q;
	BOOL negotiate_spnego = False;
	time_t t = time(NULL);

	global_encrypted_passwords_negotiated = lp_encrypted_passwords();

	/* Check the flags field to see if this is Vista.
	   WinXP sets it and Vista does not. But we have to 
	   distinguish from NT which doesn't set it either. */

	if ( (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY) &&
		((SVAL(inbuf, smb_flg2) & FLAGS2_UNKNOWN_BIT4) == 0) ) 
	{
	    	/* Don't override the SAMBA or CIFSFS arch */
		if ((get_remote_arch() != RA_SAMBA) && (get_remote_arch() != RA_CIFSFS)) {
			set_remote_arch( RA_VISTA );
		}
	}

	/* do spnego in user level security if the client
	   supports it and we can do encrypted passwords */
	
	if (global_encrypted_passwords_negotiated && 
	    (lp_security() != SEC_SHARE) &&
	    lp_use_spnego() &&
	    (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) {
		negotiate_spnego = True;
		capabilities |= CAP_EXTENDED_SECURITY;
		add_to_common_flags2(FLAGS2_EXTENDED_SECURITY);
		/* Ensure FLAGS2_EXTENDED_SECURITY gets set in this reply (already
			partially constructed. */
		SSVAL(outbuf,smb_flg2, SVAL(outbuf,smb_flg2) | FLAGS2_EXTENDED_SECURITY);
	}
	
	capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS|CAP_UNICODE;

	if (lp_unix_extensions()) {
		capabilities |= CAP_UNIX;
	}
	
	if (lp_large_readwrite() && (SMB_OFF_T_BITS == 64))
		capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS;
	
	if (SMB_OFF_T_BITS == 64)
		capabilities |= CAP_LARGE_FILES;

	if (lp_readraw() && lp_writeraw())
		capabilities |= CAP_RAW_MODE;
	
	if (lp_nt_status_support())
		capabilities |= CAP_STATUS32;
	
	if (lp_host_msdfs())
		capabilities |= CAP_DFS;
	
	if (lp_security() >= SEC_USER)
		secword |= NEGOTIATE_SECURITY_USER_LEVEL;
	if (global_encrypted_passwords_negotiated)
		secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE;
	
	if (lp_server_signing()) {
	       	if (lp_security() >= SEC_USER) {
			secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED;
			/* No raw mode with smb signing. */
			capabilities &= ~CAP_RAW_MODE;
			if (lp_server_signing() == Required)
				secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED;
			srv_set_signing_negotiated();
		} else {
			DEBUG(0,("reply_nt1: smb signing is incompatible with share level security !\n"));
			if (lp_server_signing() == Required) {
				exit_server_cleanly("reply_nt1: smb signing required and share level security selected.");
			}
		}
	}

	set_message(outbuf,17,0,True);
	
	SCVAL(outbuf,smb_vwv1,secword);
	
	Protocol = PROTOCOL_NT1;
	
	SSVAL(outbuf,smb_vwv1+1,lp_maxmux()); /* maxmpx */
	SSVAL(outbuf,smb_vwv2+1,1); /* num vcs */
	SIVAL(outbuf,smb_vwv3+1,max_recv); /* max buffer. LOTS! */
	SIVAL(outbuf,smb_vwv5+1,0x10000); /* raw size. full 64k */
	SIVAL(outbuf,smb_vwv7+1,sys_getpid()); /* session key */
	SIVAL(outbuf,smb_vwv9+1,capabilities); /* capabilities */
	put_long_date(outbuf+smb_vwv11+1,t);
	SSVALS(outbuf,smb_vwv15+1,set_server_zone_offset(t)/60);
	
	p = q = smb_buf(outbuf);
	if (!negotiate_spnego) {
		/* Create a token value and add it to the outgoing packet. */
		if (global_encrypted_passwords_negotiated) {
			/* note that we do not send a challenge at all if
			   we are using plaintext */
			get_challenge(p);
			SCVAL(outbuf,smb_vwv16+1,8);
			p += 8;
		}
		p += srvstr_push(outbuf, p, lp_workgroup(), BUFFER_SIZE - (p-outbuf), 
				 STR_UNICODE|STR_TERMINATE|STR_NOALIGN);
		DEBUG(3,("not using SPNEGO\n"));
	} else {
		DATA_BLOB spnego_blob = negprot_spnego();

		if (spnego_blob.data == NULL) {
			return ERROR_NT(NT_STATUS_NO_MEMORY);
		}

		memcpy(p, spnego_blob.data, spnego_blob.length);
		p += spnego_blob.length;
		data_blob_free(&spnego_blob);

		SCVAL(outbuf,smb_vwv16+1, 0);
		DEBUG(3,("using SPNEGO\n"));
	}
	
	SSVAL(outbuf,smb_vwv17, p - q); /* length of challenge+domain strings */
	set_message_end(outbuf, p);
	
	return (smb_len(outbuf)+4);
}
Example #22
0
static NTSTATUS cli_pull_trans(uint8_t *inbuf,
			       uint8_t wct, uint16_t *vwv,
			       uint16_t num_bytes, uint8_t *bytes,
			       uint8_t smb_cmd, bool expect_first_reply,
			       uint8_t *pnum_setup, uint16_t **psetup,
			       uint32_t *ptotal_param, uint32_t *pnum_param,
			       uint32_t *pparam_disp, uint8_t **pparam,
			       uint32_t *ptotal_data, uint32_t *pnum_data,
			       uint32_t *pdata_disp, uint8_t **pdata)
{
	uint32_t param_ofs, data_ofs;

	if (expect_first_reply) {
		if ((wct != 0) || (num_bytes != 0)) {
			return NT_STATUS_INVALID_NETWORK_RESPONSE;
		}
		return NT_STATUS_OK;
	}

	switch (smb_cmd) {
	case SMBtrans:
	case SMBtrans2:
		if (wct < 10) {
			return NT_STATUS_INVALID_NETWORK_RESPONSE;
		}
		*ptotal_param	= SVAL(vwv + 0, 0);
		*ptotal_data	= SVAL(vwv + 1, 0);
		*pnum_param	= SVAL(vwv + 3, 0);
		param_ofs	= SVAL(vwv + 4, 0);
		*pparam_disp	= SVAL(vwv + 5, 0);
		*pnum_data	= SVAL(vwv + 6, 0);
		data_ofs	= SVAL(vwv + 7, 0);
		*pdata_disp	= SVAL(vwv + 8, 0);
		*pnum_setup	= CVAL(vwv + 9, 0);
		if (wct < 10 + (*pnum_setup)) {
			return NT_STATUS_INVALID_NETWORK_RESPONSE;
		}
		*psetup = vwv + 10;

		break;
	case SMBnttrans:
		if (wct < 18) {
			return NT_STATUS_INVALID_NETWORK_RESPONSE;
		}
		*ptotal_param	= IVAL(vwv, 3);
		*ptotal_data	= IVAL(vwv, 7);
		*pnum_param	= IVAL(vwv, 11);
		param_ofs	= IVAL(vwv, 15);
		*pparam_disp	= IVAL(vwv, 19);
		*pnum_data	= IVAL(vwv, 23);
		data_ofs	= IVAL(vwv, 27);
		*pdata_disp	= IVAL(vwv, 31);
		*pnum_setup	= CVAL(vwv, 35);
		*psetup		= vwv + 18;
		break;

	default:
		return NT_STATUS_INTERNAL_ERROR;
	}

	/*
	 * Check for buffer overflows. data_ofs needs to be checked against
	 * the incoming buffer length, data_disp against the total
	 * length. Likewise for param_ofs/param_disp.
	 */

	if (trans_oob(smb_len(inbuf), param_ofs, *pnum_param)
	    || trans_oob(*ptotal_param, *pparam_disp, *pnum_param)
	    || trans_oob(smb_len(inbuf), data_ofs, *pnum_data)
	    || trans_oob(*ptotal_data, *pdata_disp, *pnum_data)) {
		return NT_STATUS_INVALID_NETWORK_RESPONSE;
	}

	*pparam = (uint8_t *)inbuf + 4 + param_ofs;
	*pdata = (uint8_t *)inbuf + 4 + data_ofs;

	return NT_STATUS_OK;
}
Example #23
0
/*
 * Called with the server locked
 */
int
smb_request(struct smb_sb_info *server)
{
	unsigned long flags, sigpipe;
	mm_segment_t fs;
	sigset_t old_set;
	int len, result;
	unsigned char *buffer;

	result = -EBADF;
	buffer = server->packet;
	if (!buffer)
		goto bad_no_packet;

	result = -EIO;
	if (server->state != CONN_VALID)
		goto bad_no_conn;

	if ((result = smb_dont_catch_keepalive(server)) != 0)
		goto bad_conn;

	len = smb_len(buffer) + 4;
	DEBUG1("len = %d cmd = 0x%X\n", len, buffer[8]);

	spin_lock_irqsave(&current->sigmask_lock, flags);
	sigpipe = sigismember(&current->signal, SIGPIPE);
	old_set = current->blocked;
	siginitsetinv(&current->blocked, sigmask(SIGKILL)|sigmask(SIGSTOP));
	recalc_sigpending(current);
	spin_unlock_irqrestore(&current->sigmask_lock, flags);

	fs = get_fs();
	set_fs(get_ds());

	result = smb_send_raw(server_sock(server), (void *) buffer, len);
	if (result > 0)
	{
		result = smb_receive(server);
	}

	/* read/write errors are handled by errno */
	spin_lock_irqsave(&current->sigmask_lock, flags);
	if (result == -EPIPE && !sigpipe)
		sigdelset(&current->signal, SIGPIPE);
	current->blocked = old_set;
	recalc_sigpending(current);
	spin_unlock_irqrestore(&current->sigmask_lock, flags);

	set_fs(fs);

	if (result >= 0)
	{
		int result2 = smb_catch_keepalive(server);
		if (result2 < 0)
		{
			printk(KERN_ERR "smb_request: catch keepalive failed\n");
			result = result2;
		}
	}
	if (result < 0)
		goto bad_conn;
	/*
	 * Check for fatal server errors ...
	 */
	if (server->rcls) {
		int error = smb_errno(server);
		if (error == EBADSLT) {
			printk(KERN_ERR "smb_request: tree ID invalid\n");
			result = error;
			goto bad_conn;
		}
	}

out:
	DEBUG1("result = %d\n", result);
	return result;
	
bad_conn:
	PARANOIA("result %d, setting invalid\n", result);
	server->state = CONN_INVALID;
	smb_invalidate_inodes(server);
	goto out;
bad_no_packet:
	printk(KERN_ERR "smb_request: no packet!\n");
	goto out;
bad_no_conn:
	printk(KERN_ERR "smb_request: connection %d not valid!\n",
	       server->state);
	goto out;
}
Example #24
0
bool cli_receive_smb(struct cli_state *cli)
{
	ssize_t len;
	uint16_t mid;
	uint32_t seqnum;

	/* fd == -1 causes segfaults -- Tom ([email protected]) */
	if (cli->fd == -1)
		return false; 

 again:
	len = client_receive_smb(cli, 0);
	
	if (len > 0) {
		/* it might be an oplock break request */
		if (!(CVAL(cli->inbuf, smb_flg) & FLAG_REPLY) &&
		    CVAL(cli->inbuf,smb_com) == SMBlockingX &&
		    SVAL(cli->inbuf,smb_vwv6) == 0 &&
		    SVAL(cli->inbuf,smb_vwv7) == 0) {
			if (cli->oplock_handler) {
				int fnum = SVAL(cli->inbuf,smb_vwv2);
				unsigned char level = CVAL(cli->inbuf,smb_vwv3+1);
				if (!NT_STATUS_IS_OK(cli->oplock_handler(cli, fnum, level))) {
					return false;
				}
			}
			/* try to prevent loops */
			SCVAL(cli->inbuf,smb_com,0xFF);
			goto again;
		}
	}

	/* If the server is not responding, note that now */
	if (len < 0) {
                DEBUG(0, ("Receiving SMB: Server stopped responding\n"));
		close(cli->fd);
		cli->fd = -1;
		return false;
	}

	mid = SVAL(cli->inbuf,smb_mid);
	seqnum = cli_state_get_seqnum(cli, mid);

	if (!cli_check_sign_mac(cli, cli->inbuf, seqnum+1)) {
		/*
		 * If we get a signature failure in sessionsetup, then
		 * the server sometimes just reflects the sent signature
		 * back to us. Detect this and allow the upper layer to
		 * retrieve the correct Windows error message.
		 */
		if (CVAL(cli->outbuf,smb_com) == SMBsesssetupX &&
			(smb_len(cli->inbuf) > (smb_ss_field + 8 - 4)) &&
			(SVAL(cli->inbuf,smb_flg2) & FLAGS2_SMB_SECURITY_SIGNATURES) &&
			memcmp(&cli->outbuf[smb_ss_field],&cli->inbuf[smb_ss_field],8) == 0 &&
			cli_is_error(cli)) {

			/*
			 * Reflected signature on login error. 
			 * Set bad sig but don't close fd.
			 */
			cli->smb_rw_error = SMB_READ_BAD_SIG;
			return true;
		}

		DEBUG(0, ("SMB Signature verification failed on incoming packet!\n"));
		cli->smb_rw_error = SMB_READ_BAD_SIG;
		close(cli->fd);
		cli->fd = -1;
		return false;
	};
	return true;
}