Skip to content

Instantly share code, notes, and snippets.

@phr34k
Last active November 22, 2021 03:21
Show Gist options
  • Save phr34k/7539329 to your computer and use it in GitHub Desktop.
Save phr34k/7539329 to your computer and use it in GitHub Desktop.
Ssh connection with file-serving via lib-ssh and NFSv2. Can be used connect to linux-based target machine from windows, on the same network though, and execute file-served files. Example usage: -t 192.168.0.1 -u user -p 22 -cwd "myworkingdirectoy" -cmd "./window". Intended for serving and executing cross compiled binaries.
#include <libssh/libssh.h>
#include <stdlib.h>
#include <stdio.h>
#include <errno.h>
#include <string.h>
#include <string>
#include <windows.h>
#include <map>
#include <vector>
#include <assert.h>
#include <windows.h>
#include <stdio.h>
#pragma comment(lib, "ws2_32.lib");
//Command parameters
std::string arg_target = "192.168.0.1";
std::string arg_user = "user";
std::string arg_port = "";
std::string arg_cwd = ".";
std::string arg_cmd = "echo no command was given \n ./main";
//NFSv2 RPC Helper structures
enum RpcMountdProc
{
Null = 0,
Mount = 1,
Dump = 2,
UMount = 3,
UMountAll = 4,
Export = 5
};
enum RpcNfsv2Proc
{
GetAttribs = 1,
SetAttribs = 2,
Root = 3,
Lookup = 4,
ReadLink = 5,
Read = 6,
Write = 8,
Create = 9,
Remove = 10,
Rename = 11,
SymLink = 13,
MkDir = 14,
RmDir = 15,
ReadDir = 16,
StatFS = 17,
};
enum RpcNfsv2Status
{
NFS_OK = 0,
NFSERR_PERM = 1,
NFSERR_NOENT = 2,
NFSERR_IO = 5,
NFSERR_NXIO = 6,
NFSERR_ACCES = 13,
NFSERR_EXIST = 17,
NFSERR_NODEV = 19,
NFSERR_NOTDIR = 20,
NFSERR_ISDIR = 21,
NFSERR_FBIG = 27,
NFSERR_NOSPC = 28,
NFSERR_ROFS = 30,
NFSERR_NAMETOOLONG = 63,
NFSERR_NOTEMPTY = 66,
NFSERR_DQUOT = 69,
NFSERR_STALE = 70,
NFSERR_WFLUSG = 99
};
struct RpcFileHandle
{
unsigned int index;
RpcFileHandle(unsigned int handle)
{
index = handle;
}
bool operator<(const RpcFileHandle& r) const { return index < r.index; }
};
struct RpcFileInfo
{
std::string path;
RpcFileInfo() {}
RpcFileInfo(const std::string& Path)
{
path = Path;
}
RpcFileInfo(const RpcFileInfo& f )
{
path = f.path;
}
};
struct RpcFileTime
{
unsigned int sec;
unsigned int usec;
RpcFileTime() : sec(0), usec(0) {}
RpcFileTime(const FILETIME& f)
{
LARGE_INTEGER date, adjust;
date.LowPart = f.dwLowDateTime;
date.HighPart = f.dwHighDateTime;
adjust.QuadPart = 11644473600000 * 10000;
date.QuadPart -= adjust.QuadPart;
sec = (unsigned int)(date.QuadPart / 10000000);
usec = 0;
}
};
struct RpcFileAttributes
{
enum ftype
{
NFNON = 0,
NFREG = 1,
NFDIR = 2,
NFBLK = 3,
NFCHR = 4,
NFLNK = 5
};
enum modes
{
DIR = 16384,
CHR = 8192,
BLK = 24576,
REG = 32768,
LNK = 40960,
NON = 49152,
SUID = 2048,
SGID = 1024,
SWAP = 512,
ROWN = 256,
WOWN = 128,
XOWN = 64,
RGRP = 32,
WGRP = 16,
XGRP = 8,
ROTH = 4,
WOTH = 2,
XOTH = 1
};
ftype type;
unsigned int mode;
unsigned int nlink;
unsigned int uid;
unsigned int gid;
unsigned int size;
unsigned int blocksize;
unsigned int rdev;
unsigned int blocks;
unsigned int fsid;
unsigned int fileid;
RpcFileTime atime;
RpcFileTime mtime;
RpcFileAttributes()
{
type = NFNON;
mode = XOWN | XGRP | XOTH | ROWN | RGRP | ROTH;
nlink = 1;
uid = 0;
gid = 0;
size = 0;
blocksize = 0;
rdev = 0;
blocks = 0;
fsid = 1;
fileid = 0;
}
};
struct RpcDirectoryEntry
{
unsigned int fileid;
const char* filename;
unsigned int cookie;
RpcDirectoryEntry( const RpcFileHandle& handle, const char* filename,
unsigned int cookie)
{
this->fileid = handle.index;
this->filename = filename;
this->cookie = cookie;
}
};
class RpcReader
{
unsigned char* _data;
unsigned int _offset;
unsigned int _size;
public:
RpcReader(unsigned char* data, int size)
{
_data = data;
_offset = 0;
_size = size;
}
unsigned int read_uint32()
{
unsigned int v = 0;
v |= static_cast<unsigned int>(_data[_offset + 0]) << 24;
v |= static_cast<unsigned int>(_data[_offset + 1]) << 16;
v |= static_cast<unsigned int>(_data[_offset + 2]) << 8;
v |= static_cast<unsigned int>(_data[_offset + 3]) << 0;
_offset += 4;
return v;
}
RpcFileHandle read_rcphandle()
{
unsigned int index = read_uint32();
read_uint32();
read_uint32();
read_uint32();
read_uint32();
read_uint32();
read_uint32();
read_uint32();
RpcFileHandle d( index );
return d;
}
std::string read_string()
{
unsigned int length = read_uint32();
std::string dirPath = "";
for (unsigned int i = 0; i < length; ++i)
dirPath.push_back(read_char());
return dirPath;
}
char read_char()
{
char s = static_cast<char>( _data[_offset + 0] );
_offset += 1;
return s;
}
char* data()
{
return (char*)&_data[0];
}
int size()
{
return _size;
}
void skip( int size )
{
_offset += size;
}
};
class RpcWriter
{
std::vector<unsigned char> _data;
unsigned int _offset;
unsigned int _size;
public:
RpcWriter()
{
_data.reserve(2048 * 4);
_data.resize(2048 * 4);
_offset = 0;
_size = 0;
}
void write_uint32( unsigned int a )
{
_data.resize( _size + 4 );
_data[_offset + 0] = (unsigned char)( (a >> 24) & 0xFF);
_data[_offset + 1] = (unsigned char)( (a >> 16) & 0xFF);
_data[_offset + 2] = (unsigned char)( (a >> 8) & 0xFF);
_data[_offset + 3] = (unsigned char)( (a >> 0) & 0xFF);
_offset += 4;
_size += 4;
assert( (_offset % 4) == 0 );
}
void write_rcphandle( const RpcFileHandle& handle )
{
write_uint32(handle.index);
write_uint32(0);
write_uint32(0);
write_uint32(0);
write_uint32(0);
write_uint32(0);
write_uint32(0);
write_uint32(0);
}
void write_rcptime( const RpcFileTime& time )
{
write_uint32(time.sec);
write_uint32(time.usec);
}
void write_rcpattributes( const RpcFileAttributes& attr )
{
write_uint32(attr.type);
write_uint32(attr.mode);
write_uint32(attr.nlink);
write_uint32(attr.uid);
write_uint32(attr.gid);
write_uint32(attr.size);
write_uint32(attr.blocksize);
write_uint32(attr.rdev);
write_uint32(attr.blocks);
write_uint32(attr.fsid);
write_uint32(attr.fileid);
write_rcptime(attr.atime);
write_rcptime(attr.mtime);
write_rcptime(attr.mtime);
}
void write_entry( const RpcDirectoryEntry& e )
{
write_uint32( e.fileid );
write_string( e.filename );
write_uint32( e.cookie );
}
void write_string(const char* s )
{
int length = strlen(s);
_data.resize( _size + (4 + length + 3) );
//resize( _size);
int offset = _offset;
_offset += 4;
_size += 4;
const char* c = s;
while( *c != 0 )
{
_data[_offset++] = *c;
_size++;
c = c + 1;
}
if( (length % 4) != 0 )
{
for (int pad = 4 - (length % 4); pad != 0; --pad)
{
_data[_offset++] = 0;
_size++;
}
}
_data[offset + 0] = (unsigned char)( (length >> 24) & 0xFF);
_data[offset + 1] = (unsigned char)( (length >> 16) & 0xFF);
_data[offset + 2] = (unsigned char)( (length >> 8) & 0xFF);
_data[offset + 3] = (unsigned char)( (length >> 0) & 0xFF);
assert( (_offset % 4) == 0 );
}
unsigned char* write_unmanaged(unsigned int size)
{
_data.resize( _size + 4 + 3);
_data[_offset + 0] = (unsigned char)( (size >> 24) & 0xFF);
_data[_offset + 1] = (unsigned char)( (size >> 16) & 0xFF);
_data[_offset + 2] = (unsigned char)( (size >> 8) & 0xFF);
_data[_offset + 3] = (unsigned char)( (size >> 0) & 0xFF);
_offset += 4; _size += 4;
_data.resize( _size + size + 3 );
unsigned char* d = &_data[_offset];
_size = _size + size;
_offset = _offset + size;
if( (size % 4) != 0 )
{
for (int pad = 4 - (size % 4); pad != 0; --pad)
{
_data[_offset++] = 0;
_size++;
}
}
assert( (_offset % 4) == 0 );
return d;
}
char* data()
{
return (char*)&_data.front();
}
int size()
{
return _size;
}
void reset(int size)
{
_size = size;
_offset = size;
}
};
struct RpcCredentialsSkip
{
RpcCredentialsSkip(RpcReader& rdr)
{
unsigned flavor = rdr.read_uint32();
unsigned length = rdr.read_uint32();
rdr.skip(length);
}
};
struct RpcVerificationSkip
{
RpcVerificationSkip(RpcReader& rdr)
{
unsigned flavor = rdr.read_uint32();
unsigned length = rdr.read_uint32();
rdr.skip(length);
}
};
struct RpcAccept
{
RpcAccept( RpcWriter& w, unsigned int xid, unsigned int acceptStatus)
{
w.write_uint32(xid);
w.write_uint32(1);
w.write_uint32(0);
w.write_uint32(0);
w.write_uint32(0);
w.write_uint32(acceptStatus);
}
};
struct RpcMismatch
{
RpcMismatch( RpcWriter& w, unsigned int xid)
{
w.write_uint32(xid);
w.write_uint32(1);
w.write_uint32(1);
w.write_uint32(0);
w.write_uint32(2);
w.write_uint32(2);
}
};
//Global state
std::map<RpcFileHandle, RpcFileInfo> m_ReferenceTable;
unsigned int m_ReferenceKey = 2;
bool m_IsRunning = true;
HANDLE m_Event = 0;
//Working reverse tunnel example, make portmap compatible with ssh reverse tunnel.
int web_server(ssh_session session)
{
int rc;
ssh_channel channel;
char buffer[256];
int nbytes, nwritten;
char *helloworld = ""
"HTTP/1.1 200 OK\n"
"Content-Type: text/html\n"
"Content-Length: 113\n"
"\n"
"<html>\n"
" <head>\n"
" <title>Hello, World!</title>\n"
" </head>\n"
" <body>\n"
" <h1>Hello, World!</h1>\n"
" </body>\n"
"</html>\n";
rc = ssh_forward_listen(session, NULL, 8080, NULL);
if (rc != SSH_OK)
{
fprintf(stderr, "Error opening remote port: %s\n",
ssh_get_error(session));
return rc;
}
channel = ssh_forward_accept(session, 60000);
if (channel == NULL)
{
fprintf(stderr, "Error waiting for incoming connection: %s\n",
ssh_get_error(session));
return SSH_ERROR;
}
while (1)
{
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
if (nbytes < 0)
{
fprintf(stderr, "Error reading incoming data: %s\n",
ssh_get_error(session));
ssh_channel_send_eof(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
if (strncmp(buffer, "GET /", 5)) continue;
nbytes = strlen(helloworld);
nwritten = ssh_channel_write(channel, helloworld, nbytes);
if (nwritten != nbytes)
{
fprintf(stderr, "Error sending answer: %s\n",
ssh_get_error(session));
ssh_channel_send_eof(channel);
ssh_channel_free(channel);
return SSH_ERROR;
}
ssh_blocking_flush(session, -1);
printf("Sent answer\n");
break;
}
ssh_channel_send_eof(channel);
ssh_channel_free(channel);
return SSH_OK;
}
//Ssh utillity function to verify the host.
int verify_knownhost(ssh_session session)
{
int state, hlen;
unsigned char *hash = NULL;
char *hexa;
char buf[10];
state = ssh_is_server_known(session);
hlen = ssh_get_pubkey_hash(session, &hash);
if (hlen < 0)
return -1;
switch (state)
{
case SSH_SERVER_KNOWN_OK:
break; /* ok */
case SSH_SERVER_KNOWN_CHANGED:
fprintf(stderr, "Host key for server changed: it is now:\n");
ssh_print_hexa("Public key hash", hash, hlen);
fprintf(stderr, "For security reasons, connection will be stopped\n");
free(hash);
return -1;
case SSH_SERVER_FOUND_OTHER:
fprintf(stderr, "The host key for this server was not found but an other"
"type of key exists.\n");
fprintf(stderr, "An attacker might change the default server key to"
"confuse your client into thinking the key does not exist\n");
free(hash);
return -1;
case SSH_SERVER_FILE_NOT_FOUND:
fprintf(stderr, "Could not find known host file.\n");
fprintf(stderr, "If you accept the host key here, the file will be"
"automatically created.\n");
/* fallback to SSH_SERVER_NOT_KNOWN behavior */
case SSH_SERVER_NOT_KNOWN:
hexa = ssh_get_hexa(hash, hlen);
fprintf(stderr,"The server is unknown. Do you trust the host key?\n");
fprintf(stderr, "Public key hash: %s\n", hexa);
ssh_string_free_char(hexa);
if (fgets(buf, sizeof(buf), stdin) == NULL)
{
ssh_string_free_char((char*)hash);
return -1;
}
if (strcmpi(buf, "yes\n") != 0)
{
ssh_string_free_char((char*)hash);
return -1;
}
if (ssh_write_knownhost(session) < 0)
{
fprintf(stderr, "Error %s\n", strerror(errno));
ssh_string_free_char((char*)hash);
return -1;
}
break;
case SSH_SERVER_ERROR:
fprintf(stderr, "Error %s", ssh_get_error(session));
ssh_string_free_char((char*)hash);
return -1;
}
ssh_string_free_char((char*)hash);
return 0;
}
//Ssh execute command statement, kill processes created by the previous process id, these are assumed
//to be working on from the NFS filesystem, and prevent unmounting the filesystem for a replacement. Remount
//the NFS directory (~/Desktop/home) to the connecting client (using remote ip of the ssh client).
int show_remote_dir(ssh_session session, ssh_channel channel)
{
char buffer[256];
unsigned int nbytes;
int rc;
std::string cmd;
cmd.append("pkill -TERM -P $(cat ~/.pid) \n kill -9 $(cat ~/.pid) \n echo $$ > ~/.pid \n DISPLAY=:0 \n export DISPLAY \n echo password | sudo -S umount -f ~/Desktop/home \n export DISPLAY \n echo password | sudo -S mount -t nfs -o vers=2 $(echo $SSH_CONNECTION | grep -oP \"^[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\\.[0-9]{1,3}\"): ~/Desktop/home \n cd Desktop/home \n");
cmd.append( arg_cmd );
cmd.append( "\n cd / \n echo password | sudo -S umount -f ~/Desktop/home " );
rc = ssh_channel_request_exec(channel, cmd.c_str());
if (rc != SSH_OK)
{
return rc;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
while (nbytes > 0)
{
if (fwrite(buffer, 1, nbytes, stdout) != nbytes)
{
return SSH_ERROR;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 0);
}
if (nbytes < 0)
{
return SSH_ERROR;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 1);
while (nbytes > 0)
{
if (fwrite(buffer, 1, nbytes, stdout) != nbytes)
{
return SSH_ERROR;
}
nbytes = ssh_channel_read(channel, buffer, sizeof(buffer), 1);
}
if (nbytes < 0)
{
return SSH_ERROR;
}
}
//Ssh utillity function to start a channel for show_remote_dir.
int show_remote_processes(ssh_session session)
{
ssh_channel channel;
int rc;
channel = ssh_channel_new(session);
if (channel == NULL)
return SSH_ERROR;
rc = ssh_channel_open_session(channel);
if (rc != SSH_OK)
{
ssh_channel_free(channel);
return rc;
}
//show_remote_processs_channel(session, channel);
rc = show_remote_dir(session, channel);
if (rc == SSH_OK)
{
/*
rc = show_test(session, channel);
if (rc == SSH_OK)
{
}
*/
}
ssh_channel_close(channel);
ssh_channel_free(channel);
return SSH_OK;
}
//Portmap thread, we should probably setup a reverse tunnel so it's only exposed the target, rather than
//being globally available for every application, however this works. And ideally we should also setup
//udp hole punching, so the target machine can reach the host machine. Currently it's presumed they
//reside on the same network.
DWORD WINAPI portmap_thread( LPVOID lpParam )
{
int sockfd,n;
struct sockaddr_in servaddr,cliaddr;
int len;
char mesg[1000];
sockfd=socket(AF_INET,SOCK_DGRAM,0);
memset(&servaddr,0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(111);
bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
for (;m_IsRunning;)
{
const int progId = 100000;
len = sizeof(cliaddr);
n = recvfrom(sockfd,mesg,1000,0,(struct sockaddr *)&cliaddr,&len);
RpcReader rdr((unsigned char*)mesg, n);
unsigned int xid = rdr.read_uint32();
unsigned int msg_type = rdr.read_uint32();
unsigned int rpcvers = rdr.read_uint32();
unsigned int prog = rdr.read_uint32();
unsigned int vers = rdr.read_uint32();
unsigned int proc = rdr.read_uint32();
//printf("xid %08X msg_type %08X rpcvers %08X\r\n", xid, msg_type, rpcvers);
//printf("prog %08X vers %08X proc %08X\r\n", prog, vers, proc);
if( msg_type != 0 )
{
RpcWriter reply;
RpcAccept type(reply, xid, 4);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( rpcvers != 2 )
{
RpcWriter reply;
RpcMismatch type(reply, xid);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( prog != progId )
{
RpcWriter reply;
RpcAccept type(reply, xid, 2);
reply.write_uint32(100000);
reply.write_uint32(100000);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else
{
RpcCredentialsSkip cred(rdr);
RpcVerificationSkip verif(rdr);
if( proc == 3 )
{
RpcWriter reply;
RpcAccept type(reply, xid, 0);
unsigned int portmap_prog = rdr.read_uint32();
unsigned int portmap_vers = rdr.read_uint32();
unsigned int portmap_prot = rdr.read_uint32();
unsigned int portmap_port = rdr.read_uint32();
/*
printf("prog:%08X, vers:%08X prot:%08X, port:%08X\r\n",
portmap_prog, portmap_vers,
portmap_prot, portmap_port);
*/
unsigned int registeredPort = 0;
if( portmap_prot == 17 )
{
//mountd
if (portmap_prog == 100005 && portmap_vers == 1)
{
registeredPort = 635;
}
//ntfsd
else if (portmap_prog == 100003 && portmap_vers == 2)
{
registeredPort = 2049;
}
}
reply.write_uint32(registeredPort);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else
{
//Reply with proc unavailable
RpcWriter reply;
RpcAccept type(reply, xid, 3);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
}
}
return 0;
}
//NFSv2 - nfsd UDP used to setup mounted access points and read data from the host machine. Currently we
//don't garbage collect, we presume this utillity is used for short lived sessions.
DWORD WINAPI nfs_thread( LPVOID lpParam )
{
int sockfd,n;
struct sockaddr_in servaddr,cliaddr;
int len;
char mesg[1000];
sockfd=socket(AF_INET,SOCK_DGRAM,0);
memset(&servaddr,0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(2049);
bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
for (;m_IsRunning;)
{
const int progId = 100003;
len = sizeof(cliaddr);
SetEvent(m_Event);
n = recvfrom(sockfd,mesg,1000,0,(struct sockaddr *)&cliaddr,&len);
if( m_IsRunning == false )
continue;
ResetEvent(m_Event);
RpcReader rdr((unsigned char*)mesg, n);
unsigned int xid = rdr.read_uint32();
unsigned int msg_type = rdr.read_uint32();
unsigned int rpcvers = rdr.read_uint32();
unsigned int prog = rdr.read_uint32();
unsigned int vers = rdr.read_uint32();
unsigned int proc = rdr.read_uint32();
//printf("xid %08X msg_type %08X rpcvers %08X\r\n", xid, msg_type, rpcvers);
//printf("prog %08X vers %08X proc %08X\r\n", prog, vers, proc);
if( msg_type != 0 )
{
RpcWriter reply;
RpcAccept type(reply, xid, 4);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( rpcvers != 2 )
{
RpcWriter reply;
RpcMismatch type(reply, xid);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( prog != progId )
{
RpcWriter reply;
RpcAccept type(reply, xid, 2);
reply.write_uint32(progId);
reply.write_uint32(progId);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else
{
RpcCredentialsSkip cred(rdr);
RpcVerificationSkip verif(rdr);
if( proc == RpcMountdProc::Null )
{
RpcWriter reply;
RpcAccept type(reply, xid, 0);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( proc == RpcNfsv2Proc::GetAttribs )
{
RpcFileHandle fhandle = rdr.read_rcphandle();
std::map<RpcFileHandle, RpcFileInfo>::iterator itt = m_ReferenceTable.find(fhandle);
if( itt == m_ReferenceTable.end() )
{
printf("GetAttribs: Illegal entry\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFSERR_STALE);
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
}
else
{
WIN32_FILE_ATTRIBUTE_DATA attributes;
BOOL succeeded = GetFileAttributesExA( itt->second.path.c_str(), GetFileExInfoStandard, &attributes);
ULARGE_INTEGER fileSize;
fileSize.LowPart = attributes.nFileSizeLow;
fileSize.HighPart = attributes.nFileSizeHigh;
if( succeeded == false || attributes.dwFileAttributes == INVALID_FILE_ATTRIBUTES )
{
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFSERR_NOENT);
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
}
else
{
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFS_OK);
if( (attributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY )
{
RpcFileAttributes attribs;
attribs.type = RpcFileAttributes::NFDIR;
attribs.mode |= RpcFileAttributes::DIR;
attribs.size = 4096;
attribs.blocksize = 4096;
attribs.blocks = 8;
attribs.atime = RpcFileTime(attributes.ftLastAccessTime);
attribs.mtime = RpcFileTime(attributes.ftLastWriteTime);
attribs.fileid = fhandle.index;
reply.write_rcpattributes(attribs);
}
//TODO: symbolic links
else
{
RpcFileAttributes attribs;
attribs.type = RpcFileAttributes::NFREG;
attribs.mode |= RpcFileAttributes::REG;
attribs.size = (unsigned int)fileSize.QuadPart;
attribs.blocksize = 4096;
attribs.blocks = (fileSize.QuadPart / 4096) + (4096 - (fileSize.QuadPart % 4096));
attribs.atime = RpcFileTime(attributes.ftLastAccessTime);
attribs.mtime = RpcFileTime(attributes.ftLastWriteTime);
attribs.fileid = fhandle.index;
reply.write_rcpattributes(attribs);
}
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
}
}
}
else if( proc == RpcNfsv2Proc::SetAttribs )
{
printf("SetAttribs\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( proc == RpcNfsv2Proc::Root )
{
printf("Root\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( proc == RpcNfsv2Proc::Lookup )
{
RpcFileHandle fhandle = rdr.read_rcphandle();
std::string entry = rdr.read_string();
std::map<RpcFileHandle, RpcFileInfo>::iterator itt = m_ReferenceTable.find(fhandle);
if( itt == m_ReferenceTable.end() )
{
printf("Lookup: Illegal entry\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFSERR_NOENT);
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
}
else
{
std::string v = itt->second.path;
v.append( "\\" );
v.append( entry.c_str() );
/*
RpcFileHandle handle(1);
RpcFileInfo info(dirPath);
reply.write_uint32(0);
reply.write_rcphandle(handle);
*/
bool found = false;
std::map<RpcFileHandle, RpcFileInfo>::iterator itt = m_ReferenceTable.begin();
for( ; itt != m_ReferenceTable.end(); ++itt )
{
if( itt->second.path == v )
{
found = true;
break;
}
}
if( found )
{
WIN32_FILE_ATTRIBUTE_DATA attributes;
BOOL succeeded = GetFileAttributesExA( itt->second.path.c_str(), GetFileExInfoStandard, &attributes);
ULARGE_INTEGER fileSize;
fileSize.LowPart = attributes.nFileSizeLow;
fileSize.HighPart = attributes.nFileSizeHigh;
if( succeeded == false || attributes.dwFileAttributes == INVALID_FILE_ATTRIBUTES )
{
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFSERR_NOENT);
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
}
else
{
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFS_OK);
if( (attributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY )
{
RpcFileAttributes attribs;
attribs.type = RpcFileAttributes::NFDIR;
attribs.mode |= RpcFileAttributes::DIR;
attribs.size = 4096;
attribs.blocksize = 4096;
attribs.blocks = 8;
attribs.atime = RpcFileTime(attributes.ftLastAccessTime);
attribs.mtime = RpcFileTime(attributes.ftLastWriteTime);
attribs.fileid = itt->first.index;
reply.write_rcphandle( itt->first );
reply.write_rcpattributes(attribs);
}
//TODO: symbolic links
else
{
RpcFileAttributes attribs;
attribs.type = RpcFileAttributes::NFREG;
attribs.mode |= RpcFileAttributes::REG;
attribs.size = (unsigned int)fileSize.QuadPart;
attribs.blocksize = 4096;
attribs.blocks = (fileSize.QuadPart / 4096) + (4096 - (fileSize.QuadPart % 4096));
attribs.atime = RpcFileTime(attributes.ftLastAccessTime);
attribs.mtime = RpcFileTime(attributes.ftLastWriteTime);
attribs.fileid = itt->first.index;
reply.write_rcphandle( itt->first );
reply.write_rcpattributes(attribs);
}
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
}
}
else
{
for( int i =0; i < v.size(); ++i )
if( v[i] == '/' )
v[i] = '\\';
WIN32_FILE_ATTRIBUTE_DATA attributes;
BOOL succeeded = GetFileAttributesExA( v.c_str(), GetFileExInfoStandard, &attributes);
ULARGE_INTEGER fileSize;
fileSize.LowPart = attributes.nFileSizeLow;
fileSize.HighPart = attributes.nFileSizeHigh;
if( succeeded == false || attributes.dwFileAttributes == INVALID_FILE_ATTRIBUTES )
{
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFSERR_NOENT);
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
}
else
{
unsigned int newId = m_ReferenceKey++;
RpcFileHandle handle = RpcFileHandle(newId);
m_ReferenceTable[handle] = RpcFileInfo(v.c_str());
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFS_OK);
if( (attributes.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) == FILE_ATTRIBUTE_DIRECTORY )
{
RpcFileAttributes attribs;
attribs.type = RpcFileAttributes::NFDIR;
attribs.mode |= RpcFileAttributes::DIR;
attribs.size = 4096;
attribs.blocksize = 4096;
attribs.blocks = 8;
attribs.atime = RpcFileTime(attributes.ftLastAccessTime);
attribs.mtime = RpcFileTime(attributes.ftLastWriteTime);
attribs.fileid = handle.index;
reply.write_rcphandle( handle );
reply.write_rcpattributes(attribs);
}
//TODO: symbolic links
else
{
RpcFileAttributes attribs;
attribs.type = RpcFileAttributes::NFREG;
attribs.mode |= RpcFileAttributes::REG;
attribs.size = (unsigned int)fileSize.QuadPart;
attribs.blocksize = 4096;
attribs.blocks = (fileSize.QuadPart / 4096) + (4096 - (fileSize.QuadPart % 4096));
attribs.atime = RpcFileTime(attributes.ftLastAccessTime);
attribs.mtime = RpcFileTime(attributes.ftLastWriteTime);
attribs.fileid = handle.index;
reply.write_rcphandle( handle );
reply.write_rcpattributes(attribs);
}
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
}
}
}
}
else if( proc == RpcNfsv2Proc::ReadLink )
{
printf("ReadLink\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( proc == RpcNfsv2Proc::Read )
{
RpcFileHandle fhandle = rdr.read_rcphandle();
unsigned int offset = rdr.read_uint32();
unsigned int count = rdr.read_uint32();
unsigned int totalcount = rdr.read_uint32();
std::map<RpcFileHandle, RpcFileInfo>::iterator itt = m_ReferenceTable.find(fhandle);
if( itt == m_ReferenceTable.end() )
{
printf("Read: Illegal entry\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFSERR_NOENT);
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
}
else
{
char buffer[4096]; DWORD bytesRead;
HANDLE hFile = CreateFileA(itt->second.path.c_str(), GENERIC_READ, 0, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
if( hFile == INVALID_HANDLE_VALUE )
{
printf("Read: failed to retieve disk-space\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFSERR_IO);
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
}
else
{
BY_HANDLE_FILE_INFORMATION info;
if( GetFileInformationByHandle(hFile, &info ) == false )
{
printf("Read: failed to information\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFSERR_IO);
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
CloseHandle(hFile);
}
else
{
ULARGE_INTEGER fileSize;
fileSize.HighPart = info.nFileSizeHigh;
fileSize.LowPart = info.nFileSizeLow;
RpcFileAttributes attribs;
attribs.type = RpcFileAttributes::NFREG;
attribs.mode |= RpcFileAttributes::REG;
attribs.size = (unsigned int)fileSize.QuadPart;
attribs.blocksize = 4096;
attribs.blocks = (fileSize.QuadPart / 4096) + (4096 - (fileSize.QuadPart % 4096));
attribs.atime = RpcFileTime(info.ftLastAccessTime);
attribs.mtime = RpcFileTime(info.ftLastWriteTime);
attribs.fileid = fhandle.index;
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFS_OK);
reply.write_rcpattributes(attribs);
unsigned char* d = reply.write_unmanaged(count);
SetFilePointer(hFile, offset, 0, FILE_BEGIN );
ReadFile(hFile, d, count, &bytesRead, 0 );
CloseHandle(hFile);
if( bytesRead == count )
{
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
}
else
{
printf("Read: failed to retieve disk-space\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFSERR_IO);
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
}
}
}
}
}
else if( proc == RpcNfsv2Proc::Write )
{
printf("Write\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( proc == RpcNfsv2Proc::Create )
{
printf("Create\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( proc == RpcNfsv2Proc::Remove )
{
printf("Remove\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( proc == RpcNfsv2Proc::Rename )
{
printf("Rename\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( proc == RpcNfsv2Proc::SymLink )
{
printf("SymLink\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( proc == RpcNfsv2Proc::MkDir )
{
printf("MkDir\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( proc == RpcNfsv2Proc::RmDir )
{
printf("RmDir\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( proc == RpcNfsv2Proc::ReadDir )
{
RpcFileHandle fhandle = rdr.read_rcphandle();
unsigned int cookie = rdr.read_uint32();
unsigned int count = rdr.read_uint32();
std::map<RpcFileHandle, RpcFileInfo>::iterator itt = m_ReferenceTable.find(fhandle);
if( itt == m_ReferenceTable.end() )
{
printf("ReadDir: Illegal entry\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFSERR_NOENT);
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
}
else
{
std::string v = itt->second.path;
v.append("\\*");
WIN32_FIND_DATAA ffd;
HANDLE hFind = INVALID_HANDLE_VALUE;
hFind = FindFirstFileA(v.c_str(), &ffd);
if (hFind == INVALID_HANDLE_VALUE)
{
DWORD v = ::GetFileAttributesA( itt->second.path.c_str() );
if( v == INVALID_FILE_ATTRIBUTES )
{
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFSERR_STALE);
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
continue;
}
else if( (v & FILE_ATTRIBUTE_DIRECTORY) != FILE_ATTRIBUTE_DIRECTORY)
{
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFSERR_NOTDIR);
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
continue;
}
else
{
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFSERR_ACCES);
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
continue;
}
}
else
{
std::string realPath;
realPath.reserve(2048);
std::vector<RpcFileInfo*> entries;
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFS_OK);
bool wasReset = false;
int file_count = 0;
int numberOfBytes = reply.size();
do
{
if( file_count >= cookie && file_count < (cookie + count) )
{
realPath = itt->second.path;
realPath.append("\\");
realPath.append(ffd.cFileName);
RpcFileHandle handle(0);
bool requiredNewEntry = true;
std::map<RpcFileHandle, RpcFileInfo>::iterator itt = m_ReferenceTable.begin();
for( ; itt != m_ReferenceTable.end(); ++itt )
{
if( itt->second.path == realPath )
{
handle = itt->first;
entries.push_back( & ((RpcFileInfo)itt->second));
requiredNewEntry = false;
break;
}
}
if( requiredNewEntry == true )
{
unsigned int newId = m_ReferenceKey++;
handle = RpcFileHandle(newId);
m_ReferenceTable[handle] = RpcFileInfo(
realPath);
}
reply.write_uint32(1);
//reply.write_rcphandle(handle);
int reset = reply.size();
RpcDirectoryEntry e(handle, ffd.cFileName,
file_count );
reply.write_entry( e);
if( reply.size() > count )
{
wasReset = true;
reply.reset( reset);
break;
}
}
file_count = file_count + 1;
}
while (FindNextFileA(hFind, &ffd) != 0);
reply.write_uint32(0);
DWORD dwError = GetLastError();
if (dwError == ERROR_NO_MORE_FILES && wasReset == false)
{
reply.write_uint32(1);
}
else
{
reply.write_uint32(0);
}
FindClose(hFind);
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
}
}
}
else if( proc == RpcNfsv2Proc::StatFS )
{
RpcFileHandle fhandle = rdr.read_rcphandle();
std::map<RpcFileHandle, RpcFileInfo>::iterator itt = m_ReferenceTable.find(fhandle);
if( itt == m_ReferenceTable.end() )
{
printf("StatFS: Illegal entry\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFSERR_NOENT);
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
}
else
{
const unsigned int BLOCK_SIZE = 4096;
ULARGE_INTEGER FreeBytesAvailableToCaller, TotalNumberOfBytes, TotalNumberOfFreeBytes;
if( GetDiskFreeSpaceExA(itt->second.path.c_str(), &FreeBytesAvailableToCaller,
&TotalNumberOfBytes, &TotalNumberOfFreeBytes ) == false )
{
printf("StatFS: failed to retieve disk-space\r\n");
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFSERR_NOENT);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else
{
FreeBytesAvailableToCaller.QuadPart /= BLOCK_SIZE;
TotalNumberOfBytes.QuadPart /= BLOCK_SIZE;
TotalNumberOfFreeBytes.QuadPart /= BLOCK_SIZE;
RpcWriter reply;
RpcAccept type(reply, xid, 0);
reply.write_uint32(RpcNfsv2Status::NFS_OK);
reply.write_uint32(BLOCK_SIZE); // tsize: optimum transfer size
reply.write_uint32(BLOCK_SIZE); // Block size of FS
reply.write_uint32(TotalNumberOfBytes.QuadPart); // Total # of blocks (of the above size)
reply.write_uint32(TotalNumberOfFreeBytes.QuadPart); // Free blocks
reply.write_uint32(FreeBytesAvailableToCaller.QuadPart); // Free blocks available to non-priv. users
int bytesSent = sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
if( bytesSent != reply.size() ) {
printf("error sending data %d %d\r\n", bytesSent, reply.size());
}
}
}
}
else
{
//Reply with proc unavailable
RpcWriter reply;
RpcAccept type(reply, xid, 3);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
}
}
return 0;
}
//NFSv2 - mountd UDP used to resolved the mount access point.
DWORD WINAPI mountd_thread( LPVOID lpParam )
{
int sockfd,n;
struct sockaddr_in servaddr,cliaddr;
int len;
char mesg[1000];
sockfd=socket(AF_INET,SOCK_DGRAM,0);
memset(&servaddr,0, sizeof(servaddr));
servaddr.sin_family = AF_INET;
servaddr.sin_addr.s_addr=htonl(INADDR_ANY);
servaddr.sin_port=htons(635);
bind(sockfd,(struct sockaddr *)&servaddr,sizeof(servaddr));
for (;m_IsRunning;)
{
const int progId = 100005;
len = sizeof(cliaddr);
n = recvfrom(sockfd,mesg,1000,0,(struct sockaddr *)&cliaddr,&len);
RpcReader rdr((unsigned char*)mesg, n);
unsigned int xid = rdr.read_uint32();
unsigned int msg_type = rdr.read_uint32();
unsigned int rpcvers = rdr.read_uint32();
unsigned int prog = rdr.read_uint32();
unsigned int vers = rdr.read_uint32();
unsigned int proc = rdr.read_uint32();
//printf("xid %08X msg_type %08X rpcvers %08X\r\n", xid, msg_type, rpcvers);
//printf("prog %08X vers %08X proc %08X\r\n", prog, vers, proc);
if( msg_type != 0 )
{
RpcWriter reply;
RpcAccept type(reply, xid, 4);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( rpcvers != 2 )
{
RpcWriter reply;
RpcMismatch type(reply, xid);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( prog != progId )
{
RpcWriter reply;
RpcAccept type(reply, xid, 2);
reply.write_uint32(progId);
reply.write_uint32(progId);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else
{
RpcCredentialsSkip cred(rdr);
RpcVerificationSkip verif(rdr);
if( proc == RpcMountdProc::Null )
{
//Reply with proc unavailable
RpcWriter reply;
RpcAccept type(reply, xid, 0);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( proc == RpcMountdProc::Mount )
{
unsigned int length = rdr.read_uint32();
std::string dirPath = "";
for (unsigned int i = 0; i < length; ++i)
{
char s = rdr.read_char();
if( s == '/' ) s = '\\';
dirPath.push_back(s);
}
if( dirPath.size() >= 2 && dirPath[1] == ':' )
{
}
else
{
std::string t;
dirPath.swap(t);
dirPath = arg_cwd;
dirPath.append(t);
}
RpcWriter reply;
RpcAccept type(reply, xid, 0);
DWORD dwAttrib = GetFileAttributesA(dirPath.c_str());
if( dwAttrib == INVALID_FILE_ATTRIBUTES )
{
reply.write_uint32(2);
reply.write_uint32(0);
}
else
{
RpcFileHandle handle(1);
RpcFileInfo info(dirPath);
m_ReferenceTable[handle] = info;
reply.write_uint32(0);
reply.write_rcphandle(handle);
}
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( proc == RpcMountdProc::Dump )
{
printf("Dump\r\n");
//Reply with proc unavailable
RpcWriter reply;
RpcAccept type(reply, xid, 3);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( proc == RpcMountdProc::UMount )
{
unsigned int length = rdr.read_uint32();
std::string dirPath = "";
for (unsigned int i = 0; i < length; ++i)
dirPath.push_back(rdr.read_char());
printf("Unmount %d:%s\r\n", length, dirPath.c_str());
//Reply with proc unavailable
RpcWriter reply;
RpcAccept type(reply, xid, 3);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else if( proc == RpcMountdProc::UMountAll )
{
printf("UMountAll\r\n");
//Reply with proc unavailable
RpcWriter reply;
RpcAccept type(reply, xid, 3);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
else
{
//Reply with proc unavailable
RpcWriter reply;
RpcAccept type(reply, xid, 3);
sendto(sockfd,reply.data(),reply.size(),0,
(struct sockaddr *)&cliaddr,sizeof(cliaddr));
}
}
}
return 0;
}
int main()
{
for( int i = 0; i < __argc; ++i )
{
if( stricmp( __argv[i], "-t") == 0 )
{
if( i + 1 < __argc )
{
arg_target = __argv[i + 1];
i += 1;
}
else
{
printf("missing argument");
}
}
else if( stricmp( __argv[i], "-u") == 0 )
{
if( i + 1 < __argc )
{
arg_user = __argv[i + 1];
i += 1;
}
else
{
printf("missing argument");
}
}
else if( stricmp( __argv[i], "-p") == 0 )
{
if( i + 1 < __argc )
{
arg_port = __argv[i + 1];
i += 1;
}
else
{
printf("missing argument");
}
}
else if( stricmp( __argv[i], "-cwd") == 0 )
{
if( i + 1 < __argc )
{
arg_cwd = __argv[i + 1];
i += 1;
}
else
{
printf("missing argument");
}
}
else if( stricmp( __argv[i], "-cmd") == 0 )
{
if( i + 1 < __argc )
{
arg_cmd = __argv[i + 1];
i += 1;
}
else
{
printf("missing argument");
}
}
}
ssh_session my_ssh_session;
int rc;
my_ssh_session = ssh_new();
if (my_ssh_session == NULL)
exit(-1);
rc = ssh_options_set(my_ssh_session, SSH_OPTIONS_HOST, arg_target.c_str());
if (rc != SSH_OK)
{
fprintf(stderr, "Error setting option host: %s\n",
ssh_get_error(my_ssh_session));
exit(-1);
}
rc = ssh_options_set(my_ssh_session, SSH_OPTIONS_USER, arg_user.c_str());
if (rc != SSH_OK)
{
fprintf(stderr, "Error setting option user: %s\n",
ssh_get_error(my_ssh_session));
exit(-1);
}
if( arg_port.empty() == false )
{
rc = ssh_options_set(my_ssh_session, SSH_OPTIONS_PORT, arg_port.c_str());
if (rc != SSH_OK)
{
fprintf(stderr, "Error setting option port: %s\n",
ssh_get_error(my_ssh_session));
exit(-1);
}
}
if( arg_port.empty() == true )
printf("Connecting to %s as user %s\r\n", arg_target.c_str(), arg_user.c_str() );
else
printf("Connecting to %s:%s as user %s\r\n", arg_target.c_str(), arg_port.c_str(), arg_user.c_str() );
rc = ssh_connect(my_ssh_session);
if (rc != SSH_OK)
{
fprintf(stderr, "Error connecting to localhost: %s\n",
ssh_get_error(my_ssh_session));
exit(-1);
}
printf("Connected to target\r\n");
if (verify_knownhost(my_ssh_session) < 0)
{
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
exit(-1);
}
char path[2048];
GetModuleFileNameA(0, path, 2048);
char* ds = strrchr(path, '\\') + 1;
int type;
strcpy(ds, "min.pub" ); ssh_string publickey = publickey_from_file(my_ssh_session, path, &type);
strcpy(ds, "min" ); ssh_private_key privatkey = privatekey_from_file(my_ssh_session,path, type,"");
rc = ssh_userauth_pubkey(my_ssh_session, NULL, publickey, privatkey );
if (rc != SSH_OK)
{
fprintf(stderr, "Authentication failed: %s\n",
ssh_get_error(my_ssh_session));
}
//Prepare the NFS service before starting the script
DWORD threadId;
m_Event = CreateEvent(0, true, false, 0 );
HANDLE webserver = CreateThread(0,0, &portmap_thread, 0, 0, &threadId);
HANDLE nfsserver = CreateThread(0,0, &nfs_thread, 0, 0, &threadId);
HANDLE mountdserver = CreateThread(0,0, &mountd_thread, 0, 0, &threadId);
//Execute the script
show_remote_processes(my_ssh_session);
//Close client (fire & forget style)
ssh_disconnect(my_ssh_session);
ssh_free(my_ssh_session);
Sleep(100);
//Wait for all server threads to close down.
m_IsRunning = false;
//WaitForSingleObject(webserver, INFINITE);
//WaitForSingleObject(mountdserver, INFINITE);
WaitForSingleObject(m_Event, INFINITE);
TerminateThread(webserver, 0 );
TerminateThread(nfsserver, 0 );
TerminateThread(mountdserver, 0 );
CloseHandle(webserver);
CloseHandle(nfsserver);
CloseHandle(mountdserver);
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment