Decrypt Firefox password database - c++

I want to write a simple utility that extracts passwords from a Firefox password database (the corresponding file is called signons.sqlite in the profile folder).
What I've done so far: Opened database using sqlite, retrieved encrypted username, encrypted password and address of website (all stored as std::string).
So, the only thing remaining is to decrypt the username and password strings.
I tried the following (PK11Decrypt ought to store the plaintext password in plaintext):
void Firefox_Importer::PK11Decrypt(string _cipheredBuffer, char **plaintext) {
// declarations needed
SECItem * request;
SECItem * reply;
unsigned int len = (unsigned int)_cipheredBuffer.length();
const char* cipheredBuffer = (const char*)_cipheredBuffer.c_str();
// generate request and reply SECItem; seems to work properly
reply = SECITEM_AllocItem(NULL, NULL, 0);
if (reply == NULL) cout << "Error allocating SECITEM." << endl;
request = NSSBase64_DecodeBuffer(NULL, NULL, cipheredBuffer, len);
if (request == NULL) cout << "Error decoding buffer." << endl;
// the following is not working
SECStatus tmp = PK11SDR_Decrypt(request, reply, NULL);
if(tmp != SECSuccess) cout << "Something went wrong during decrypting" << endl;
*plaintext = (char*)malloc(reply->len + 1);
strncpy(*plaintext, (const char*)reply->data, reply->len);
(*plaintext)[reply->len] = '\0';
SECITEM_FreeItem(request, true);
SECITEM_FreeItem(reply, true);
}
When PK11Decrypt is called, it prints Something went wrong during decrypting, indicating that the call to PK11SDR_Decrypt didn't work properly. It always returns SECFailure (which corresponds to -1).
Does anybody have some hints or know what I'm doing wrong?

It could be that the call to PK11_Authenticate() isn't optional, even if no master password is set (yes, NSS is pretty messed up). So you might need to do the following first:
PK11SlotInfo *slot = PK11_GetInternalKeySlot();
if (!slot) cout << "Error getting internal slot" << endl;
SECStatus tmp = PK11_Authenticate(slot, PR_TRUE, NULL);
if (tmp != SECSuccess) cout << "Authentication error" << endl;
Note that I pass NULL as context to PK11_Authenticate(), the context is only required if a password prompt should be displayed.
Edit: Never mind, I noticed that PK11SDR_Decrypt() will call both functions internally. Given that you get SECFailure as result, it is likely that PK11_GetInternalKeySlot() fails which would indicate that NSS isn't initialized properly.

Firefox is opensource software. You can find the most recent source here, it is up to you to find the part where they decrypt the passwords and copy it into your application. Good luck.

Related

C++ OpenSSL: libssl fails to verify certificates on Windows

