how does putty generate the names of it's named pipes? - putty

agent_named_pipe_name.c has this:
char *agent_named_pipe_name(void)
{
char *username = get_username();
char *suffix = capi_obfuscate_string("Pageant");
char *pipename = dupprintf("\\\\.\\pipe\\pageant.%s.%s", username, suffix);
sfree(username);
sfree(suffix);
return pipename;
}
My question is... how does capi_obfuscate_string("Pageant") work? It's defined in cryptoapi.c and appears to just pass the parameter that's passed to it through sha256 and that's it. Except that when I do sha256('Pageant') locally what I get doesn't match the named pipe name that I got on my system. Further, one would think that if that is all that it were doing that running ./pageant --openssh-config pageant.conf on two systems, under different user accounts, would yield the same result on both systems and yet it's not.
Any ideas?

Related

How to get file as a resource with Storage?

I am trying to lock a file with the flock function but I am not able to do it. I work with Laravel 8 and Storage Class.
The code is as follows:
$disk = Storage::disk('communication');
$file_name = 'received.json';
$file_exists = $disk->exists($file_name);
if($file_exists){
flock($disk->get($file_name), LOCK_EX);
...
}
The problem I'm having is that when I invoke the get() function on the file path, it returns the contents of the file (a string), which causes the following error:
flock() expects parameter 1 to be resource, string given
I need to know how to get file as a resource and not the content of the file.
Could someone help me and tell me how to do it?
Thank you very much in advance.
You can use Storage::readStream() method
if($file_exists){
$stream=Storage::disk('communication')->readStream($file_name);
flock($stream, LOCK_EX);
}
As per php doc
flock(resource $stream, int $operation, int &$would_block = null): bool
First param needed stream.flock() allows you to perform a simple
reader/writer model which can be used on virtually every platform
(including most Unix derivatives and even Windows).
Ref:https://www.php.net/manual/en/function.flock.php

Extracting part of a string on jenkins pipeline

