/**************************************************************************** reply to a read and X This code is basically stolen from reply_read_and_X with some wrinkles to handle pipes. ****************************************************************************/ int reply_pipe_read_and_X(char *inbuf,char *outbuf,int length,int bufsize) { pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2); int smb_maxcnt = SVAL(inbuf,smb_vwv5); int smb_mincnt = SVAL(inbuf,smb_vwv6); int nread = -1; char *data; /* we don't use the offset given to use for pipe reads. This is deliberate, instead we always return the next lump of data on the pipe */ #if 0 uint32 smb_offs = IVAL(inbuf,smb_vwv3); #endif if (!p) return(ERROR(ERRDOS,ERRbadfid)); set_message(outbuf,12,0,True); data = smb_buf(outbuf); nread = (int)read_from_pipe(p, data, (size_t)smb_maxcnt); if (nread < 0) return(UNIXERROR(ERRDOS,ERRnoaccess)); SSVAL(outbuf,smb_vwv5,nread); SSVAL(outbuf,smb_vwv6,smb_offset(data,outbuf)); SSVAL(smb_buf(outbuf),-2,nread); DEBUG(3,("readX-IPC pnum=%04x min=%d max=%d nread=%d\n", p->pnum, smb_mincnt, smb_maxcnt, nread)); return chain_reply(inbuf,outbuf,length,bufsize); }
int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize) { smb_np_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2); uint16 vuid = SVAL(inbuf,smb_uid); size_t numtowrite = SVAL(inbuf,smb_vwv10); int nwritten = -1; int smb_doff = SVAL(inbuf, smb_vwv11); BOOL pipe_start_message_raw = ((SVAL(inbuf, smb_vwv7) & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) == (PIPE_START_MESSAGE|PIPE_RAW_MODE)); char *data; if (!p) { return(ERROR_DOS(ERRDOS,ERRbadfid)); } if (p->vuid != vuid) { return ERROR_NT(NT_STATUS_INVALID_HANDLE); } data = smb_base(inbuf) + smb_doff; if (numtowrite == 0) { nwritten = 0; } else { if(pipe_start_message_raw) { /* * For the start of a message in named pipe byte mode, * the first two bytes are a length-of-pdu field. Ignore * them (we don't trust the client). JRA. */ if(numtowrite < 2) { DEBUG(0,("reply_pipe_write_and_X: start of message set and not enough data sent.(%u)\n", (unsigned int)numtowrite )); return (UNIXERROR(ERRDOS,ERRnoaccess)); } data += 2; numtowrite -= 2; } nwritten = write_to_pipe(p, data, numtowrite); } if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) { return (UNIXERROR(ERRDOS,ERRnoaccess)); } set_message(outbuf,6,0,True); nwritten = (pipe_start_message_raw ? nwritten + 2 : nwritten); SSVAL(outbuf,smb_vwv2,nwritten); DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten)); return chain_reply(inbuf,outbuf,length,bufsize); }
//#if 0 int reply_pipe_write_and_X(char *inbuf,char *outbuf,int length,int bufsize, int ProcSockID, int threadid) { pipes_struct *p = get_rpc_pipe_p(inbuf,smb_vwv2, threadid); uint32 numtowrite = SVAL(inbuf,smb_vwv10); int nwritten = -1; int smb_doff = SVAL(inbuf, smb_vwv11); int pipe_start_message_raw = ((SVAL(inbuf, smb_vwv7) & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) == (PIPE_START_MESSAGE|PIPE_RAW_MODE)); char *data; if (!p) return(ERROR(ERRDOS,ERRbadfid)); data = smb_base(inbuf) + smb_doff; if (numtowrite == 0) nwritten = 0; else { if(pipe_start_message_raw) { /* * For the start of a message in named pipe byte mode, * the first two bytes are a length-of-pdu field. Ignore * them (we don't trust the client. JRA. */ if(numtowrite < 2) { //0507 DEBUG(0,("reply_pipe_write_and_X: start of message set and not enough data sent.(%u)\n", //0507 (unsigned int)numtowrite )); //0507 return (UNIXERROR(ERRDOS,ERRnoaccess)); return 0; } data += 2; numtowrite -= 2; } nwritten = write_to_pipe(p, data, numtowrite); } if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) //0507 return (UNIXERROR(ERRDOS,ERRnoaccess)); return 0; set_message(outbuf,6,0,True); nwritten = (pipe_start_message_raw ? nwritten + 2 : nwritten); SSVAL(outbuf,smb_vwv2,nwritten); //0507 DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", //0507 p->pnum, nwritten)); return chain_reply(inbuf,outbuf,length,bufsize, ProcSockID, threadid); }
static void reply_lockingX_success(struct blocking_lock_record *blr) { reply_outbuf(blr->req, 2, 0); /* * As this message is a lockingX call we must handle * any following chained message correctly. * This is normally handled in construct_reply(), * but as that calls switch_message, we can't use * that here and must set up the chain info manually. */ chain_reply(blr->req); TALLOC_FREE(blr->req->outbuf); }
void reply_pipe_read_and_X(struct smb_request *req) { smb_np_struct *p = get_rpc_pipe_p(SVAL(req->inbuf,smb_vwv2)); int smb_maxcnt = SVAL(req->inbuf,smb_vwv5); int smb_mincnt = SVAL(req->inbuf,smb_vwv6); int nread = -1; char *data; bool unused; /* we don't use the offset given to use for pipe reads. This is deliberate, instead we always return the next lump of data on the pipe */ #if 0 uint32 smb_offs = IVAL(req->inbuf,smb_vwv3); #endif if (!p) { reply_doserror(req, ERRDOS, ERRbadfid); return; } reply_outbuf(req, 12, smb_maxcnt); data = smb_buf(req->outbuf); nread = read_from_pipe(p, data, smb_maxcnt, &unused); if (nread < 0) { reply_doserror(req, ERRDOS, ERRnoaccess); return; } srv_set_message((char *)req->outbuf, 12, nread, False); SSVAL(req->outbuf,smb_vwv5,nread); SSVAL(req->outbuf,smb_vwv6,smb_offset(data,req->outbuf)); SSVAL(smb_buf(req->outbuf),-2,nread); DEBUG(3,("readX-IPC pnum=%04x min=%d max=%d nread=%d\n", p->pnum, smb_mincnt, smb_maxcnt, nread)); chain_reply(req); }
static void reply_lockingX_success(blocking_lock_record *blr) { char *outbuf = OutBuffer; int bufsize = BUFFER_SIZE; char *inbuf = blr->inbuf; int outsize = 0; construct_reply_common(inbuf, outbuf); set_message(outbuf,2,0,True); /* * As this message is a lockingX call we must handle * any following chained message correctly. * This is normally handled in construct_reply(), * but as that calls switch_message, we can't use * that here and must set up the chain info manually. */ outsize = chain_reply(inbuf,outbuf,blr->length,bufsize); outsize += chain_size; send_blocking_reply(outbuf,outsize); }
void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req) { const char *fname = NULL; char *pipe_name = NULL; files_struct *fsp; TALLOC_CTX *ctx = talloc_tos(); NTSTATUS status; /* XXXX we need to handle passed times, sattr and flags */ srvstr_pull_req_talloc(ctx, req, &pipe_name, req->buf, STR_TERMINATE); if (!pipe_name) { reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, ERRDOS, ERRbadpipe); return; } /* If the name doesn't start \PIPE\ then this is directed */ /* at a mailslot or something we really, really don't understand, */ /* not just something we really don't understand. */ if ( strncmp(pipe_name,PIPE,PIPELEN) != 0 ) { reply_doserror(req, ERRSRV, ERRaccess); return; } DEBUG(4,("Opening pipe %s.\n", pipe_name)); /* Strip \PIPE\ off the name. */ fname = pipe_name + PIPELEN; #if 0 /* * Hack for NT printers... JRA. */ if(should_fail_next_srvsvc_open(fname)) { reply_doserror(req, ERRSRV, ERRaccess); return; } #endif status = open_np_file(req, fname, &fsp); if (!NT_STATUS_IS_OK(status)) { if (NT_STATUS_EQUAL(status, NT_STATUS_OBJECT_NAME_NOT_FOUND)) { reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, ERRDOS, ERRbadpipe); return; } reply_nterror(req, status); return; } /* Prepare the reply */ reply_outbuf(req, 15, 0); /* Mark the opened file as an existing named pipe in message mode. */ SSVAL(req->outbuf,smb_vwv9,2); SSVAL(req->outbuf,smb_vwv10,0xc700); SSVAL(req->outbuf, smb_vwv2, fsp->fnum); SSVAL(req->outbuf, smb_vwv3, 0); /* fmode */ srv_put_dos_date3((char *)req->outbuf, smb_vwv4, 0); /* mtime */ SIVAL(req->outbuf, smb_vwv6, 0); /* size */ SSVAL(req->outbuf, smb_vwv8, 0); /* rmode */ SSVAL(req->outbuf, smb_vwv11, 0x0001); chain_reply(req); return; }
int reply_open_pipe_and_X(char *inbuf,char *outbuf,int length,int bufsize) { pstring fname; uint16 vuid = SVAL(inbuf, smb_uid); pipes_struct *p; int smb_ofun = SVAL(inbuf,smb_vwv8); int size=0,fmode=0,mtime=0,rmode=0; int i; /* XXXX we need to handle passed times, sattr and flags */ pstrcpy(fname,smb_buf(inbuf)); /* If the name doesn't start \PIPE\ then this is directed */ /* at a mailslot or something we really, really don't understand, */ /* not just something we really don't understand. */ if ( strncmp(fname,PIPE,PIPELEN) != 0 ) return(ERROR(ERRSRV,ERRaccess)); //0507 DEBUG(4,("Opening pipe %s.\n", fname)); /* See if it is one we want to handle. */ for( i = 0; pipe_names[i].client_pipe ; i++ ) //0507 if( strequal(fname,pipe_names[i].client_pipe) ) if( !strcmp(fname,pipe_names[i].client_pipe) ) break; if (pipe_names[i].client_pipe == NULL) return(ERROR(ERRSRV,ERRaccess)); /* Strip \PIPE\ off the name. */ pstrcpy(fname,smb_buf(inbuf) + PIPELEN); /* * Hack for NT printers... JRA. */ //0611 if(should_fail_next_srvsvc_open(fname)) // return(ERROR(ERRSRV,ERRaccess)); //0507 return 0; /* Known pipes arrive with DIR attribs. Remove it so a regular file */ /* can be opened and add it in after the open. */ //0507 DEBUG(3,("Known pipe %s opening.\n",fname)); smb_ofun |= FILE_CREATE_IF_NOT_EXIST; p = open_rpc_pipe_p(fname, vuid, threadid); if (!p) return(ERROR(ERRSRV,ERRnofids)); /* Prepare the reply */ set_message(outbuf,15,0,True); /* Mark the opened file as an existing named pipe in message mode. */ SSVAL(outbuf,smb_vwv9,2); SSVAL(outbuf,smb_vwv10,0xc700); if (rmode == 2) { //0507 DEBUG(4,("Resetting open result to open from create.\n")); rmode = 1; } SSVAL(outbuf,smb_vwv2, p->pnum); SSVAL(outbuf,smb_vwv3,fmode); //0507 put_dos_date3(outbuf,smb_vwv4,mtime); SIVAL(outbuf,smb_vwv6,size); SSVAL(outbuf,smb_vwv8,rmode); SSVAL(outbuf,smb_vwv11,0x0001); return chain_reply(inbuf,outbuf,length,bufsize); }
int reply_sesssetup_and_X(connection_struct *conn, char *inbuf,char *outbuf, int length,int bufsize) { int sess_vuid; int smb_bufsize; DATA_BLOB lm_resp; DATA_BLOB nt_resp; DATA_BLOB plaintext_password; fstring user; fstring sub_user; /* Sainitised username for substituion */ fstring domain; fstring native_os; fstring native_lanman; fstring primary_domain; static BOOL done_sesssetup = False; auth_usersupplied_info *user_info = NULL; auth_serversupplied_info *server_info = NULL; NTSTATUS nt_status; BOOL doencrypt = global_encrypted_passwords_negotiated; DATA_BLOB session_key; START_PROFILE(SMBsesssetupX); ZERO_STRUCT(lm_resp); ZERO_STRUCT(nt_resp); ZERO_STRUCT(plaintext_password); DEBUG(3,("wct=%d flg2=0x%x\n", CVAL(inbuf, smb_wct), SVAL(inbuf, smb_flg2))); /* a SPNEGO session setup has 12 command words, whereas a normal NT1 session setup has 13. See the cifs spec. */ if (CVAL(inbuf, smb_wct) == 12 && (SVAL(inbuf, smb_flg2) & FLAGS2_EXTENDED_SECURITY)) { if (!global_spnego_negotiated) { DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at SPNEGO session setup when it was not negoitiated.\n")); return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } if (SVAL(inbuf,smb_vwv4) == 0) { setup_new_vc_session(); } return reply_sesssetup_and_X_spnego(conn, inbuf, outbuf, length, bufsize); } smb_bufsize = SVAL(inbuf,smb_vwv2); if (Protocol < PROTOCOL_NT1) { uint16 passlen1 = SVAL(inbuf,smb_vwv7); /* Never do NT status codes with protocols before NT1 as we don't get client caps. */ remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES); if ((passlen1 > MAX_PASS_LEN) || (passlen1 > smb_bufrem(inbuf, smb_buf(inbuf)))) { return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); } if (doencrypt) { lm_resp = data_blob(smb_buf(inbuf), passlen1); } else { plaintext_password = data_blob(smb_buf(inbuf), passlen1+1); /* Ensure null termination */ plaintext_password.data[passlen1] = 0; } srvstr_pull_buf(inbuf, user, smb_buf(inbuf)+passlen1, sizeof(user), STR_TERMINATE); *domain = 0; } 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); char *save_p = smb_buf(inbuf); uint16 byte_count; if(global_client_caps == 0) { global_client_caps = IVAL(inbuf,smb_vwv11); if (!(global_client_caps & CAP_STATUS32)) { remove_from_common_flags2(FLAGS2_32_BIT_ERROR_CODES); } /* 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 (!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; } /* check for nasty tricks */ if (passlen1 > MAX_PASS_LEN || passlen1 > smb_bufrem(inbuf, p)) { return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); } if (passlen2 > MAX_PASS_LEN || passlen2 > smb_bufrem(inbuf, p+passlen1)) { return ERROR_NT(nt_status_squash(NT_STATUS_INVALID_PARAMETER)); } /* Save the lanman2 password and the NT md4 password. */ if ((doencrypt) && (passlen1 != 0) && (passlen1 != 24)) { doencrypt = False; } if (doencrypt) { lm_resp = data_blob(p, passlen1); nt_resp = data_blob(p+passlen1, passlen2); } else { pstring pass; BOOL unic=SVAL(inbuf, smb_flg2) & FLAGS2_UNICODE_STRINGS; #if 0 /* This was the previous fix. Not sure if it's still valid. JRA. */ if ((ra_type == RA_WINNT) && (passlen2 == 0) && unic && passlen1) { /* NT4.0 stuffs up plaintext unicode password lengths... */ srvstr_pull(inbuf, pass, smb_buf(inbuf) + 1, sizeof(pass), passlen1, STR_TERMINATE); #endif if (unic && (passlen2 == 0) && passlen1) { /* Only a ascii plaintext password was sent. */ srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass), passlen1, STR_TERMINATE|STR_ASCII); } else { srvstr_pull(inbuf, pass, smb_buf(inbuf), sizeof(pass), unic ? passlen2 : passlen1, STR_TERMINATE); } plaintext_password = data_blob(pass, strlen(pass)+1); } p += passlen1 + passlen2; p += srvstr_pull_buf(inbuf, user, p, sizeof(user), STR_TERMINATE); p += srvstr_pull_buf(inbuf, domain, p, sizeof(domain), STR_TERMINATE); p += srvstr_pull_buf(inbuf, native_os, p, sizeof(native_os), STR_TERMINATE); p += srvstr_pull_buf(inbuf, native_lanman, p, sizeof(native_lanman), STR_TERMINATE); /* not documented or decoded by Ethereal but there is one more string in the extra bytes which is the same as the PrimaryDomain when using extended security. Windows NT 4 and 2003 use this string to store the native lanman string. Windows 9x does not include a string here at all so we have to check if we have any extra bytes left */ byte_count = SVAL(inbuf, smb_vwv13); if ( PTR_DIFF(p, save_p) < byte_count) p += srvstr_pull_buf(inbuf, primary_domain, p, sizeof(primary_domain), STR_TERMINATE); else fstrcpy( primary_domain, "null" ); DEBUG(3,("Domain=[%s] NativeOS=[%s] NativeLanMan=[%s] PrimaryDomain=[%s]\n", domain, native_os, native_lanman, primary_domain)); if ( ra_type == RA_WIN2K ) { if ( strlen(native_lanman) == 0 ) ra_lanman_string( primary_domain ); else ra_lanman_string( native_lanman ); } } if (SVAL(inbuf,smb_vwv4) == 0) { setup_new_vc_session(); } DEBUG(3,("sesssetupX:name=[%s]\\[%s]@[%s]\n", domain, user, get_remote_machine_name())); if (*user) { if (global_spnego_negotiated) { /* This has to be here, because this is a perfectly valid behaviour for guest logons :-( */ DEBUG(0,("reply_sesssetup_and_X: Rejecting attempt at 'normal' session setup after negotiating spnego.\n")); return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } fstrcpy(sub_user, user); } else { fstrcpy(sub_user, lp_guestaccount()); } sub_set_smb_name(sub_user); reload_services(True); if (lp_security() == SEC_SHARE) { /* in share level we should ignore any passwords */ data_blob_free(&lm_resp); data_blob_free(&nt_resp); data_blob_clear_free(&plaintext_password); map_username(sub_user); add_session_user(sub_user); add_session_workgroup(domain); /* Then force it to null for the benfit of the code below */ *user = 0; } if (!*user) { nt_status = check_guest_password(&server_info); } else if (doencrypt) { if (!negprot_global_auth_context) { DEBUG(0, ("reply_sesssetup_and_X: Attempted encrypted session setup without negprot denied!\n")); return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } nt_status = make_user_info_for_reply_enc(&user_info, user, domain, lm_resp, nt_resp); if (NT_STATUS_IS_OK(nt_status)) { nt_status = negprot_global_auth_context->check_ntlm_password(negprot_global_auth_context, user_info, &server_info); } } else { struct auth_context *plaintext_auth_context = NULL; const uint8 *chal; nt_status = make_auth_context_subsystem(&plaintext_auth_context); if (NT_STATUS_IS_OK(nt_status)) { chal = plaintext_auth_context->get_ntlm_challenge(plaintext_auth_context); if (!make_user_info_for_reply(&user_info, user, domain, chal, plaintext_password)) { nt_status = NT_STATUS_NO_MEMORY; } if (NT_STATUS_IS_OK(nt_status)) { nt_status = plaintext_auth_context->check_ntlm_password(plaintext_auth_context, user_info, &server_info); (plaintext_auth_context->free)(&plaintext_auth_context); } } } free_user_info(&user_info); if (!NT_STATUS_IS_OK(nt_status)) { nt_status = do_map_to_guest(nt_status, &server_info, user, domain); } if (!NT_STATUS_IS_OK(nt_status)) { data_blob_free(&nt_resp); data_blob_free(&lm_resp); data_blob_clear_free(&plaintext_password); return ERROR_NT(nt_status_squash(nt_status)); } /* Ensure we can't possible take a code path leading to a null defref. */ if (!server_info) { return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } nt_status = create_local_token(server_info); if (!NT_STATUS_IS_OK(nt_status)) { DEBUG(10, ("create_local_token failed: %s\n", nt_errstr(nt_status))); data_blob_free(&nt_resp); data_blob_free(&lm_resp); data_blob_clear_free(&plaintext_password); return ERROR_NT(nt_status_squash(nt_status)); } if (server_info->user_session_key.data) { session_key = data_blob(server_info->user_session_key.data, server_info->user_session_key.length); } else { session_key = data_blob(NULL, 0); } data_blob_clear_free(&plaintext_password); /* it's ok - setup a reply */ set_message(outbuf,3,0,True); if (Protocol >= PROTOCOL_NT1) { char *p = smb_buf( outbuf ); p += add_signature( outbuf, p ); set_message_end( outbuf, p ); /* perhaps grab OS version here?? */ } if (server_info->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 */ if (lp_security() == SEC_SHARE) { sess_vuid = UID_FIELD_INVALID; data_blob_free(&session_key); TALLOC_FREE(server_info); } else { /* register_vuid keeps the server info */ sess_vuid = register_vuid(server_info, session_key, nt_resp.data ? nt_resp : lm_resp, sub_user); if (sess_vuid == UID_FIELD_INVALID) { data_blob_free(&nt_resp); data_blob_free(&lm_resp); return ERROR_NT(nt_status_squash(NT_STATUS_LOGON_FAILURE)); } /* current_user_info is changed on new vuid */ reload_services( True ); sessionsetup_start_signing_engine(server_info, inbuf); } data_blob_free(&nt_resp); data_blob_free(&lm_resp); SSVAL(outbuf,smb_uid,sess_vuid); SSVAL(inbuf,smb_uid,sess_vuid); if (!done_sesssetup) max_send = MIN(max_send,smb_bufsize); done_sesssetup = True; END_PROFILE(SMBsesssetupX); return chain_reply(inbuf,outbuf,length,bufsize); }
void reply_open_pipe_and_X(connection_struct *conn, struct smb_request *req) { const char *fname = NULL; char *pipe_name = NULL; smb_np_struct *p; int size=0,fmode=0,mtime=0,rmode=0; int i; TALLOC_CTX *ctx = talloc_tos(); /* XXXX we need to handle passed times, sattr and flags */ srvstr_pull_buf_talloc(ctx, req->inbuf, req->flags2, &pipe_name, smb_buf(req->inbuf), STR_TERMINATE); if (!pipe_name) { reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, ERRDOS, ERRbadpipe); return; } /* If the name doesn't start \PIPE\ then this is directed */ /* at a mailslot or something we really, really don't understand, */ /* not just something we really don't understand. */ if ( strncmp(pipe_name,PIPE,PIPELEN) != 0 ) { reply_doserror(req, ERRSRV, ERRaccess); return; } DEBUG(4,("Opening pipe %s.\n", pipe_name)); /* See if it is one we want to handle. */ for( i = 0; pipe_names[i].client_pipe ; i++ ) { if( strequal(pipe_name,pipe_names[i].client_pipe)) { break; } } if (pipe_names[i].client_pipe == NULL) { reply_botherror(req, NT_STATUS_OBJECT_NAME_NOT_FOUND, ERRDOS, ERRbadpipe); return; } /* Strip \PIPE\ off the name. */ fname = pipe_name + PIPELEN; #if 0 /* * Hack for NT printers... JRA. */ if(should_fail_next_srvsvc_open(fname)) { reply_doserror(req, ERRSRV, ERRaccess); return; } #endif /* Known pipes arrive with DIR attribs. Remove it so a regular file */ /* can be opened and add it in after the open. */ DEBUG(3,("Known pipe %s opening.\n",fname)); p = open_rpc_pipe_p(fname, conn, req->vuid); if (!p) { reply_doserror(req, ERRSRV, ERRnofids); return; } /* Prepare the reply */ reply_outbuf(req, 15, 0); /* Mark the opened file as an existing named pipe in message mode. */ SSVAL(req->outbuf,smb_vwv9,2); SSVAL(req->outbuf,smb_vwv10,0xc700); if (rmode == 2) { DEBUG(4,("Resetting open result to open from create.\n")); rmode = 1; } SSVAL(req->outbuf,smb_vwv2, p->pnum); SSVAL(req->outbuf,smb_vwv3,fmode); srv_put_dos_date3((char *)req->outbuf,smb_vwv4,mtime); SIVAL(req->outbuf,smb_vwv6,size); SSVAL(req->outbuf,smb_vwv8,rmode); SSVAL(req->outbuf,smb_vwv11,0x0001); chain_reply(req); return; }
void reply_pipe_write_and_X(struct smb_request *req) { smb_np_struct *p = get_rpc_pipe_p(SVAL(req->inbuf,smb_vwv2)); size_t numtowrite = SVAL(req->inbuf,smb_vwv10); int nwritten = -1; int smb_doff = SVAL(req->inbuf, smb_vwv11); bool pipe_start_message_raw = ((SVAL(req->inbuf, smb_vwv7) & (PIPE_START_MESSAGE|PIPE_RAW_MODE)) == (PIPE_START_MESSAGE|PIPE_RAW_MODE)); char *data; if (!p) { reply_doserror(req, ERRDOS, ERRbadfid); return; } if (p->vuid != req->vuid) { reply_nterror(req, NT_STATUS_INVALID_HANDLE); return; } data = smb_base(req->inbuf) + smb_doff; if (numtowrite == 0) { nwritten = 0; } else { if(pipe_start_message_raw) { /* * For the start of a message in named pipe byte mode, * the first two bytes are a length-of-pdu field. Ignore * them (we don't trust the client). JRA. */ if(numtowrite < 2) { DEBUG(0,("reply_pipe_write_and_X: start of " "message set and not enough data " "sent.(%u)\n", (unsigned int)numtowrite )); reply_unixerror(req, ERRDOS, ERRnoaccess); return; } data += 2; numtowrite -= 2; } nwritten = write_to_pipe(p, data, numtowrite); } if ((nwritten == 0 && numtowrite != 0) || (nwritten < 0)) { reply_unixerror(req, ERRDOS,ERRnoaccess); return; } reply_outbuf(req, 6, 0); nwritten = (pipe_start_message_raw ? nwritten + 2 : nwritten); SSVAL(req->outbuf,smb_vwv2,nwritten); DEBUG(3,("writeX-IPC pnum=%04x nwritten=%d\n", p->pnum, nwritten)); chain_reply(req); }
int reply_open_pipe_and_X(connection_struct *conn, char *inbuf,char *outbuf,int length,int bufsize) { pstring fname; pstring pipe_name; uint16 vuid = SVAL(inbuf, smb_uid); smb_np_struct *p; int size=0,fmode=0,mtime=0,rmode=0; int i; /* XXXX we need to handle passed times, sattr and flags */ srvstr_pull_buf(inbuf, pipe_name, smb_buf(inbuf), sizeof(pipe_name), STR_TERMINATE); /* If the name doesn't start \PIPE\ then this is directed */ /* at a mailslot or something we really, really don't understand, */ /* not just something we really don't understand. */ if ( strncmp(pipe_name,PIPE,PIPELEN) != 0 ) { return(ERROR_DOS(ERRSRV,ERRaccess)); } DEBUG(4,("Opening pipe %s.\n", pipe_name)); /* See if it is one we want to handle. */ for( i = 0; pipe_names[i].client_pipe ; i++ ) { if( strequal(pipe_name,pipe_names[i].client_pipe)) { break; } } if (pipe_names[i].client_pipe == NULL) { return(ERROR_BOTH(NT_STATUS_OBJECT_NAME_NOT_FOUND,ERRDOS,ERRbadpipe)); } /* Strip \PIPE\ off the name. */ pstrcpy(fname, pipe_name + PIPELEN); #if 0 /* * Hack for NT printers... JRA. */ if(should_fail_next_srvsvc_open(fname)) return(ERROR(ERRSRV,ERRaccess)); #endif /* Known pipes arrive with DIR attribs. Remove it so a regular file */ /* can be opened and add it in after the open. */ DEBUG(3,("Known pipe %s opening.\n",fname)); p = open_rpc_pipe_p(fname, conn, vuid); if (!p) { return(ERROR_DOS(ERRSRV,ERRnofids)); } /* Prepare the reply */ set_message(outbuf,15,0,True); /* Mark the opened file as an existing named pipe in message mode. */ SSVAL(outbuf,smb_vwv9,2); SSVAL(outbuf,smb_vwv10,0xc700); if (rmode == 2) { DEBUG(4,("Resetting open result to open from create.\n")); rmode = 1; } SSVAL(outbuf,smb_vwv2, p->pnum); SSVAL(outbuf,smb_vwv3,fmode); srv_put_dos_date3(outbuf,smb_vwv4,mtime); SIVAL(outbuf,smb_vwv6,size); SSVAL(outbuf,smb_vwv8,rmode); SSVAL(outbuf,smb_vwv11,0x0001); return chain_reply(inbuf,outbuf,length,bufsize); }