I've done a lot of looking around but I can't seem to find a decent solution to this problem. Many of the StackOverflow posts are regarding Ruby, but I'm using OpenSSL more or less directly (via the https://gitlab.com/eidheim/Simple-Web-Server library) for a C++ application/set of libraries, and need to work out how to fix this completely transparently for users (they should not need to hook up any custom certificate verification file in order to use the application).
On Windows, when I attempt to use the SimpleWeb HTTPS client, connections fail if I have certificate verification switched on, because the certificate for the connection fails to validate. This is not the case on Linux, where verification works fine.
I was advised to follow this solution to import the Windows root certificates into OpenSSL so that they could be used by the verification routines. However, this doesn't seem to make any difference as far as I can see. I have dug into the guts of the libssl verification functions to try and understand exactly what's going on, and although the above answer recommends adding the Windows root certificates to a new X509_STORE, it appears that the SSL connection context has its own store which is set up when the connection is initialised. This makes me think that simply creating a new X509_STORE and adding certificates there is not helping because the connection doesn't actually use that store.
It may well be that I've spent so much time debugging the minutiae of libssl that I'm missing what the actual approach to solving this problem should be. Does OpenSSL provide a canonical way of looking up system certificates that I'm not setting? Alternatively, could the issue be the way that the SimpleWeb library/ASIO is initialising OpenSSL? I know that the library allows you to provide a path for a "verify file" for certificates, but I feel like this wouldn't be an appropriate solution since I as a developer should be using the certificates found on the end user's system, rather than hard-coding my own.
EDIT: For context, this is the code I'm using in a tiny example application:
#define MY_ENCODING_TYPE (PKCS_7_ASN_ENCODING | X509_ASN_ENCODING)
static void LoadSystemCertificates()
{
HCERTSTORE hStore;
PCCERT_CONTEXT pContext = nullptr;
X509 *x509 = nullptr;
X509_STORE *store = X509_STORE_new();
hStore = CertOpenSystemStore(NULL, "ROOT");
if (!hStore)
{
return;
}
while ((pContext = CertEnumCertificatesInStore(hStore, pContext)) != nullptr)
{
const unsigned char* encodedCert = reinterpret_cast<const unsigned char*>(pContext->pbCertEncoded);
x509 = d2i_X509(nullptr, &encodedCert, pContext->cbCertEncoded);
if (x509)
{
X509_STORE_add_cert(store, x509);
X509_free(x509);
}
}
CertCloseStore(hStore, 0);
}
static void MakeRequest(const std::string& address)
{
using Client = SimpleWeb::Client<SimpleWeb::HTTPS>;
Client httpsClient(address);
httpsClient.io_service = std::make_shared<asio::io_service>();
std::cout << "Making request to: " << address << std::endl;
bool hasResponse = false;
httpsClient.request("GET", [address, &hasResponse](std::shared_ptr<Client::Response> response, const SimpleWeb::error_code& error)
{
hasResponse = true;
if ( error )
{
std::cerr << "Got error from " << address << ": " << error.message() << std::endl;
}
else
{
std::cout << "Got response from " << address << ":\n" << response->content.string() << std::endl;
}
});
while ( !hasResponse )
{
httpsClient.io_service->poll();
httpsClient.io_service->reset();
std::this_thread::sleep_for(std::chrono::milliseconds(20));
}
}
int main(int, char**)
{
LoadSystemCertificates();
MakeRequest("google.co.uk");
return 0;
}
The call returns me: Got error from google.co.uk: certificate verify failed
OK, to anyone who this might help in future, this is how I solved this issue. This answer to a related question helped.
It turns out that the issue was indeed that the SSL context was not making use of the certificate store that I'd set up. Everything else was OK, bu the missing piece of the puzzle was a call to SSL_CTX_set_cert_store(), which takes the certificate store and provides it to the SSL context.
In the context of the SimpleWeb library, the easiest way to do this appeared to be to subclass the SimpleWeb::Client<SimpleWeb::HTTPS> class and add the following to the constructor:
#define WIN32_LEAN_AND_MEAN
#include <Windows.h>
#include <wincrypt.h>
class MyClient : public SimpleWeb::Client<SimpleWeb::HTTPS>
{
public:
MyClient( /* ... */ ) :
SimpleWeb::Client<SimpleWeb::HTTPS>( /* ... */ )
{
AddWindowsRootCertificates();
}
private:
using OpenSSLContext = asio::ssl::context::native_handle_type;
void AddWindowsRootCertificates()
{
// Get the SSL context from the SimpleWeb class.
OpenSSLContext sslContext = context.native_handle();
// Get a certificate store populated with the Windows root certificates.
// If this fails for some reason, the function returns null.
X509_STORE* certStore = GetWindowsCertificateStore();
if ( sslContext && certStore )
{
// Set this store to be used for the SSL context.
SSL_CTX_set_cert_store(sslContext, certStore);
}
}
static X509_STORE* GetWindowsCertificateStore()
{
// To avoid populating the store every time, we keep a static
// pointer to the store and just initialise it the first time
// this function is called.
static X509_STORE* certificateStore = nullptr;
if ( !certificateStore )
{
// Not initialised yet, so do so now.
// Try to open the root certificate store.
HCERTSTORE rootStore = CertOpenSystemStore(0, "ROOT");
if ( rootStore )
{
// The new store is reference counted, so we can create it
// and keep the pointer around for later use.
certificateStore = X509_STORE_new();
PCCERT_CONTEXT pContext = nullptr;
while ( (pContext = CertEnumCertificatesInStore(rootStore, pContext)) != nullptr )
{
// d2i_X509() may modify the pointer, so make a local copy.
const unsigned char* content = pContext->pbCertEncoded;
// Convert the certificate to X509 format.
X509 *x509 = d2i_X509(NULL, &content, pContext->cbCertEncoded);
if ( x509 )
{
// Successful conversion, so add to the store.
X509_STORE_add_cert(certificateStore, x509);
// Release our reference.
X509_free(x509);
}
}
// Make sure to close the store.
CertCloseStore(rootStore, 0);
}
}
return certificateStore;
}
};
Obviously GetWindowsCertificateStore() would need to be abstracted out to somewhere platform-specific if your class needs to compile on multiple platforms.