I am having some trouble with the syntax in my pipeline script.
I am trying to capture everything after the last forward slash "/" and before the last period "." in this string git#github.com:project/access-server-pd.git (access-server-pd)
Here (below) is how I would like to set it up
MYVAR="git#github.com:project/access-server-pd.git"
NAME=${MYVAR%.*} # retain the part before the colon
NAME=${NAME##*/} # retain the part after the last slash
echo $NAME
I have it current set up with triple quotes on the pipeline script:
stage('Git Clone') {
MYVAR="$GIT_REPO"
echo "$MYVAR"
NAME="""${MYVAR%.*}"""
echo "$NAME"
But I am receiving an unexpected token on "." error. How might I write this so that I can get this to work?
UPDATE: This command does the trick:
echo "git#github.com:project/access-server-pd.git" | sed 's#.*/\([^.]*\).*#\1#'
Now I just need to find the proper syntax to create a variable to store that value.
In this case, it looks like using a few Groovy/Java methods on the String can extract the parts.
final beforeColon = url.substring(0, url.indexOf(':')) // git#github.com
final afterLastSlash = url.substring(url.lastIndexOf('/') + 1, url.length()) // project/access-server-pd.git
This uses a few different methods:
public int String.indexOf(String str, int fromIndex)
public String String.substring(int beginIndex, int endIndex)
public int String.length()
public int String.lastIndexOf(String str)
You do need to be careful about the code you use in your pipeline. If it is sandboxed it will run in a protected domain where every invocation is security checked. For example, the whitelist in the Script Security Plugin whitelists all of the calls used above (for example, method java.lang.String lastIndexOf java.lang.String).
Performing String manipulation in your pipeline code is perfectly reasonable as you might make decisions and change your orchestration based on it.

Getting Windows domain username in correct case (to match Active Directory)

How can I sensibly get a Windows 7 user's username, but in the case that it's stored in the Active Directory domain (such as BillyBird), not using whatever case the user happened to type it when logging in (probably billybird, but could even be something like bILlYbIRd)?
This is in Perl, but since it's interacting with the operating system, solutions in other languages may be translatable.
I've tried these and they don't work; they all return the username in the case it was typed by the user when logging in*:
getlogin
Win32::LoginName
$ENV{USERNAME}
Win32::OLE->new('WScript.Network')->UserName
Win32API::Net::UserGetInfo
I have come up with a couple of bad ways of getting the right value. I'll post those as answers and hope that somebody else has a better one. Thanks.
* At least they do some of the time. For some users it alternates each time they log in between giving the as-typed and the as-AD values, but in all cases the above methods all agree with each other and %USERNAME%.
This gets the right value, but involves fetching the list of all domain users over the network and iterating over them looking for a case-insensitive match, which seems excessive just for returning something about the current user:
use v5.16;
use Win32::NetAdmin qw<GetDomainController GetUsers FILTER_NORMAL_ACCOUNT>;
my $comparable_username = fc getlogin;
GetDomainController('', '', my $domain_controller);
GetUsers($domain_controller, FILTER_NORMAL_ACCOUNT, \my #all_username);
my $username;
for (#all_username)
{
if (fc eq $comparable_username)
{
$username = $_;
last;
}
}
Here's my thought about using wmic put into practice
use strict;
use warnings 'all';
say username();
sub username {
for ( `wmic useraccount get name` ) {
return $1 if /\A($ENV{USERNAME})\s*\z/i;
}
return;
}
Update
To prevent wmic from fetching the full user name list, you can use the LIKE operator in a WHERE cal
sub username {
my #user = `wmic UserAccount WHERE ( name LIKE '$ENV{username}' ) GET name`;
return unless $user[1] =~ /\S/;
$user[1] =~ s/\s+\z//r;
}
This is a possible solution; it gets the username in the right case:
use IPC::System::Simple qw<capturex>;
my $username;
foreach (capturex qw<NET USER /DOMAIN>, getlogin)
{
if (/^User name\s*(\S+)$/)
{
$username = $1;
last;
}
}
However it involves running an external system command to parse its output (which is relatively slow), and relies on that output always being in English. An alternative solution that used an API for directly looking up whatever the NET USER command is doing would be superior to this one.

tmux titles-string not executing shell command

I have the following lines in my ~/.tmux.conf
set-option -g set-titles on
set-option -g set-titles-string "#(whoami)##H: $PWD \"#S\" (#W)#F [#I:#P]"
This has worked in the past but after upgrading to 2.0 shell commands are no longer executed. I now see in my title:
#(whoami)#myhostname.local: /Users/lander [..rest..]
According to the man page, this should work:
status-left string
Display string (by default the session name) to the left of the status
bar. string will be passed through strftime(3) and formats (see
FORMATS) will be expanded. It may also contain any of the following
special character sequences:
Character pair Replaced with
#(shell-command) First line of the command's output
#[attributes] Colour or attribute change
## A literal `#'
Well done for reading the code, it's simple really: set-titles-string switched to using formats which don't expand #(). Patching this is easy, and no, it's not good enough to reinstate status_print() to tmux.h, instead, job expansion should be a separate function and used from status_replace() and format_expand(). No idea when this will get done.
Thanks for playing.
The code that performed the task your are mentioning is no longer present in version 2.0. That's the short answer to the question above. Either the documentation hasn't been updated to reflect this, or this was done accidentally and is a bug.
What follows is exactly why I think this is the case. I'm at the end of my lunch break, so I can't create a patch for this right now. If no one else gets around to fixing this from here, I will take a stab at it this weekend.
I checkout out the git repository and took a look at code changes from version 1.9a -> 2.0.
The function that actually does this replacement is status_replace() in status.c. This still seems to work, as the command processing works in the status lines, which still call this function.
In version 1.9a, this was also called from server_client_set_title() in server-client.c, around line 770. It looks like this:
void
server_client_set_title(struct client *c)
{
struct session *s = c->session;
const char *template;
char *title;
template = options_get_string(&s->options, "set-titles-string");
title = status_replace(c, NULL, NULL, NULL, template, time(NULL), 1);
if (c->title == NULL || strcmp(title, c->title) != 0) {
free(c->title);
c->title = xstrdup(title);
tty_set_title(&c->tty, c->title);
}
free(title);
}
In version 2.0, this call has been replaced with (now down around line 947):
void
server_client_set_title(struct client *c)
{
struct session *s = c->session;
const char *template;
char *title;
struct format_tree *ft;
template = options_get_string(&s->options, "set-titles-string");
ft = format_create();
format_defaults(ft, c, NULL, NULL, NULL);
title = format_expand_time(ft, template, time(NULL));
if (c->title == NULL || strcmp(title, c->title) != 0) {
free(c->title);
c->title = xstrdup(title);
tty_set_title(&c->tty, c->title);
}
free(title);
format_free(ft);
}
It looks like calls to format_expand_time() and status_replace() might be mutually exclusive. That is the part that might take a bit of effort to fix -- getting the old function call back in there without breaking whatever new functionality they've just added.

RtlDosPathNameToNtPathName_U on "\\?\C:" Returns Invalid Path

Why is it that when I call RtlDosPathNameToNtPathName_U on the path \\?\C:, instead of getting back
\??\C:
I get back
\??\C:\฀\\?\C:
which is clearly incorrect?
Code snippet (in D):
struct CurDir { UnicodeString DosPath; HANDLE Handle; }
extern (Windows) static bool RtlDosPathNameToNtPathName_U(
in const(wchar)* DosPathName, out UnicodeString NtPathName,
out const(wchar)* NtFileNamePart, out CurDir DirectoryInfo);
wchar[] toNtPath(const(wchar)[] path)
{
UnicodeString ntPath;
CurDir curDir;
const(wchar)* fileNamePart;
enforce(RtlDosPathNameToNtPathName_U(path.ptr, ntPath,
fileNamePart, curDir));
try
{ return ntPath.Buffer[0 .. ntPath.Length / ntPath.Buffer[0].sizeof].dup; }
finally { RtlFreeHeap(RtlGetProcessHeap(), 0, ntPath.Buffer); }
}
writeln(toNtPath(r"\\?\C:")); //Returns the weird string
Update:
I figured out the problem -- see my answer.
RtlDosPathNameToNtPathName_U is giving you the correct output. The reason you see a weird-looking character in the middle is because UNICODE_STRINGs are not required to be null-terminated (which I'm sure you know already). The file name \??\C:\ is a completely valid native-format file name. I suspect what you really want is to prepend the device name instead of just referring to the GLOBAL?? directory like what RtlDosPathNameToNtPathName_U has done.
To do that, simply call NtQuerySymbolicLinkObject on \??\x:, where x is the drive letter that the path is using, and prepend the result. If it's a UNC path, prepend \Device\Mup. And so on for the other types of paths (if there are any).
I figured out the problem myself, with #wj32's help: I'd totally forgotten that the input to RtlDosPathNameToNtPathName_U needed to be null-terminated, and my code didn't handle that properly. Thanks for everyone's help!

Resources