diff options
-rw-r--r-- | source3/smbd/process.c | 8 | ||||
-rw-r--r-- | source3/smbd/reply.c | 154 |
2 files changed, 111 insertions, 51 deletions
diff --git a/source3/smbd/process.c b/source3/smbd/process.c index 6751272567..be311b4135 100644 --- a/source3/smbd/process.c +++ b/source3/smbd/process.c @@ -882,10 +882,10 @@ static const struct smb_message_struct { /* 0xbd */ { NULL, NULL, NULL, 0 }, /* 0xbe */ { NULL, NULL, NULL, 0 }, /* 0xbf */ { NULL, NULL, NULL, 0 }, -/* 0xc0 */ { "SMBsplopen",reply_printopen,NULL,AS_USER}, -/* 0xc1 */ { "SMBsplwr",reply_printwrite,NULL,AS_USER}, -/* 0xc2 */ { "SMBsplclose",reply_printclose,NULL,AS_USER}, -/* 0xc3 */ { "SMBsplretq",reply_printqueue,NULL,AS_USER}, +/* 0xc0 */ { "SMBsplopen",NULL,reply_printopen,AS_USER}, +/* 0xc1 */ { "SMBsplwr",NULL,reply_printwrite,AS_USER}, +/* 0xc2 */ { "SMBsplclose",NULL,reply_printclose,AS_USER}, +/* 0xc3 */ { "SMBsplretq",NULL,reply_printqueue,AS_USER}, /* 0xc4 */ { NULL, NULL, NULL, 0 }, /* 0xc5 */ { NULL, NULL, NULL, 0 }, /* 0xc6 */ { NULL, NULL, NULL, 0 }, diff --git a/source3/smbd/reply.c b/source3/smbd/reply.c index 9313f3883c..1d0791a899 100644 --- a/source3/smbd/reply.c +++ b/source3/smbd/reply.c @@ -4187,55 +4187,72 @@ void reply_echo(connection_struct *conn, struct smb_request *req) Reply to a printopen. ****************************************************************************/ -int reply_printopen(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_printopen(connection_struct *conn, struct smb_request *req) { - int outsize = 0; files_struct *fsp; NTSTATUS status; START_PROFILE(SMBsplopen); - + + if (req->wct < 2) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBsplopen); + return; + } + if (!CAN_PRINT(conn)) { + reply_doserror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBsplopen); - return ERROR_DOS(ERRDOS,ERRnoaccess); + return; } /* Open for exclusive use, write only. */ status = print_fsp_open(conn, NULL, &fsp); if (!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBsplopen); - return(ERROR_NT(status)); + return; } - outsize = set_message(inbuf,outbuf,1,0,True); - SSVAL(outbuf,smb_vwv0,fsp->fnum); + reply_outbuf(req, 1, 0); + SSVAL(req->outbuf,smb_vwv0,fsp->fnum); DEBUG(3,("openprint fd=%d fnum=%d\n", fsp->fh->fd, fsp->fnum)); END_PROFILE(SMBsplopen); - return(outsize); + return; } /**************************************************************************** Reply to a printclose. ****************************************************************************/ -int reply_printclose(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_printclose(connection_struct *conn, struct smb_request *req) { - int outsize = set_message(inbuf,outbuf,0,0,False); - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); + files_struct *fsp; NTSTATUS status; + START_PROFILE(SMBsplclose); - CHECK_FSP(fsp,conn); + if (req->wct < 3) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBsplclose); + return; + } + + fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); + + if (!check_fsp(conn, req, fsp, ¤t_user)) { + END_PROFILE(SMBsplclose); + return; + } if (!CAN_PRINT(conn)) { + reply_nterror(req, NT_STATUS_DOS(ERRSRV, ERRerror)); END_PROFILE(SMBsplclose); - return ERROR_NT(NT_STATUS_DOS(ERRSRV, ERRerror)); + return; } DEBUG(3,("printclose fd=%d fnum=%d\n", @@ -4244,39 +4261,50 @@ int reply_printclose(connection_struct *conn, status = close_file(fsp,NORMAL_CLOSE); if(!NT_STATUS_IS_OK(status)) { + reply_nterror(req, status); END_PROFILE(SMBsplclose); - return ERROR_NT(status); + return; } END_PROFILE(SMBsplclose); - return(outsize); + return; } /**************************************************************************** Reply to a printqueue. ****************************************************************************/ -int reply_printqueue(connection_struct *conn, - char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_printqueue(connection_struct *conn, struct smb_request *req) { - int outsize = set_message(inbuf,outbuf,2,3,True); - int max_count = SVAL(inbuf,smb_vwv0); - int start_index = SVAL(inbuf,smb_vwv1); + int max_count; + int start_index; + START_PROFILE(SMBsplretq); + if (req->wct < 2) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBsplretq); + return; + } + + max_count = SVAL(req->inbuf,smb_vwv0); + start_index = SVAL(req->inbuf,smb_vwv1); + /* we used to allow the client to get the cnum wrong, but that is really quite gross and only worked when there was only one printer - I think we should now only accept it if they get it right (tridge) */ if (!CAN_PRINT(conn)) { + reply_doserror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBsplretq); - return ERROR_DOS(ERRDOS,ERRnoaccess); + return; } - SSVAL(outbuf,smb_vwv0,0); - SSVAL(outbuf,smb_vwv1,0); - SCVAL(smb_buf(outbuf),0,1); - SSVAL(smb_buf(outbuf),1,0); + reply_outbuf(req, 2, 3); + SSVAL(req->outbuf,smb_vwv0,0); + SSVAL(req->outbuf,smb_vwv1,0); + SCVAL(smb_buf(req->outbuf),0,1); + SSVAL(smb_buf(req->outbuf),1,0); DEBUG(3,("printqueue start_index=%d max_count=%d\n", start_index, max_count)); @@ -4284,7 +4312,6 @@ int reply_printqueue(connection_struct *conn, { print_queue_struct *queue = NULL; print_status_struct status; - char *p = smb_buf(outbuf) + 3; int count = print_queue_status(SNUM(conn), &queue, &status); int num_to_get = ABS(max_count); int first = (max_count>0?start_index:start_index+max_count+1); @@ -4297,22 +4324,33 @@ int reply_printqueue(connection_struct *conn, for (i=first;i<first+num_to_get;i++) { + char blob[28]; + char *p = blob; + srv_put_dos_date2(p,0,queue[i].time); SCVAL(p,4,(queue[i].status==LPQ_PRINTING?2:3)); SSVAL(p,5, queue[i].job); SIVAL(p,7,queue[i].size); SCVAL(p,11,0); - srvstr_push(outbuf, SVAL(outbuf, smb_flg2), p+12, + srvstr_push(blob, req->flags2, p+12, queue[i].fs_user, 16, STR_ASCII); - p += 28; + + if (message_push_blob( + &req->outbuf, + data_blob_const( + blob, sizeof(blob))) == -1) { + reply_nterror(req, NT_STATUS_NO_MEMORY); + END_PROFILE(SMBsplretq); + return; + } } if (count > 0) { - outsize = set_message(inbuf,outbuf,2,28*count+3,False); - SSVAL(outbuf,smb_vwv0,count); - SSVAL(outbuf,smb_vwv1,(max_count>0?first+count:first-1)); - SCVAL(smb_buf(outbuf),0,1); - SSVAL(smb_buf(outbuf),1,28*count); + SSVAL(req->outbuf,smb_vwv0,count); + SSVAL(req->outbuf,smb_vwv1, + (max_count>0?first+count:first-1)); + SCVAL(smb_buf(req->outbuf),0,1); + SSVAL(smb_buf(req->outbuf),1,28*count); } SAFE_FREE(queue); @@ -4321,44 +4359,66 @@ int reply_printqueue(connection_struct *conn, } END_PROFILE(SMBsplretq); - return(outsize); + return; } /**************************************************************************** Reply to a printwrite. ****************************************************************************/ -int reply_printwrite(connection_struct *conn, char *inbuf,char *outbuf, int dum_size, int dum_buffsize) +void reply_printwrite(connection_struct *conn, struct smb_request *req) { int numtowrite; - int outsize = set_message(inbuf,outbuf,0,0,False); char *data; - files_struct *fsp = file_fsp(SVAL(inbuf,smb_vwv0)); + files_struct *fsp; START_PROFILE(SMBsplwr); + + if (req->wct < 1) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBsplwr); + return; + } + fsp = file_fsp(SVAL(req->inbuf,smb_vwv0)); + + if (!check_fsp(conn, req, fsp, ¤t_user)) { + END_PROFILE(SMBsplwr); + return; + } + if (!CAN_PRINT(conn)) { + reply_doserror(req, ERRDOS, ERRnoaccess); END_PROFILE(SMBsplwr); - return ERROR_DOS(ERRDOS,ERRnoaccess); + return; } - CHECK_FSP(fsp,conn); if (!CHECK_WRITE(fsp)) { - return(ERROR_DOS(ERRDOS,ERRbadaccess)); + reply_doserror(req, ERRDOS, ERRbadaccess); + END_PROFILE(SMBsplwr); + return; } - numtowrite = SVAL(smb_buf(inbuf),1); - data = smb_buf(inbuf) + 3; - + numtowrite = SVAL(smb_buf(req->inbuf),1); + + if (smb_buflen(req->inbuf) < numtowrite + 3) { + reply_nterror(req, NT_STATUS_INVALID_PARAMETER); + END_PROFILE(SMBsplwr); + return; + } + + data = smb_buf(req->inbuf) + 3; + if (write_file(fsp,data,-1,numtowrite) != numtowrite) { + reply_unixerror(req, ERRHRD, ERRdiskfull); END_PROFILE(SMBsplwr); - return(UNIXERROR(ERRHRD,ERRdiskfull)); + return; } DEBUG( 3, ( "printwrite fnum=%d num=%d\n", fsp->fnum, numtowrite ) ); END_PROFILE(SMBsplwr); - return(outsize); + return; } /**************************************************************************** |