How to get data from a specific data piece from a JSON

I'm trying to get the first accepted_answer_id.
If i print out the parsed data this is what it looks like
{"items":[{"accepted_answer_id":23249538,"question_id":23248046},{"accepted_answer_id":5582009,"question_id":5581697},{"accepted_answer_id":43114369,"question_id":43113569},{"accepted_answer_id":12120575,"question_id":12120425},{"question_id":22162858},{"accepted_answer_id":10101621,"question_id":10101556}]}
what I want is that first accepted_answer_id's numbers. So in this case all I want is 23249538. How would I go about doing this? I'm doing this using stack exchange API. This is for an assignment for school where I have to set up on our server a tool that when people ask a question gets them if available someones answer from stack overflow. This number will piped into another URL using CURL which will then grab the answer for me and print it to terminal for the user. I also want it that if there is no accepted_answer_id it just terminates the program with a failure to find answer to user.
//actually getting the data
result = curl_easy_perform(curl);
//making sure that the curl is ok and worked right
if(result != CURLE_OK)
{
cout << curl_easy_strerror(result) << endl;
return 1;
}
//making sure that the website gave info
int httpCode(0);
curl_easy_getinfo(curl, CURLINFO_RESPONSE_CODE, &httpCode);
curl_easy_cleanup(curl);
//if website worked it will be equal to 200
if(httpCode == 200)
{
cout << "Sucessful Response From URL" << endl;
json data = json::parse(readBuffer);
cout << data << endl;
}
}
You can use a json lib for CPP, such as rapidjson (rapidjson is faster)or jsoncpp, etc.
https://github.com/Tencent/rapidjson
https://github.com/open-source-parsers/jsoncpp

win32 C++ print string to printer

