Suppressing password echo in golang in testable code - unit-testing

I have this code in Go:
func getPasswordAndUsername(reader io.Reader) (string, string) {
var username string
var password string
r := bufio.NewScanner(reader)
fmt.Printf("ENTER USERNAME:\n")
r.Scan()
username = r.Text()
fmt.Printf("ENTER PASSWORD:\n")
r.Scan()
password = r.Text()
return username, password
}
Which is great in that it's fully testable without user interaction. As I can build a reader out of both os.Stdin and, eg
strings.NewReader(teststring) - but awful in that it echoes the password in actual real-world use. The solutions I have seen of using a particular terminal type don't seem testable to me in the same way - ie I would have to have some code in the function that mutates the execution path depending on the context. Is there a way of ensuring that the function can have a single path of execution?
This is very clearly NOT the same question as how can I suppress password echoes in Go as I have made it clear I have seen the terminal-based code. Instead I am asking for a way to have a function that can run both in interactive mode and inside a test harness where there is no interaction.
Perhaps that isn't possible, but the answer is not simply "use the terminal code".

Related

How to make the login part in QuickFIX

How can I make the login part in QuickFIX in c++?
I found tons of tutorials and articles on how to do this on c# or java, but nothing on c++.
I have a server (acceptor), and a client (initiator). The username and password of the client are stored in the settings file, and are hardcoded in the server program.
From what I've read in the client I set the username and password in fromAdmin() and read and check the in the server in the toAdmin(), but how do I do that?
Here's what I've tried so far:
cast the message to a FIX44::Logon& object using:
FIX44::Logon& logon_message = dynamic_cast<FIX44::Logon&>(message);
Set the Username and password to the logon object like this:
if(session_settings.has("Username"))
{
FIX::Username username = session_settings.getString("Username");
logon_message.set(username);
}
And send the message like this:
FIX::Message messageToSend = logon_message;
FIX::Session::sendToTarget(messageToSend);
But I get this error on the cast:
cannot dynamic_cast 'message' (of type 'class FIX::Message') to type 'struct FIX44::Logon&' (target is not pointer or reference to complete type)
What I've tried I got inspired from http://niki.code-karma.com/2011/01/quickfix-logon-support-for-username-password/comment-page-1/.
I'm still not clear on how to make the client and the server.
Can anyone help me?
Possible mistakes:
I think you have fromAdmin()/toAdmin() backward. toAdmin() is called on outgoing admin messages, fromAdmin() is called on incoming. For the Initiator, you must set the fields within the toAdmin() callback. Your Acceptor will check the user/pass in fromAdmin().
Are you trying to dynamic_cast without first checking to see if it was a Logon message? The toAdmin() callback handles all admin messages; the message could be a Heartbeat, Logon, Logout, etc. That might explain your cast error.
As to what the code should look like, my C++ is rusty, but the basic pattern is this:
void YourMessageCracker::toAdmin( FIX::Message& message, const FIX::SessionID& sessionID)
{
if (FIX::MsgType_Logon == message.getHeader().getField(FIX::FIELD::MsgType))
{
FIX44::Logon& logon_message = dynamic_cast<FIX44::Logon&>(message);
logon_message.setField(FIX::Username("my_username"));
logon_message.setField(FIX::Password("my_password"));
}
}
From there, I think you can see how you'd write a similar fromAdmin() where you'd get the fields instead of setting them.
The above uses hard-coded user/pass, but you probably want to pull it from the config file. I think your calls to session_settings.getString(str) are correct for that.
(Please forgive any coding errors. I'm much more fluent in the Java/C# versions of the QF engine, though the basic principles are the same.)
I see that your first web reference uses the FIELD_GET_REF macro. It may be better than message.getHeader().getField(), but I'm not familiar with it.

MVC3/ASP.NET Best practice for ensuring a file argument is local and not trying to go outside of my application root directory?

Another developer maintains a large collection of crystal reports. I need to make these reports available with my ASP.NET MVC3 page without requiring a full Crystal Reports Server product.
The current reporting site is a classic ASP page with all of the args passed e.g Prompt0&Prompt1...etc
To that end, I've created an aspx page that sits in my MVC app and serves these reports out of a directory in my app like so:
public partial class Report : System.Web.UI.Page
{
protected void Page_Load(object sender, EventArgs e)
{
iLogger logger = LoggingFactory.CreateLogger();
ReportDocument rd = new ReportDocument();
string fileName = Request.QueryString["reportfile"];
if(!Regex.IsMatch(fileName,#"^[ 0-9a-zA-Z-_\\]+.rpt$"))
{
//log and throw
}
if(Path.IsPathRooted(fileName))
{
//log and throw
}
string rootPath = Server.MapPath("~/Reports/");
string path = Path.Combine(rootPath, fileName);
if (File.Exists(path))
{
rd.Load(path);
}
//get all keys starting with Prompt
var prompts = Request.QueryString.AllKeys.Where(q => q.StartsWith("Prompt"));
foreach (string promptKey in prompts)
{
//try to convert the rest of the string to an int
//yes, this should probably not just be a replace here...
string withoutPrompt = promptKey.Replace("Prompt", "");
int promptVal;
if (int.TryParse(withoutPrompt, out promptVal))
{
rd.SetParameterValue(promptVal, Request.QueryString[promptKey]);
}
//rd.SetParameterValue(promptKey, Request.QueryString[promptKey]);
}
CrystalReportViewer1.ReportSource = rd;
}
}
This works suprisingly well for the amount of effort (the report designer just needs to change the links within the report/query pages from e.g mywebserver.foo/Report1.rpt?Prompt....etc.etc to mywebserver.foo/mymvcreport/report.aspx?Filename=report1.rpt&Prompt... etc
So great, we can quickly move over to our MVC app and avoid having to have 10 sites go out and buy Crystal Server.
My obvious concern is that in the filename arg, someone could put just about anything in there, eg: "C:\foo\bar" or "../bla/blah",etc. Is there a single best practice for escaping these filenames and ensuring that it is a local path to my app?
I'd like to be able to take a parameter of eg: /Sales/Quarterly/Quarterly.rpt
My first thought is to just use a regex of eg [0-9a-zA-z-_\]+ to ensure no colon or dot characters can be used. Any suggestions on the most complete way to handle this?
Thanks!
EDIT:
Updated with preliminary checks I put in...
as long as you have assigned the right permissions to the application pool user this is something you shouldnt worry about.

Force mail spool to run via code

G'day
Is there a way to force the mail spooler to run, rather than wait for the delay period set in CFAdmin?
I had a look through the admin API and could not see anything, so I suspect the answer might be "no", but I thought perhaps someone knows how to call the underlying process?
The reason for wanting to do this is a bit of an edge case. On our testing server we've got the spooler set to run every 15sec, which - for most things - is fine. However we have an increasing number of unit tests (which run on this same test server) which inspect the content of email messages that have been sent for various elements we need to verify the integrity of. Currently the tests check the Undelivr dir and if the relevant mail message is not found, waits 2sec and tries again, waiting for a total of 20sec before deciding the test needs to be aborted (20sec is an arbitrary amount; 15sec between spool intervals, and some "wriggle room"). This works fine, but it means the unit test suite ends up running slower than it really needs to be, because these email-checking tests have this "up to 20sec" pause in them.
It's not the end of the world, but it's something I'd like to deal with if poss.
I guess one approach I could take is to check the spool dir instead, but I'd rather wait until the email message is "parked" in the Undelivr dir if poss. I'm slightly hesitant to mess with stuff in the spool dir (for no informed reason, granted).
Anyway, all my waffle aside, the short version of the question is "is there any way to force mail spool to run via code?".
Cheers.
<cfobject action="CREATE"
type="JAVA"
class="coldfusion.server.ServiceFactory"
name="factory">
<cfset MailSpoolService = factory.getMailSpoolService()>
<cfset MailSpoolService.restart()>
OK, I've got the official line from one of the Adobe engineers on this: basically what I'm trying to do can't be done, as it currently stands.
There's a method to re-run the email spool, but it's private to the mail spool service.
Oh well.
Cheers to everyone who looked into this for me & offered suggestions.
There's a method to re-run the email spool, but it's private to the
mail spool service.
As I mentioned in the comments, you can invoke a private method by setting its accessibility to true. Not something you want to do "willy-nilly", but probably okay for a unit test.
Disclaimer: I would not swear these are the right methods. But it did seem to kick-off mail processing in my brief tests.
<cfscript>
// Tested with CF 9.0.1
factory = createObject("java", "coldfusion.server.ServiceFactory");
spoolService = factory.getMailSpoolService();
spoolClass = spoolService.getClass();
methodToCall = spoolClass.getDeclaredMethod("refreshSpoolFiles", []);
methodToCall.setAccessible(true);
methodToCall.invoke(spoolService, []);
methodToCall = spoolClass.getDeclaredMethod("deliverStandard", []);
methodToCall.setAccessible(true);
methodToCall.invoke(spoolService, []);
</cfscript>

Which winapi function will allow me to change logged in user's password?

I'm looking for a winapi function that will allow me to change current logged in user's password. In my case, I know current password of logged in user. I use Windows 7 Ultimate.
Thanks.
Background
The background will look weird, but I'm going to describe it for clarification. My personal home PC is used by several users (dad, sister, cousins etc.). I'm the only administrator of the PC. All others are standard user. All user accounts are password protected.
I don't like that other people use my account as they mess with anything. I always install all softwares from my account and also troubleshoot PC. When I'm away from my PC for several weeks, may be some other user need to install a software, or do something that require administrative right. For this reason they may need to use my account. There may be emergency cases, and I must allow the user to log into my account by giving account password.
I recently faced such a situation. Before leaving my PC for long time, I changed my regular password to something else. I'll change that again when I reach my PC.
So I'm thinking to write a tiny program that will run each time someone logs into my account. The program will only change current password to something else that I only know. In this case, if anyone logs into my account, installs something, logs out, and cannot logged back in as the password changes.
Suppose I set my account's password as abcd. When someone logs in, the program will change it to abcde. Next time may be abc123 and so on.
You're looking for NetUserChangePassword(). Check this MSDN link for sample code:
http://support.microsoft.com/kb/151546
You could use ADSI to connect to the local machine, get the user object and call the change password action.
MSDN doc on IADsUser::ChangePassword has the following example.
The following "C++" code example shows how to change a user password.
HRESULT ChangePassword(
IADsUser *pUser,
LPWSTR oldPasswd,
LPWSTR newPasswd)
{
HRESULT hr=S_OK;
if(!pUser) { return E_FAIL;}
hr = pUser->ChangePassword(oldPasswd, newPasswd);
printf("User password has been changed");
return hr;
}
The following VB code example shows how to get the user and change a user password.
Dim usr As IADsUser
Dim szOldPass As String
Dim szNewPass As String
On Error GoTo Cleanup
' Fabrikam is the MSDN fictional domain - us '.' for localhost
Set usr = GetObject("WinNT://Fabrikam/JeffSmith,user")
' Add code to securely retrieve the old and new password.
usr.ChangePassword szOldPass, szNewPass
Cleanup:
If (Err.Number<>0) Then
MsgBox("An error has occurred. " & Err.Number)
End If
Set usr = Nothing

Unit Testing a Windows Scheduled Task Console App

I am in the process of taking over a legacy system that contains a Console App project, which is run as a Scheduled Task on our production servers. It mainly produces daily and weekly reports, does some database maintenance, etc.
The "main" of the console app handles inputting the command line arguments and determining which of several different processes to execute. Something like
Module MainModule
Public Sub Main()
'--- Check if command line arguments were specified
Dim args() As String = Environment.GetCommandLineArgs()
If args.Length > 1 Then
ConsoleMain(args)
End If
End Sub
Public Sub ConsoleMain(ByVal args() As String)
Dim rc As New Coordinator(enableEmails_)
Try
Dim arg_ As String = args(1)
Dim success_ As Boolean = True
Select Case arg_.ToUpper()
Case TaskType.OrderIntegration
success_ = rc.OrderIntegration()
Case TaskType.Motivators
success_ = rc.MotivatorsCreateFile(New CustomerMotivatorsManager)
... repeat for each of the various "Task Types"
End Module
What my question is:
- This being a Console App with a Main() and ConsoleMain(), I don't seem to have anything that I can access from a Test - i.e. the "Main" and "ConsoleMain" do not appear to be accessible. How can I unit-test something like this, to test the "if argument 'x' is passed, function 'y' is called"?
Thanks in advance,
I'm not sure why Main wouldn't be visible from your tests, unless VB.NET does some behind-the-curtains stuff to hide it.
In any case, why not move your code into its own class(es)? Then you can run unit tests against each class at a time, rather than executing the whole thing at once.
Unit tests usually execute against individual classes, rather than executing the Main entry point of an app.