int buffer_add_int16(xrtp_buffer_t * buf, int16 word) { if(buf->len_data + sizeof(int16) > buf->len) { return OS_EREFUSE; } if(buf->byte_order == BIGEND_ORDER) { buffer_log(("buffer_add_int16: Add BE(%d) to buf[%d]@%d\n", word, buf->pos, (int)buf->data)); RSSVALS(buf->data, buf->len_data, word); } else { buffer_log(("buffer_add_int16: Add LE(%d) to buf[%d]@%d\n", word, buf->pos, (int)buf->data)); SSVALS(buf->data, buf->len_data, word); } buf->len_data += sizeof(int16); buf->pos += sizeof(int16); return OS_OK; }
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); }
static void reply_nt1(struct smb_request *req, uint16 choice) { /* 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; bool negotiate_spnego = False; struct timespec ts; ssize_t ret; struct smbd_server_connection *sconn = req->sconn; bool signing_enabled = false; bool signing_required = false; sconn->smb1.negprot.encrypted_passwords = lp_encrypt_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 ( (req->flags2 & FLAGS2_EXTENDED_SECURITY) && ((req->flags2 & FLAGS2_SMB_SECURITY_SIGNATURES_REQUIRED) == 0) ) { if (get_remote_arch() != RA_SAMBA) { set_remote_arch( RA_VISTA ); } } reply_outbuf(req,17,0); /* do spnego in user level security if the client supports it and we can do encrypted passwords */ if (sconn->smb1.negprot.encrypted_passwords && lp_use_spnego() && (req->flags2 & 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(req->outbuf, smb_flg2, req->flags2 | FLAGS2_EXTENDED_SECURITY); } capabilities |= CAP_NT_SMBS|CAP_RPC_REMOTE_APIS; if (lp_unicode()) { capabilities |= CAP_UNICODE; } if (lp_unix_extensions()) { capabilities |= CAP_UNIX; } if (lp_large_readwrite()) capabilities |= CAP_LARGE_READX|CAP_LARGE_WRITEX|CAP_W2K_SMBS; capabilities |= CAP_LARGE_FILES; if (!lp_async_smb_echo_handler() && lp_read_raw() && lp_write_raw()) capabilities |= CAP_RAW_MODE; if (lp_nt_status_support()) capabilities |= CAP_STATUS32; if (lp_host_msdfs()) capabilities |= CAP_DFS; secword |= NEGOTIATE_SECURITY_USER_LEVEL; if (sconn->smb1.negprot.encrypted_passwords) { secword |= NEGOTIATE_SECURITY_CHALLENGE_RESPONSE; } signing_enabled = smb_signing_is_allowed(req->sconn->smb1.signing_state); signing_required = smb_signing_is_mandatory(req->sconn->smb1.signing_state); if (signing_enabled) { secword |= NEGOTIATE_SECURITY_SIGNATURES_ENABLED; /* No raw mode with smb signing. */ capabilities &= ~CAP_RAW_MODE; if (signing_required) { secword |=NEGOTIATE_SECURITY_SIGNATURES_REQUIRED; } } SSVAL(req->outbuf,smb_vwv0,choice); SCVAL(req->outbuf,smb_vwv1,secword); smbXsrv_connection_init_tables(req->sconn->conn, PROTOCOL_NT1); SSVAL(req->outbuf,smb_vwv1+1, lp_max_mux()); /* maxmpx */ SSVAL(req->outbuf,smb_vwv2+1, 1); /* num vcs */ SIVAL(req->outbuf,smb_vwv3+1, sconn->smb1.negprot.max_recv); /* max buffer. LOTS! */ SIVAL(req->outbuf,smb_vwv5+1, 0x10000); /* raw size. full 64k */ SIVAL(req->outbuf,smb_vwv7+1, getpid()); /* session key */ SIVAL(req->outbuf,smb_vwv9+1, capabilities); /* capabilities */ clock_gettime(CLOCK_REALTIME,&ts); put_long_date_timespec(TIMESTAMP_SET_NT_OR_BETTER,(char *)req->outbuf+smb_vwv11+1,ts); SSVALS(req->outbuf,smb_vwv15+1,set_server_zone_offset(ts.tv_sec)/60); if (!negotiate_spnego) { /* Create a token value and add it to the outgoing packet. */ if (sconn->smb1.negprot.encrypted_passwords) { uint8 chal[8]; /* note that we do not send a challenge at all if we are using plaintext */ get_challenge(sconn, chal); ret = message_push_blob( &req->outbuf, data_blob_const(chal, sizeof(chal))); if (ret == -1) { DEBUG(0, ("Could not push challenge\n")); reply_nterror(req, NT_STATUS_NO_MEMORY); return; } SCVAL(req->outbuf, smb_vwv16+1, ret); } ret = message_push_string(&req->outbuf, lp_workgroup(), STR_UNICODE|STR_TERMINATE |STR_NOALIGN); if (ret == -1) { DEBUG(0, ("Could not push workgroup string\n")); reply_nterror(req, NT_STATUS_NO_MEMORY); return; } ret = message_push_string(&req->outbuf, lp_netbios_name(), STR_UNICODE|STR_TERMINATE |STR_NOALIGN); if (ret == -1) { DEBUG(0, ("Could not push netbios name string\n")); reply_nterror(req, NT_STATUS_NO_MEMORY); return; } DEBUG(3,("not using SPNEGO\n")); } else { DATA_BLOB spnego_blob = negprot_spnego(req, req->sconn); if (spnego_blob.data == NULL) { reply_nterror(req, NT_STATUS_NO_MEMORY); return; } ret = message_push_blob(&req->outbuf, spnego_blob); if (ret == -1) { DEBUG(0, ("Could not push spnego blob\n")); reply_nterror(req, NT_STATUS_NO_MEMORY); return; } data_blob_free(&spnego_blob); SCVAL(req->outbuf,smb_vwv16+1, 0); DEBUG(3,("using SPNEGO\n")); } return; }
bool cli_send_trans(struct cli_state *cli, int trans, const char *pipe_name, int fid, int flags, uint16 *setup, unsigned int lsetup, unsigned int msetup, const char *param, unsigned int lparam, unsigned int mparam, const char *data, unsigned int ldata, unsigned int mdata) { unsigned int i; unsigned int this_ldata,this_lparam; unsigned int tot_data=0,tot_param=0; char *outdata,*outparam; char *p; int pipe_name_len=0; uint16 mid; this_lparam = MIN(lparam,cli->max_xmit - (500+lsetup*2)); /* hack */ this_ldata = MIN(ldata,cli->max_xmit - (500+lsetup*2+this_lparam)); memset(cli->outbuf,'\0',smb_size); cli_set_message(cli->outbuf,14+lsetup,0,True); SCVAL(cli->outbuf,smb_com,trans); SSVAL(cli->outbuf,smb_tid, cli->cnum); cli_setup_packet(cli); /* * Save the mid we're using. We need this for finding * signing replies. */ mid = cli->mid; if (pipe_name) { pipe_name_len = clistr_push(cli, smb_buf(cli->outbuf), pipe_name, -1, STR_TERMINATE); } outparam = smb_buf(cli->outbuf)+(trans==SMBtrans ? pipe_name_len : 3); outdata = outparam+this_lparam; /* primary request */ SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */ SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */ SSVAL(cli->outbuf,smb_mprcnt,mparam); /* mprcnt */ SSVAL(cli->outbuf,smb_mdrcnt,mdata); /* mdrcnt */ SCVAL(cli->outbuf,smb_msrcnt,msetup); /* msrcnt */ SSVAL(cli->outbuf,smb_flags,flags); /* flags */ SIVAL(cli->outbuf,smb_timeout,0); /* timeout */ SSVAL(cli->outbuf,smb_pscnt,this_lparam); /* pscnt */ SSVAL(cli->outbuf,smb_psoff,smb_offset(outparam,cli->outbuf)); /* psoff */ SSVAL(cli->outbuf,smb_dscnt,this_ldata); /* dscnt */ SSVAL(cli->outbuf,smb_dsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */ SCVAL(cli->outbuf,smb_suwcnt,lsetup); /* suwcnt */ for (i=0;i<lsetup;i++) /* setup[] */ SSVAL(cli->outbuf,smb_setup+i*2,setup[i]); p = smb_buf(cli->outbuf); if (trans != SMBtrans) { *p++ = 0; /* put in a null smb_name */ *p++ = 'D'; *p++ = ' '; /* observed in OS/2 */ } if (this_lparam) /* param[] */ memcpy(outparam,param,this_lparam); if (this_ldata) /* data[] */ memcpy(outdata,data,this_ldata); cli_setup_bcc(cli, outdata+this_ldata); show_msg(cli->outbuf); if (!cli_send_smb(cli)) { return False; } cli_state_seqnum_persistent(cli, mid); if (this_ldata < ldata || this_lparam < lparam) { /* receive interim response */ if (!cli_receive_smb(cli) || cli_is_error(cli)) { cli_state_seqnum_remove(cli, mid); return(False); } tot_data = this_ldata; tot_param = this_lparam; while (tot_data < ldata || tot_param < lparam) { this_lparam = MIN(lparam-tot_param,cli->max_xmit - 500); /* hack */ this_ldata = MIN(ldata-tot_data,cli->max_xmit - (500+this_lparam)); cli_set_message(cli->outbuf,trans==SMBtrans?8:9,0,True); SCVAL(cli->outbuf,smb_com,(trans==SMBtrans ? SMBtranss : SMBtranss2)); outparam = smb_buf(cli->outbuf); outdata = outparam+this_lparam; /* secondary request */ SSVAL(cli->outbuf,smb_tpscnt,lparam); /* tpscnt */ SSVAL(cli->outbuf,smb_tdscnt,ldata); /* tdscnt */ SSVAL(cli->outbuf,smb_spscnt,this_lparam); /* pscnt */ SSVAL(cli->outbuf,smb_spsoff,smb_offset(outparam,cli->outbuf)); /* psoff */ SSVAL(cli->outbuf,smb_spsdisp,tot_param); /* psdisp */ SSVAL(cli->outbuf,smb_sdscnt,this_ldata); /* dscnt */ SSVAL(cli->outbuf,smb_sdsoff,smb_offset(outdata,cli->outbuf)); /* dsoff */ SSVAL(cli->outbuf,smb_sdsdisp,tot_data); /* dsdisp */ if (trans==SMBtrans2) SSVALS(cli->outbuf,smb_sfid,fid); /* fid */ if (this_lparam) /* param[] */ memcpy(outparam,param+tot_param,this_lparam); if (this_ldata) /* data[] */ memcpy(outdata,data+tot_data,this_ldata); cli_setup_bcc(cli, outdata+this_ldata); show_msg(cli->outbuf); cli->mid = mid; if (!cli_send_smb(cli)) { cli_state_seqnum_remove(cli, mid); return False; } tot_data += this_ldata; tot_param += this_lparam; } } return(True); }