After a few days of searching the net on how exactly I can go about printing an arbitrary string to an arbitrary printer on windows, I finally came up with this code.
LPBYTE pPrinterEnum;
DWORD pcbNeeded, pcbReturned;
PRINTER_INFO_2 *piTwo = NULL;
HDC printer;
EnumPrinters(PRINTER_ENUM_LOCAL,NULL,2,NULL,0,&pcbNeeded,&pcbReturned);
pPrinterEnum = new BYTE[pcbNeeded];
if (!EnumPrinters(PRINTER_ENUM_LOCAL,NULL,2,pPrinterEnum,pcbNeeded,&pcbNeeded,&pcbReturned)) {
qDebug() << "In Print, could not enumerate printers";
} else {
piTwo = ((PRINTER_INFO_2*)pPrinterEnum);
for (int i = 0; i < pcbReturned; i++) {
QString name = QString::fromWCharArray(piTwo[i].pPrinterName);
if (this->m_printer_path == name) {
const WCHAR * driver = L"WINSPOOL\0";
printer = CreateDC(NULL,piTwo[i].pPrinterName,NULL,NULL);
}
}
}
if (printer == 0) {
qDebug() << "No Printer HDC";
return;
} else {
qDebug() << "Printer seems okay!";
}
qDebug() << "Starting Document";
DOCINFO di;
memset( &di, 0, sizeof( di ) );
di.cbSize = sizeof( di );
WCHAR * text = new WCHAR[ba.length()];
QString(ba).toWCharArray(text);
StartDoc(printer,&di);
qDebug() << "Writing text";
TextOut(printer,0, 0, text, ba.length());
qDebug() << "Text Written";
EndPage(printer);
qDebug() << "Page ended";
DeleteDC(printer);
qDebug() << "DC Deleted";
Some basic caveats:
1) I cannot use QPrinter. I need to write raw text, no postscript.
2) I do not know the name of the printer until the user sets it, and I do not know the size of the string to print until the user creates it.
Additional information:
a) The printer works, I can print from Notepad, Chrome, just about everything to the printer that I want.
b) I am willing to implement just about any hack. Ones like write it to a text file and issue the copy command don't seem to work, that is, I get a failed to initialize device error.
This works:
notepad /P Documents/test_print.txt
This does not work:
copy Documents\test_print.txt /D:EPSON_TM_T20
copy Documents\test_print.txt /D \MYCOMPUTER\epson_tm_t20 (leads to access denied, printer is shared)
print Documents\test_print.txt (Unable to initialize device)
I have tried just about every recommended way to print a text file from the command line, just doesn't work. I have installed, reinstalled driver, added printer, mucked with ports and done it all again.
Obviously there is something simple about windows printing that I am missing due to inexperience.
What I want to accomplish is:
1) Best Scenario( Directly write text to the printer)
2) Second best scenario (Write text to a file, then execute some program to print it for me) Notepad adds an annoying amount of space to the bottom of the printout wasting paper.
Since the program is for end users, I have to find a way to do this automagically for them, so I can't expect them to click checkbox a in tab 36 after running command obscure_configuration from a powershell.
Any help would be greatly appreciated.
/Jason
UPDATE
This is the working code, before I go through an spruce it up a bit, which prints the contents of a QByteArray to a thermal printer.
qDebug() << "Executing windows code";
BOOL bStatus = FALSE;
DOC_INFO_1 DocInfo;
DWORD dwJob = 0L;
DWORD dwBytesWritten = 0L;
HANDLE hPrinter;
wchar_t * name = new wchar_t[this->m_printer_path.length()+1];
this->m_printer_path.toWCharArray(name);
name[this->m_printer_path.length() + 1] = 0;
qDebug() << "opening printer";
bStatus = OpenPrinter(name,&hPrinter, NULL);
if (bStatus) {
qDebug() << "Printer opened";
DocInfo.pDocName = L"My Document";
DocInfo.pOutputFile = NULL;
DocInfo.pDatatype = L"RAW";
dwJob = StartDocPrinter( hPrinter, 1, (LPBYTE)&DocInfo );
if (dwJob > 0) {
qDebug() << "Job is set.";
bStatus = StartPagePrinter(hPrinter);
if (bStatus) {
qDebug() << "Writing text to printer";
bStatus = WritePrinter(hPrinter,ba.data(),ba.length(),&dwBytesWritten);
EndPagePrinter(hPrinter);
} else {
qDebug() << "could not start printer";
}
EndDocPrinter(hPrinter);
qDebug() << "closing doc";
} else {
qDebug() << "Couldn't create job";
}
ClosePrinter(hPrinter);
qDebug() << "closing printer";
} else {
qDebug() << "Could not open printer";
}
if (dwBytesWritten != ba.length()) {
qDebug() << "Wrong number of bytes";
} else {
qDebug() << "bytes written is correct " << QString::number(ba.length()) ;
}
Note: I do owe an apology to Skizz, what he wrote was actually helpful in debugging the fundamental issue. The characters in the QByteArray are preformatted specifically for the printer, the problem is, they contain several NULL bytes. When trying to send them to the printer, this causes TextOut to truncate the text, only printing the first few lines. Using WritePrinter, as suggested in the answer ignores null bytes and accepts a void * and a length, and just puts it all there.
Further, his response recommending the use of PrintDlg did work to fectch the correct printer HDC, the issus is that, the user first chooses a printer once, and then doesn't need to choose it each time they print, because they will be printing alot (It's a Point of Sale).
The problem with getting the printer HDC from the string name was due to not adding the all important NULL byte to wchar_* which was solved this way:
wchar_t * name = new wchar_t[this->m_printer_path.length()+1];
this->m_printer_path.toWCharArray(name);
name[this->m_printer_path.length() + 1] = 0;
In the above, m_printer_path is a string representation of the name of the printer taken from Print Manager.
Because the string has all the formatting necessary for the printer, there's no need to worry about new lines, or any formatting.
All three answers to this question were actually very helpful in implementing the final working solution, and I have voted up each answer, and I appreciate the time each person took in responding.
Most modern printers don't perform any form of layout processing of the data they are given. Thus, sending a sequence of characters to the printer would, at best, just print a line of text running off the side of the page in some default font. Carriage returns may work too.
What modern printers usually do is print pages using preprocessed data that the printer understands and defines what to print where and how to print it. All this preprocessing is done on the host PC and the results sent to the printer. This is why you usually install printer drivers - these drivers take the user data (whether it's a simple text file or a DTP page) and converts it into a language the printer understands.
The upshot of this is that sending raw text to the printer probably won't work.
Then you've got the problem of having multiple printers with different properties and languages.
So, in Windows, all this is abstracted into the printer device context object. This has the same interface as a graphics device context but you create it differently.
The Win32 API has a common dialog to let the user choose the printer. Use the PrintDlgEx function to allow the user to choose a printer. Then use the returned DC to draw text to the page.
There are a couple of MSDN articles describing how to send raw data (printer control codes, etc.) to a printer.
How To: Send Data Directly to a GDI Printer
How To: Send Data Directly to an XPS Printer
You have the right idea (though you should have StartPage and EndDoc calls to match up). The problem is that TextOut draws only a line of text. It won't break long strings into multiple lines, etc. You need to do that (or find code to do it).
If you know that the text will always fit on a single page, you could probably replace your TextOut with a DrawTextEx call, which can do basic line breaking, tab expansion, etc.
Why not try QPrint.. it prints raw text using a Generic Text Only driver
QString prn("^XA^FO121,41^A0N,19,15^FDABC DEFGHIJKLMNOPQRSTUVWXYZ^FS^XZ");
QPrinter printer(QPrinterInfo::defaultPrinter()); //the default printer is "Generic / Text Only"
QTextDocument doc(prn);
doc.print(&printer);
MTry the following code in C++:
#include<fstream>
Class PrinterDriver{
Private:
fstream print("PRN")
Public:
Void Print(char a[]){
print >>a;}
Char GetPrinterStatus[](){
char c[];
print<<c;
return c;}};
understand it(key)

C++/AS3 winsock send() wont write within else if statment

So, I have a server/client application, at a particular point in the code the client needs to log in to the server, so the server requsts a username and password from the client (and then checks it and blah blah blah)
heres my code,
client side (AS3)
function hwndLogKeyboard(evt:KeyboardEvent):void
{
if (evt.keyCode == 13)
{
var allow:Boolean = false;
var prompt:String;
socket.writeMultiByte("002", "us-ascii");
socket.writeByte(0);
socket.flush();
while (socket.bytesAvailable == 0)
{
trace("waiting for bytes to read");
}
prompt = socket.readMultiByte(2, "us-ascii"); //YOU WERE MISSING ); here originally updated as I was formatting, probably just copy paste error
trace(prompt);
if (prompt == "UN")//server has prompted for username information, time to send it
{
socket.writeMultiByte(inputname.text, "us-ascii");
socket.flush();
prompt = socket.readMultiByte(2, "us-ascii");
if (prompt == "PW")//server has prompted for password information, time to send it
{
socket.writeMultiByte(inputpass.text, "us-ascii");
socket.writeByte(0);
socket.flush();
}
}
//more code in here that i have commented out until this issue is resolved
}
and the server side (where im positive the problem is occuring, writtin in C++)
if(testr >= 0)
{
string dataR = string(buffer);
//data was recived from a client - analize the data to find out what it means
//signals are in the format "xxx" where 'x' is an int between 0-9
if(dataR == "001")
{
cout << "A new client has connected" << endl;
}
else if(dataR == "002")//002 is a client attempting to log-on to the server
{
cout << "Client requesting log-on" << endl;
char recvUsername[16];
const char requestUsername[3] = "UN";
char recvPassword[16];
const char requestPassword[3] = "PW";
send(Client,requestUsername,3,0);//request username from client
recv(Client,recvUsername,16,0);//got username, now time to request password
send(Client,requestPassword,16,0);//request password from client
recv(Client,recvPassword,3,0);//got password, now time to compare them against current records
cout << recvUsername << endl << recPassword << endl;
}
else if(dataR == "003")
{
cout << "A client has used chat" << endl;
}
}
else
{
cout << "error" << endl << testr << endl << WSAGetLastError << endl;
}
At first I thought it was a time issue, that perhaps the client was reading from the buffer before the server can write to it, becuase AS3 crashes becuase the read buffer is empty!
But, here's the trick, I can move my send(Client,requestUsername,3,0) to inside the if(dataR == "001") block, and it works fine. The data IS avalible for flash to read when it goes looking for it. In fact I can put that send statement almost anywhere in my server after the client's socket is created, and it works, just not where i need it to.
That's why i added the
while (socket.bytesAvailable == 0)
{
trace("waiting for bytes to read");
}
in the client, so that it would sit a loop until there was data to read, and if that had been the problem, i would have re-wrote some things to avoid that nasty while loop from having to be there. What I don't understand is that it goes into an infinite loop, flooding me with trace statements. the sever DOESN'T write the data to the socket, but from anywhere else in the code it will. I get no errors, no compiler complaints, it doesn't go out of scope or anything like that, something is just odd here.
help is much appreciated
-Tyler
still having this problem, it works everywhere else in the code except inside the 'else if' block, im completley stumped.

Flush queued GPIB responses

Architecture ->GBIP from external interface is connected to target ( linux) system via gpib bus.
Inside Linux box , there is ethernet cable from GPIB to motherboard.
The PIC_GPIB card on external interface is IEEE 488.2
I am sending a query from external interface to linux box.
Few scenarios
1) If I send a query which does not expect a response back , then next query send will work.
2) If I send a query which expect response back , and when I have received the response and read it and then fire next query it works fine.
3) BUT if I send a query from external interface and got response back and I ignore to read the response , then Next query fails.
I am requesting help for scenario 3.
The coding is done on linux side and its a socket programming , which uses linux inbuilt function from unistd.h for read and write.
My investigation : I have found there is a internal memory on gbib card on external interface which stores the value of previous response until we have the read. Generally I use IEEE string utility software to write commands that goes to linux box and read reposne via read button .
Could someone please direct me how to clean input buffer or memory which stores value so that write from external command contiunues without bothering to read it.
My code on linux side has been developed in C++ and socket programming. I have used in bulit write and read function to write and read to the gpib and to json server.
Sample code is shown below
bool GpibClass::ReadWriteFromGPIB()
{
bool check = true;
int n = 0;
char buffer[BUFFER_SIZE];
fd_set read_set;
struct timeval lTimeOut;
// Reset the read mask for the select
FD_ZERO(&read_set);
FD_SET(mGpibFd, &read_set);
FD_SET(mdiffFd, &read_set);
// Set Timeout to check the status of the connection
// when no data is being received
lTimeOut.tv_sec = CONNECTION_STATUS_CHECK_TIMEOUT_SECONDS;
lTimeOut.tv_usec = 0;
cout << "Entered into this function" << endl;
// Look for sockets with available data
if (-1 == select(FD_SETSIZE, &read_set, NULL, NULL, &lTimeOut))
{
cout << "Select failed" << endl;
// We don't know the cause of select's failure.
// Close everything and start from scratch:
CloseConnection(mGpibFd);
CloseConnection(mdifferntServer); // this is different server
check = false;
}
// Check if data is available from GPIB server,
// and if any read and push it to gpib
if(true == check)
{
cout << "Check data from GPIB after select" << endl;
if (FD_ISSET(mGpibFd, &read_set))
{
n = read(mGpibFd, buffer, BUFFER_SIZE);
cout << "Read from GPIB" << n << " bytes" << endl;
if(0 < n)
{
// write it to different server and check if we get response from it
}
else
{
// Something failed on socket read - most likely
// connection dropped. Close socket and retry later
CloseConnection(mGpibFd);
check = false;
}
}
}
// Check if data is available from different server,
// and if any read and push it to gpib
if(true == check)
{
cout << "Check data from diff server after select" << endl;
if (FD_ISSET(mdiffFd, &read_set))
{
n = read(mdiffFd, buffer, BUFFER_SIZE);
cout << "Read from diff servewr " << n << " bytes" << endl;
if (0 < n)
{
// Append, just in case - makes sure data is sent.
// Extra cr/lf shouldn't cause any problem if the json
// server has already added them
strcpy(buffer + n, "\r\n");
write(mGpibFd, buffer, n + 2);
std::cout <<" the buffer sixze = " << buffer << std::endl;
}
else
{
// Something failed on socket read - most likely
// connection dropped. Close socket and retry later
CloseConnection(mdiffFd);
check = false;
}
}
}
return check;
}
You should ordinarily be reading responses after any operation which could generate them.
If you fail to do that, an easy solution would be to read responses in a loop until you have drained the queue to empty.
You can reset the instrument (probably *RST), but you would probably loose other state as well. You will have to check it's documentation to see if there is a command to reset only the response queue. Checking the documentation is always a good idea, because the number of instruments which precisely comply with the spec is dwarfed by the number which augment or omit parts in unique ways.