1
1

Merge branch 'master' of git://git.libssh.org/projects/libssh/libssh

Conflicts:
	include/libssh/priv.h
Этот коммит содержится в:
Aris Adamantiadis 2009-08-23 16:41:29 +02:00
родитель 8bae43876f fbfea94559
Коммит d4bc6fa954
15 изменённых файлов: 523 добавлений и 1095 удалений

Просмотреть файл

@ -23,6 +23,19 @@ endif(CMAKE_COMPILER_IS_GNUC)
# HEADER FILES
check_include_file(pty.h HAVE_PTY_H)
check_include_file(terminos.h HAVE_TERMIOS_H)
if (WIN32)
check_include_file(wspiapi.h HAVE_WSPIAPI_H)
if (NOT HAVE_WSPIAPI_H)
message(STATUS "WARNING: Without wspiapi.h, this build will only work on Windows XP and newer versions")
endif (NOT HAVE_WSPIAPI_H)
check_include_file(ws2tcpip.h HAVE_WS2TCPIP_H)
if (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
set(HAVE_GETADDRINFO TRUE)
set(HAVE_GETHOSTBYNAME TRUE)
endif (HAVE_WSPIAPI_H OR HAVE_WS2TCPIP_H)
set(HAVE_SELECT TRUE)
endif (WIN32)
set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
check_include_file(openssl/aes.h HAVE_OPENSSL_AES_H)
@ -32,26 +45,26 @@ set(CMAKE_REQUIRED_INCLUDES ${OPENSSL_INCLUDE_DIRS})
check_include_file(openssl/des.h HAVE_OPENSSL_DES_H)
# FUNCTIONS
check_function_exists(cfmakeraw HAVE_CFMAKERAW)
if (WIN32)
set(HAVE_GETADDRINFO TRUE)
set(HAVE_GETHOSTBYNAME TRUE)
set(HAVE_SELECT TRUE)
else (WIN32)
if (UNIX)
# libsocket (Solaris)
check_library_exists(socket getaddrinfo "" HAVE_LIBSOCKET)
if (HAVE_LIBSOCKET)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} socket)
endif (HAVE_LIBSOCKET)
# libnsl (Solaris)
check_library_exists(nsl gethostbyname "" HAVE_LIBNSL)
if (HAVE_LIBNSL)
set(CMAKE_REQUIRED_LIBRARIES ${CMAKE_REQUIRED_LIBRARIES} nsl)
endif (HAVE_LIBNSL)
check_function_exists(getaddrinfo HAVE_GETADDRINFO)
if (NOT HAVE_GETADDRINFO)
check_library_exists("socket" "getaddrinfo" "" HAVE_LIB_GETADDRINFO)
set(HAVE_GETADDRINFO 1)
endif (NOT HAVE_GETADDRINFO)
check_function_exists(gethostbyname HAVE_GETHOSTBYNAME)
if (NOT HAVE_GETHOSTBYNAME)
check_library_exists("nsl" "gethostbyname" "" HAVE_LIB_GETHOSTBYNAME)
set(HAVE_GETHOSTBYNAME 1)
endif (NOT HAVE_GETHOSTBYNAME)
check_function_exists(poll HAVE_POLL)
check_function_exists(select HAVE_SELECT)
check_function_exists(cfmakeraw HAVE_CFMAKERAW)
check_function_exists(regcomp HAVE_REGCOMP)
endif (WIN32)
endif (UNIX)
# LIBRARIES
if (CRYPTO_FOUND)

Просмотреть файл

@ -40,6 +40,7 @@ else (OPENSSL_LIBRARIES AND OPENSSL_INCLUDE_DIRS)
/usr/local/ssl/include
/opt/local/include
/sw/include
/usr/lib/sfw/include
)
mark_as_advanced(OPENSSL_INCLUDE_DIR)

Просмотреть файл

@ -23,6 +23,9 @@
/* Define to 1 if you have the <openssl/aes.h> header file. */
#cmakedefine HAVE_OPENSSL_AES_H 1
/* Define to 1 if you have the <wspiapi.h> header file. */
#cmakedefine HAVE_WSPIAPI_H 1
/* Define to 1 if you have the <openssl/blowfish.h> header file. */
#cmakedefine HAVE_OPENSSL_BLOWFISH_H 1

Просмотреть файл

@ -120,6 +120,7 @@ typedef struct ssh_agent_struct* ssh_agent;
typedef struct ssh_session_struct* ssh_session;
typedef struct ssh_kbdint_struct* ssh_kbdint;
typedef struct ssh_scp_struct* ssh_scp;
typedef struct ssh_scp_request_struct* ssh_scp_request;
/* Socket type */
#ifdef _WIN32
@ -336,6 +337,9 @@ LIBSSH_API int channel_request_sftp(ssh_channel channel);
LIBSSH_API int channel_request_x11(ssh_channel channel, int single_connection, const char *protocol,
const char *cookie, int screen_number);
LIBSSH_API ssh_channel channel_accept_x11(ssh_channel channel, int timeout_ms);
LIBSSH_API int channel_forward_listen(ssh_session session, const char *address, int port, int *bound_port);
LIBSSH_API ssh_channel channel_forward_accept(ssh_session session, int timeout_ms);
LIBSSH_API int channel_forward_cancel(ssh_session session, const char *address, int port);
LIBSSH_API int channel_write(ssh_channel channel, const void *data, uint32_t len);
LIBSSH_API int channel_send_eof(ssh_channel channel);
LIBSSH_API int channel_is_eof(ssh_channel channel);
@ -440,6 +444,10 @@ LIBSSH_API int ssh_userauth_kbdint_setanswer(SSH_SESSION *session, unsigned int
LIBSSH_API int ssh_init(void);
LIBSSH_API int ssh_finalize(void);
/* misc.c */
LIBSSH_API char *ssh_dirname (const char *path);
LIBSSH_API char *ssh_basename (const char *path);
/* messages.c */
typedef struct ssh_message_struct SSH_MESSAGE;
typedef struct ssh_message_struct *ssh_message;
@ -461,12 +469,22 @@ enum {
SSH_SCP_READ
};
enum ssh_scp_request_types {
/** A new directory is going to be pulled */
SSH_SCP_REQUEST_NEWDIR,
/** A new file is going to be pulled */
SSH_SCP_REQUEST_NEWFILE
};
LIBSSH_API ssh_scp ssh_scp_new(ssh_session session, int mode, const char *location);
LIBSSH_API int ssh_scp_init(ssh_scp scp);
LIBSSH_API int ssh_scp_close(ssh_scp scp);
LIBSSH_API void ssh_scp_free(ssh_scp scp);
LIBSSH_API int ssh_scp_push_directory(ssh_scp scp, const char *dirname, const char *perms);
LIBSSH_API int ssh_scp_leave_directory(ssh_scp scp);
LIBSSH_API int ssh_scp_push_file(ssh_scp scp, const char *filename, size_t size, const char *perms);
LIBSSH_API int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len);
LIBSSH_API ssh_scp_request ssh_scp_pull_request(ssh_scp scp);
LIBSSH_API int ssh_scp_deny_request(ssh_scp scp, ssh_scp_request request, const char *reason);
#ifdef __cplusplus
}

Просмотреть файл

@ -32,19 +32,16 @@
#ifdef _MSC_VER
#define snprintf _snprintf
/** Imitate define of inttypes.h */
#define PRIdS "Id"
#else
#include <unistd.h>
#define PRIdS "zd"
#endif
#include "config.h"
#include "libssh/libssh.h"
/* Debugging constants */
/* Define this if you want to debug crypto systems */
/* it's usefull when you are debugging the lib */
/*#define DEBUG_CRYPTO */
/* some constants */
#define MAX_PACKET_LEN 262144
#define ERROR_BUFFERLEN 1024
@ -362,6 +359,7 @@ enum ssh_scp_states {
SSH_SCP_READ_READING, //File is opened and reading
SSH_SCP_ERROR //Something bad happened
};
struct ssh_scp_struct {
ssh_session session;
int mode;
@ -372,6 +370,16 @@ struct ssh_scp_struct {
size_t processed;
};
struct ssh_scp_request_struct {
ssh_scp scp;
enum ssh_scp_request_types type;
char *name;
char *mode;
size_t size;
int acked;
};
struct ssh_message_struct;
struct ssh_session_struct {
@ -860,6 +868,10 @@ int match_hostname(const char *host, const char *pattern, unsigned int len);
void message_handle(SSH_SESSION *session, uint32_t type);
int ssh_execute_message_callbacks(SSH_SESSION *session);
/* scp.c */
ssh_scp_request ssh_scp_request_new(void);
/* log.c */
#ifndef __FUNCTION__

Просмотреть файл

@ -1,999 +0,0 @@
/*++
Copyright (c) 2000, Microsoft Corporation
Module Name:
wspiapi.h
Abstract:
The file contains protocol independent API functions.
Revision History:
Wed Jul 12 10:50:31 2000, Created
--*/
#ifndef _WSPIAPI_H_
#define _WSPIAPI_H_
#include <stdio.h> // sprintf()
#include <stdlib.h> // calloc(), strtoul()
#include <malloc.h> // calloc()
#include <string.h> // strlen(), strcmp(), strstr()
#define WspiapiMalloc(tSize) calloc(1, (tSize))
#define WspiapiFree(p) free(p)
#define WspiapiSwap(a, b, c) { (c) = (a); (a) = (b); (b) = (c); }
#define getaddrinfo WspiapiGetAddrInfo
#define getnameinfo WspiapiGetNameInfo
#define freeaddrinfo WspiapiFreeAddrInfo
typedef int (WINAPI *WSPIAPI_PGETADDRINFO) (
IN const char *nodename,
IN const char *servname,
IN const struct addrinfo *hints,
OUT struct addrinfo **res);
typedef int (WINAPI *WSPIAPI_PGETNAMEINFO) (
IN const struct sockaddr *sa,
IN socklen_t salen,
OUT char *host,
IN size_t hostlen,
OUT char *serv,
IN size_t servlen,
IN int flags);
typedef void (WINAPI *WSPIAPI_PFREEADDRINFO) (
IN struct addrinfo *ai);
#ifdef __cplusplus
extern "C" {
#endif
////////////////////////////////////////////////////////////
// v4 only versions of getaddrinfo and friends.
// NOTE: gai_strerror is inlined in ws2tcpip.h
////////////////////////////////////////////////////////////
__inline
char *
WINAPI
WspiapiStrdup (
IN const char * pszString)
/*++
Routine Description
allocates enough storage via calloc() for a copy of the string,
copies the string into the new memory, and returns a pointer to it.
Arguments
pszString string to copy into new memory
Return Value
a pointer to the newly allocated storage with the string in it.
NULL if enough memory could not be allocated, or string was NULL.
--*/
{
char *pszMemory;
if (!pszString)
return(NULL);
pszMemory = (char *) WspiapiMalloc(strlen(pszString) + 1);
if (!pszMemory)
return(NULL);
return(strcpy(pszMemory, pszString));
}
__inline
BOOL
WINAPI
WspiapiParseV4Address (
IN const char * pszAddress,
OUT PDWORD pdwAddress)
/*++
Routine Description
get the IPv4 address (in network byte order) from its string
representation. the syntax should be a.b.c.d.
Arguments
pszArgument string representation of the IPv4 address
ptAddress pointer to the resulting IPv4 address
Return Value
Returns FALSE if there is an error, TRUE for success.
--*/
{
DWORD dwAddress = 0;
const char *pcNext = NULL;
int iCount = 0;
// ensure there are 3 '.' (periods)
for (pcNext = pszAddress; *pcNext != '\0'; pcNext++)
if (*pcNext == '.')
iCount++;
if (iCount != 3)
return FALSE;
// return an error if dwAddress is INADDR_NONE (255.255.255.255)
// since this is never a valid argument to getaddrinfo.
dwAddress = inet_addr(pszAddress);
if (dwAddress == INADDR_NONE)
return FALSE;
*pdwAddress = dwAddress;
return TRUE;
}
__inline
struct addrinfo *
WINAPI
WspiapiNewAddrInfo (
IN int iSocketType,
IN int iProtocol,
IN WORD wPort,
IN DWORD dwAddress)
/*++
Routine Description
allocate an addrinfo structure and populate fields.
IPv4 specific internal function, not exported.
Arguments
iSocketType SOCK_*. can be wildcarded (zero).
iProtocol IPPROTO_*. can be wildcarded (zero).
wPort port number of service (in network order).
dwAddress IPv4 address (in network order).
Return Value
returns an addrinfo struct, or NULL if out of memory.
--*/
{
struct addrinfo *ptNew;
struct sockaddr_in *ptAddress;
// allocate a new addrinfo structure.
ptNew =
(struct addrinfo *) WspiapiMalloc(sizeof(struct addrinfo));
if (!ptNew)
return NULL;
ptAddress =
(struct sockaddr_in *) WspiapiMalloc(sizeof(struct sockaddr_in));
if (!ptAddress)
{
WspiapiFree(ptNew);
return NULL;
}
ptAddress->sin_family = AF_INET;
ptAddress->sin_port = wPort;
ptAddress->sin_addr.s_addr = dwAddress;
// fill in the fields...
ptNew->ai_family = PF_INET;
ptNew->ai_socktype = iSocketType;
ptNew->ai_protocol = iProtocol;
ptNew->ai_addrlen = sizeof(struct sockaddr_in);
ptNew->ai_addr = (struct sockaddr *) ptAddress;
return ptNew;
}
__inline
int
WINAPI
WspiapiQueryDNS(
IN const char *pszNodeName,
IN int iSocketType,
IN int iProtocol,
IN WORD wPort,
OUT char *pszAlias,
OUT struct addrinfo **pptResult)
/*++
Routine Description
helper routine for WspiapiLookupNode.
performs name resolution by querying the DNS for A records.
*pptResult would need to be freed if an error is returned.
Arguments
pszNodeName name of node to resolve.
iSocketType SOCK_*. can be wildcarded (zero).
iProtocol IPPROTO_*. can be wildcarded (zero).
wPort port number of service (in network order).
pszAlias where to return the alias.
pptResult where to return the result.
Return Value
Returns 0 on success, an EAI_* style error value otherwise.
--*/
{
struct addrinfo **pptNext = pptResult;
struct hostent *ptHost = NULL;
char **ppAddresses;
*pptNext = NULL;
pszAlias[0] = '\0';
ptHost = gethostbyname(pszNodeName);
if (ptHost)
{
if ((ptHost->h_addrtype == AF_INET) &&
(ptHost->h_length == sizeof(struct in_addr)))
{
for (ppAddresses = ptHost->h_addr_list;
*ppAddresses != NULL;
ppAddresses++)
{
// create an addrinfo structure...
*pptNext = WspiapiNewAddrInfo(
iSocketType,
iProtocol,
wPort,
((struct in_addr *) *ppAddresses)->s_addr);
if (!*pptNext)
return EAI_MEMORY;
pptNext = &((*pptNext)->ai_next);
}
}
// pick up the canonical name.
strcpy(pszAlias, ptHost->h_name);
return 0;
}
switch (WSAGetLastError())
{
case WSAHOST_NOT_FOUND: return EAI_NONAME;
case WSATRY_AGAIN: return EAI_AGAIN;
case WSANO_RECOVERY: return EAI_FAIL;
case WSANO_DATA: return EAI_NODATA;
default: return EAI_NONAME;
}
}
__inline
int
WINAPI
WspiapiLookupNode(
IN const char *pszNodeName,
IN int iSocketType,
IN int iProtocol,
IN WORD wPort,
IN BOOL bAI_CANONNAME,
OUT struct addrinfo **pptResult)
/*++
Routine Description
resolve a nodename and return a list of addrinfo structures.
IPv4 specific internal function, not exported.
*pptResult would need to be freed if an error is returned.
NOTE: if bAI_CANONNAME is true, the canonical name should be
returned in the first addrinfo structure.
Arguments
pszNodeName name of node to resolve.
iSocketType SOCK_*. can be wildcarded (zero).
iProtocol IPPROTO_*. can be wildcarded (zero).
wPort port number of service (in network order).
bAI_CANONNAME whether the AI_CANONNAME flag is set.
pptResult where to return result.
Return Value
Returns 0 on success, an EAI_* style error value otherwise.
--*/
{
int iError = 0;
int iAliasCount = 0;
char szFQDN1[NI_MAXHOST] = "";
char szFQDN2[NI_MAXHOST] = "";
char *pszName = szFQDN1;
char *pszAlias = szFQDN2;
char *pszScratch = NULL;
strcpy(pszName, pszNodeName);
for (;;)
{
iError = WspiapiQueryDNS(pszNodeName,
iSocketType,
iProtocol,
wPort,
pszAlias,
pptResult);
if (iError)
break;
// if we found addresses, then we are done.
if (*pptResult)
break;
// stop infinite loops due to DNS misconfiguration. there appears
// to be no particular recommended limit in RFCs 1034 and 1035.
if ((!strlen(pszAlias)) ||
(!strcmp(pszName, pszAlias)) ||
(++iAliasCount == 16))
{
iError = EAI_FAIL;
break;
}
// there was a new CNAME, look again.
WspiapiSwap(pszName, pszAlias, pszScratch);
}
if (!iError && bAI_CANONNAME)
{
(*pptResult)->ai_canonname = WspiapiStrdup(pszAlias);
if (!(*pptResult)->ai_canonname)
iError = EAI_MEMORY;
}
return iError;
}
__inline
int
WINAPI
WspiapiClone (
IN WORD wPort,
IN struct addrinfo *ptResult)
/*++
Routine Description
clone every addrinfo structure in ptResult for the UDP service.
ptResult would need to be freed if an error is returned.
Arguments
wPort port number of UDP service.
ptResult list of addrinfo structures, each
of whose node needs to be cloned.
Return Value
Returns 0 on success, an EAI_MEMORY on allocation failure.
--*/
{
struct addrinfo *ptNext = NULL;
struct addrinfo *ptNew = NULL;
for (ptNext = ptResult; ptNext != NULL; )
{
// create an addrinfo structure...
ptNew = WspiapiNewAddrInfo(
SOCK_DGRAM,
ptNext->ai_protocol,
wPort,
((struct sockaddr_in *) ptNext->ai_addr)->sin_addr.s_addr);
if (!ptNew)
break;
// link the cloned addrinfo
ptNew->ai_next = ptNext->ai_next;
ptNext->ai_next = ptNew;
ptNext = ptNew->ai_next;
}
if (ptNext != NULL)
return EAI_MEMORY;
return 0;
}
__inline
void
WINAPI
WspiapiLegacyFreeAddrInfo (
IN struct addrinfo *ptHead)
/*++
Routine Description
Free an addrinfo structure (or chain of structures).
As specified in RFC 2553, Section 6.4.
Arguments
ptHead structure (chain) to free
--*/
{
struct addrinfo *ptNext; // next strcture to free
for (ptNext = ptHead; ptNext != NULL; ptNext = ptHead)
{
if (ptNext->ai_canonname)
WspiapiFree(ptNext->ai_canonname);
if (ptNext->ai_addr)
WspiapiFree(ptNext->ai_addr);
ptHead = ptNext->ai_next;
WspiapiFree(ptNext);
}
}
__inline
int
WINAPI
WspiapiLegacyGetAddrInfo(
IN const char *pszNodeName,
IN const char *pszServiceName,
IN const struct addrinfo *ptHints,
OUT struct addrinfo **pptResult)
/*++
Routine Description
Protocol-independent name-to-address translation.
As specified in RFC 2553, Section 6.4.
This is the hacked version that only supports IPv4.
Arguments
pszNodeName node name to lookup.
pszServiceName service name to lookup.
ptHints hints about how to process request.
pptResult where to return result.
Return Value
returns zero if successful, an EAI_* error code if not.
--*/
{
int iError = 0;
int iFlags = 0;
int iFamily = PF_UNSPEC;
int iSocketType = 0;
int iProtocol = 0;
WORD wPort = 0;
DWORD dwAddress = 0;
struct servent *ptService = NULL;
char *pc = NULL;
BOOL bClone = FALSE;
WORD wTcpPort = 0;
WORD wUdpPort = 0;
// initialize pptResult with default return value.
*pptResult = NULL;
////////////////////////////////////////
// validate arguments...
//
// both the node name and the service name can't be NULL.
if ((!pszNodeName) && (!pszServiceName))
return EAI_NONAME;
// validate hints.
if (ptHints)
{
// all members other than ai_flags, ai_family, ai_socktype
// and ai_protocol must be zero or a null pointer.
if ((ptHints->ai_addrlen != 0) ||
(ptHints->ai_canonname != NULL) ||
(ptHints->ai_addr != NULL) ||
(ptHints->ai_next != NULL))
{
return EAI_FAIL;
}
// the spec has the "bad flags" error code, so presumably we
// should check something here. insisting that there aren't
// any unspecified flags set would break forward compatibility,
// however. so we just check for non-sensical combinations.
//
// we cannot come up with a canonical name given a null node name.
iFlags = ptHints->ai_flags;
if ((iFlags & AI_CANONNAME) && !pszNodeName)
return EAI_BADFLAGS;
// we only support a limited number of protocol families.
iFamily = ptHints->ai_family;
if ((iFamily != PF_UNSPEC) && (iFamily != PF_INET))
return EAI_FAMILY;
// we only support only these socket types.
iSocketType = ptHints->ai_socktype;
if ((iSocketType != 0) &&
(iSocketType != SOCK_STREAM) &&
(iSocketType != SOCK_DGRAM) &&
(iSocketType != SOCK_RAW))
return EAI_SOCKTYPE;
// REVIEW: What if ai_socktype and ai_protocol are at odds?
iProtocol = ptHints->ai_protocol;
}
////////////////////////////////////////
// do service lookup...
if (pszServiceName)
{
wPort = (WORD) strtoul(pszServiceName, &pc, 10);
if (*pc == '\0') // numeric port string
{
wPort = wTcpPort = wUdpPort = htons(wPort);
if (iSocketType == 0)
{
bClone = TRUE;
iSocketType = SOCK_STREAM;
}
}
else // non numeric port string
{
if ((iSocketType == 0) || (iSocketType == SOCK_DGRAM))
{
ptService = getservbyname(pszServiceName, "udp");
if (ptService)
wPort = wUdpPort = ptService->s_port;
}
if ((iSocketType == 0) || (iSocketType == SOCK_STREAM))
{
ptService = getservbyname(pszServiceName, "tcp");
if (ptService)
wPort = wTcpPort = ptService->s_port;
}
// assumes 0 is an invalid service port...
if (wPort == 0) // no service exists
return (iSocketType ? EAI_SERVICE : EAI_NONAME);
if (iSocketType == 0)
{
// if both tcp and udp, process tcp now & clone udp later.
iSocketType = (wTcpPort) ? SOCK_STREAM : SOCK_DGRAM;
bClone = (wTcpPort && wUdpPort);
}
}
}
////////////////////////////////////////
// do node name lookup...
// if we weren't given a node name,
// return the wildcard or loopback address (depending on AI_PASSIVE).
//
// if we have a numeric host address string,
// return the binary address.
//
if ((!pszNodeName) || (WspiapiParseV4Address(pszNodeName, &dwAddress)))
{
if (!pszNodeName)
{
dwAddress = htonl((iFlags & AI_PASSIVE)
? INADDR_ANY
: INADDR_LOOPBACK);
}
// create an addrinfo structure...
*pptResult =
WspiapiNewAddrInfo(iSocketType, iProtocol, wPort, dwAddress);
if (!(*pptResult))
iError = EAI_MEMORY;
if (!iError && pszNodeName)
{
// implementation specific behavior: set AI_NUMERICHOST
// to indicate that we got a numeric host address string.
(*pptResult)->ai_flags |= AI_NUMERICHOST;
// return the numeric address string as the canonical name
if (iFlags & AI_CANONNAME)
{
(*pptResult)->ai_canonname =
WspiapiStrdup(inet_ntoa(*((struct in_addr *) &dwAddress)));
if (!(*pptResult)->ai_canonname)
iError = EAI_MEMORY;
}
}
}
// if we do not have a numeric host address string and
// AI_NUMERICHOST flag is set, return an error!
else if (iFlags & AI_NUMERICHOST)
{
iError = EAI_NONAME;
}
// since we have a non-numeric node name,
// we have to do a regular node name lookup.
else
{
iError = WspiapiLookupNode(pszNodeName,
iSocketType,
iProtocol,
wPort,
(iFlags & AI_CANONNAME),
pptResult);
}
if (!iError && bClone)
{
iError = WspiapiClone(wUdpPort, *pptResult);
}
if (iError)
{
WspiapiLegacyFreeAddrInfo(*pptResult);
*pptResult = NULL;
}
return (iError);
}
__inline
int
WINAPI
WspiapiLegacyGetNameInfo(
IN const struct sockaddr *ptSocketAddress,
IN socklen_t tSocketLength,
OUT char *pszNodeName,
IN size_t tNodeLength,
OUT char *pszServiceName,
IN size_t tServiceLength,
IN int iFlags)
/*++
Routine Description
protocol-independent address-to-name translation.
as specified in RFC 2553, Section 6.5.
this is the hacked version that only supports IPv4.
Arguments
ptSocketAddress socket address to translate.
tSocketLength length of above socket address.
pszNodeName where to return the node name.
tNodeLength size of above buffer.
pszServiceName where to return the service name.
tServiceLength size of above buffer.
iFlags flags of type NI_*.
Return Value
returns zero if successful, an EAI_* error code if not.
--*/
{
struct servent *ptService;
WORD wPort;
char szBuffer[] = "65535";
char *pszService = szBuffer;
struct hostent *ptHost;
struct in_addr tAddress;
char *pszNode = NULL;
char *pc = NULL;
// sanity check ptSocketAddress and tSocketLength.
if (!ptSocketAddress)
return EAI_FAIL;
if ((ptSocketAddress->sa_family != AF_INET) ||
(tSocketLength != sizeof(struct sockaddr_in)))
{
return EAI_FAMILY;
}
if (!(pszNodeName && tNodeLength) &&
!(pszServiceName && tServiceLength))
{
return EAI_NONAME;
}
// the draft has the "bad flags" error code, so presumably we
// should check something here. insisting that there aren't
// any unspecified flags set would break forward compatibility,
// however. so we just check for non-sensical combinations.
if ((iFlags & NI_NUMERICHOST) && (iFlags & NI_NAMEREQD))
{
return EAI_BADFLAGS;
}
// translate the port to a service name (if requested).
if (pszServiceName && tServiceLength)
{
wPort = ((struct sockaddr_in *) ptSocketAddress)->sin_port;
if (iFlags & NI_NUMERICSERV)
{
// return numeric form of the address.
sprintf(szBuffer, "%u", ntohs(wPort));
}
else
{
// return service name corresponding to port.
ptService = getservbyport(wPort,
(iFlags & NI_DGRAM) ? "udp" : NULL);
if (ptService && ptService->s_name)
{
// lookup successful.
pszService = ptService->s_name;
}
else
{
// DRAFT: return numeric form of the port!
sprintf(szBuffer, "%u", ntohs(wPort));
}
}
if (tServiceLength > strlen(pszService))
strcpy(pszServiceName, pszService);
else
return EAI_FAIL;
}
// translate the address to a node name (if requested).
if (pszNodeName && tNodeLength)
{
// this is the IPv4-only version, so we have an IPv4 address.
tAddress = ((struct sockaddr_in *) ptSocketAddress)->sin_addr;
if (iFlags & NI_NUMERICHOST)
{
// return numeric form of the address.
pszNode = inet_ntoa(tAddress);
}
else
{
// return node name corresponding to address.
ptHost = gethostbyaddr((char *) &tAddress,
sizeof(struct in_addr),
AF_INET);
if (ptHost && ptHost->h_name)
{
// DNS lookup successful.
// stop copying at a "." if NI_NOFQDN is specified.
pszNode = ptHost->h_name;
if ((iFlags & NI_NOFQDN) && (pc = strchr(pszNode, '.')))
*pc = '\0';
}
else
{
// DNS lookup failed. return numeric form of the address.
if (iFlags & NI_NAMEREQD)
{
switch (WSAGetLastError())
{
case WSAHOST_NOT_FOUND: return EAI_NONAME;
case WSATRY_AGAIN: return EAI_AGAIN;
case WSANO_RECOVERY: return EAI_FAIL;
default: return EAI_NONAME;
}
}
else
pszNode = inet_ntoa(tAddress);
}
}
if (tNodeLength > strlen(pszNode))
strcpy(pszNodeName, pszNode);
else
return EAI_FAIL;
}
return 0;
}
typedef struct
{
char const *pszName;
FARPROC pfAddress;
} WSPIAPI_FUNCTION;
#define WSPIAPI_FUNCTION_ARRAY \
{ \
"getaddrinfo", (FARPROC) WspiapiLegacyGetAddrInfo, \
"getnameinfo", (FARPROC) WspiapiLegacyGetNameInfo, \
"freeaddrinfo", (FARPROC) WspiapiLegacyFreeAddrInfo, \
}
__inline
FARPROC
WINAPI
WspiapiLoad(
IN WORD wFunction)
/*++
Routine Description
try to locate the address family independent name resolution routines
(i.e. getaddrinfo, getnameinfo, freeaddrinfo, gai_strerror).
Locks
this function call is not synchronized. hence the library containing
the routines might be loaded multiple times. another option is to
synchronize through a spin lock using a static local variable and the
InterlockedExchange operation.
Arguments
wFunction ordinal # of the function to get the pointer to
0 getaddrinfo
1 getnameinfo
2 freeaddrinfo
Return Value
address of the library/legacy routine
--*/
{
HMODULE hLibrary = NULL;
// these static variables store state across calls, across threads.
static BOOL bInitialized = FALSE;
static WSPIAPI_FUNCTION rgtGlobal[] = WSPIAPI_FUNCTION_ARRAY;
static const int iNumGlobal = (sizeof(rgtGlobal) /
sizeof(WSPIAPI_FUNCTION));
// we overwrite rgtGlobal only if all routines exist in library.
WSPIAPI_FUNCTION rgtLocal[] = WSPIAPI_FUNCTION_ARRAY;
FARPROC fScratch = NULL;
int i = 0;
if (bInitialized) // WspiapiLoad has already been called once
return (rgtGlobal[wFunction].pfAddress);
do // breakout loop
{
// in Whistler and beyond...
// the routines are present in the WinSock 2 library (ws2_32.dll).
// printf("Looking in ws2_32 for getaddrinfo...\n");
hLibrary = LoadLibraryA("ws2_32");
if (hLibrary != NULL)
{
fScratch = GetProcAddress(hLibrary, "getaddrinfo");
if (fScratch == NULL)
{
FreeLibrary(hLibrary);
hLibrary = NULL;
}
}
if (hLibrary != NULL)
break;
// in the IPv6 Technology Preview...
// the routines are present in the IPv6 WinSock library (wship6.dll).
// printf("Looking in wship6 for getaddrinfo...\n");
hLibrary = LoadLibraryA("wship6");
if (hLibrary != NULL)
{
fScratch = GetProcAddress(hLibrary, "getaddrinfo");
if (fScratch == NULL)
{
FreeLibrary(hLibrary);
hLibrary = NULL;
}
}
} while (FALSE);
if (hLibrary != NULL)
{
// use routines from this library...
// since getaddrinfo is here, we expect all routines to be here,
// but will fall back to IPv4-only if any of them is missing.
for (i = 0; i < iNumGlobal; i++)
{
rgtLocal[i].pfAddress
= GetProcAddress(hLibrary, rgtLocal[i].pszName);
if (rgtLocal[i].pfAddress == NULL)
{
FreeLibrary(hLibrary);
hLibrary = NULL;
break;
}
}
if (hLibrary != NULL)
{
// printf("found!\n");
for (i = 0; i < iNumGlobal; i++)
rgtGlobal[i].pfAddress = rgtLocal[i].pfAddress;
}
}
bInitialized = TRUE;
return (rgtGlobal[wFunction].pfAddress);
}
__inline
int
WINAPI
WspiapiGetAddrInfo(
IN const char *nodename,
IN const char *servname,
IN const struct addrinfo *hints,
OUT struct addrinfo **res)
{
static WSPIAPI_PGETADDRINFO pfGetAddrInfo = NULL;
if (!pfGetAddrInfo)
pfGetAddrInfo = (WSPIAPI_PGETADDRINFO) WspiapiLoad(0);
return ((*pfGetAddrInfo)
(nodename, servname, hints, res));
}
__inline
int
WINAPI
WspiapiGetNameInfo (
IN const struct sockaddr *sa,
IN socklen_t salen,
OUT char *host,
IN size_t hostlen,
OUT char *serv,
IN size_t servlen,
IN int flags)
{
static WSPIAPI_PGETNAMEINFO pfGetNameInfo = NULL;
if (!pfGetNameInfo)
pfGetNameInfo = (WSPIAPI_PGETNAMEINFO) WspiapiLoad(1);
return ((*pfGetNameInfo)
(sa, salen, host, hostlen, serv, servlen, flags));
}
__inline
void
WINAPI
WspiapiFreeAddrInfo (
IN struct addrinfo *ai)
{
static WSPIAPI_PFREEADDRINFO pfFreeAddrInfo = NULL;
if (!pfFreeAddrInfo)
pfFreeAddrInfo = (WSPIAPI_PFREEADDRINFO) WspiapiLoad(2);
(*pfFreeAddrInfo)(ai);
}
#ifdef __cplusplus
}
#endif
#endif // _WSPIAPI_H_

Просмотреть файл

@ -35,19 +35,19 @@ if (WIN32)
)
endif (WIN32)
if (HAVE_LIB_GETHOSTBYNAME)
if (HAVE_LIBNSL)
set(LIBSSH_LINK_LIBRARIES
${LIBSSH_LINK_LIBRARIES}
nsl
)
endif (HAVE_LIB_GETHOSTBYNAME)
endif (HAVE_LIBNSL)
if (HAVE_LIB_GETADDRINFO)
if (HAVE_LIBSOCKET)
set(LIBSSH_LINK_LIBRARIES
${LIBSSH_LINK_LIBRARIES}
socket
)
endif (HAVE_LIB_GETADDRINFO)
endif (HAVE_LIBSOCKET)
if (CRYPTO_LIBRARY)
set(LIBSSH_PRIVATE_INCLUDE_DIRS

Просмотреть файл

@ -1057,7 +1057,7 @@ static int channel_request(ssh_channel channel, const char *request,
}
rc = packet_wait(session, SSH2_MSG_CHANNEL_SUCCESS, 1);
if (rc) {
if (rc == SSH_ERROR) {
if (session->in_packet.type == SSH2_MSG_CHANNEL_FAILURE) {
ssh_log(session, SSH_LOG_PACKET,
"%s channel request failed", request);
@ -1335,19 +1335,14 @@ error:
return rc;
}
static ssh_channel channel_accept(ssh_session session, int channeltype,
int timeout_ms) {
#ifndef _WIN32
/**
* @brief Accept an X11 forwarding channel.
*
* @param channel An x11-enabled session channel.
*
* @param timeout_ms Timeout in milli-seconds.
*
* @return Newly created channel, or NULL if no X11 request from the server
*/
ssh_channel channel_accept_x11(ssh_channel channel, int timeout_ms) {
static const struct timespec ts = {0, 50000000}; /* 50ms */
SSH_SESSION *session = channel->session;
static const struct timespec ts = {
.tv_sec = 0,
.tv_nsec = 50000000 /* 50ms */
};
#endif
SSH_MESSAGE *msg = NULL;
struct ssh_iterator *iterator;
int t;
@ -1361,19 +1356,207 @@ ssh_channel channel_accept_x11(ssh_channel channel, int timeout_ms) {
while (iterator) {
msg = (SSH_MESSAGE*)iterator->data;
if (ssh_message_type(msg) == SSH_REQUEST_CHANNEL_OPEN &&
ssh_message_subtype(msg) == SSH_CHANNEL_X11) {
ssh_message_subtype(msg) == channeltype) {
ssh_list_remove(session->ssh_message_list, iterator);
return ssh_message_channel_request_open_reply_accept(msg);
}
iterator = iterator->next;
}
}
#ifdef _WIN32
Sleep(50); /* 50ms */
#else
nanosleep(&ts, NULL);
#endif
}
return NULL;
}
#endif
/**
* @brief Accept an X11 forwarding channel.
*
* @param channel An x11-enabled session channel.
*
* @param timeout_ms Timeout in milli-seconds.
*
* @return Newly created channel, or NULL if no X11 request from the server
*/
ssh_channel channel_accept_x11(ssh_channel channel, int timeout_ms) {
return channel_accept(channel->session, SSH_CHANNEL_X11, timeout_ms);
}
static int global_request(ssh_session session, const char *request,
ssh_buffer buffer, int reply) {
ssh_string req = NULL;
int rc = SSH_ERROR;
enter_function();
req = string_from_char(request);
if (req == NULL) {
goto error;
}
if (buffer_add_u8(session->out_buffer, SSH2_MSG_GLOBAL_REQUEST) < 0 ||
buffer_add_ssh_string(session->out_buffer, req) < 0 ||
buffer_add_u8(session->out_buffer, reply == 0 ? 0 : 1) < 0) {
goto error;
}
string_free(req);
if (buffer != NULL) {
if (buffer_add_data(session->out_buffer, buffer_get(buffer),
buffer_get_len(buffer)) < 0) {
goto error;
}
}
if (packet_send(session) != SSH_OK) {
leave_function();
return rc;
}
ssh_log(session, SSH_LOG_RARE,
"Sent a SSH_MSG_GLOBAL_REQUEST %s", request);
if (reply == 0) {
leave_function();
return SSH_OK;
}
rc = packet_wait(session, SSH2_MSG_REQUEST_SUCCESS, 1);
if (rc == SSH_ERROR) {
if (session->in_packet.type == SSH2_MSG_REQUEST_FAILURE) {
ssh_log(session, SSH_LOG_PACKET,
"%s channel request failed", request);
ssh_set_error(session, SSH_REQUEST_DENIED,
"Channel request %s failed", request);
} else {
ssh_log(session, SSH_LOG_RARE,
"Received an unexpected %d message", session->in_packet.type);
}
} else {
ssh_log(session, SSH_LOG_RARE, "Received a SUCCESS");
}
leave_function();
return rc;
error:
buffer_reinit(session->out_buffer);
string_free(req);
leave_function();
return rc;
}
/**
* @brief Sends the "tcpip-forward" global request to ask the server to begin
* listening for inbound connections.
*
* @param session The ssh session to send the request.
*
* @param address The address to bind to on the server. Pass NULL to bind
* to all available addresses on all protocol families
* supported by the server.
*
* @param port The port to bind to on the server. Pass 0 to ask the
* server to allocate the next available unprivileged port
* number
*
* @param bound_port The pointer to get actual bound port. Pass NULL to
* ignore.
*
* @return SSH_OK on success\n
* SSH_ERROR on error
*/
int channel_forward_listen(ssh_session session, const char *address, int port, int *bound_port) {
ssh_buffer buffer = NULL;
ssh_string addr = NULL;
int rc = SSH_ERROR;
uint32_t tmp;
buffer = buffer_new();
if (buffer == NULL) {
goto error;
}
addr = string_from_char(address ? address : "");
if (addr == NULL) {
goto error;
}
if (buffer_add_ssh_string(buffer, addr) < 0 ||
buffer_add_u32(buffer, htonl(port)) < 0) {
goto error;
}
rc = global_request(session, "tcpip-forward", buffer, 1);
if (rc == SSH_OK && port == 0 && bound_port) {
buffer_get_u32(session->in_buffer, &tmp);
*bound_port = ntohl(tmp);
}
error:
buffer_free(buffer);
string_free(addr);
return rc;
}
/**
* @brief Accept an incoming TCP/IP forwarding channel.
*
* @param session The ssh session to use.
*
* @param timeout_ms Timeout in milli-seconds.
*
* @return Newly created channel, or NULL if no incoming channel request from
* the server
*/
ssh_channel channel_forward_accept(ssh_session session, int timeout_ms) {
return channel_accept(session, SSH_CHANNEL_FORWARDED_TCPIP, timeout_ms);
}
/**
* @brief Sends the "cancel-tcpip-forward" global request to ask the server to
* cancel the tcpip-forward request.
*
* @param session The ssh session to send the request.
*
* @param address The bound address on the server.
*
* @param port The bound port on the server.
*
* @return SSH_OK on success\n
* SSH_ERROR on error
*/
int channel_forward_cancel(ssh_session session, const char *address, int port) {
ssh_buffer buffer = NULL;
ssh_string addr = NULL;
int rc = SSH_ERROR;
buffer = buffer_new();
if (buffer == NULL) {
goto error;
}
addr = string_from_char(address ? address : "");
if (addr == NULL) {
goto error;
}
if (buffer_add_ssh_string(buffer, addr) < 0 ||
buffer_add_u32(buffer, htonl(port)) < 0) {
goto error;
}
rc = global_request(session, "cancel-tcpip-forward", buffer, 1);
error:
buffer_free(buffer);
string_free(addr);
return rc;
}
/**
* @brief Set environement variables.

Просмотреть файл

@ -28,13 +28,25 @@
#include <string.h>
#ifdef _WIN32
/* getaddrinfo, freeaddrinfo, getnameinfo */
#define _WIN32_WINNT 0x0501
/*
* Only use Windows API functions available on Windows 2000 SP4 or later.
* The available constants are in <sdkddkver.h>.
* http://msdn.microsoft.com/en-us/library/aa383745.aspx
* http://blogs.msdn.com/oldnewthing/archive/2007/04/11/2079137.aspx
*/
#undef _WIN32_WINNT
#define _WIN32_WINNT 0x0500 /* _WIN32_WINNT_WIN2K */
#undef NTDDI_VERSION
#define NTDDI_VERSION 0x05000400 /* NTDDI_WIN2KSP4 */
#include <winsock2.h>
#include <ws2tcpip.h>
#include "wspiapi.h" /* Workaround for w2k systems */
/* <wspiapi.h> is necessary for getaddrinfo before Windows XP, but it isn't
* available on some platforms like MinGW. */
#ifdef HAVE_WSPIAPI_H
#include <wspiapi.h>
#endif
#else /* _WIN32 */

Просмотреть файл

@ -542,7 +542,6 @@ static int dsa_public_to_string(DSA *key, ssh_buffer buffer) {
goto error;
}
string_fill(n, (char *) tmp, size);
gcry_sexp_release(sexp);
#elif defined HAVE_LIBCRYPTO
p = make_bignum_string(key->p);

Просмотреть файл

@ -238,6 +238,114 @@ const void *_ssh_list_get_head(struct ssh_list *list){
return data;
}
/**
* @brief Parse directory component.
*
* dirname breaks a null-terminated pathname string into a directory component.
* In the usual case, ssh_dirname() returns the string up to, but not including,
* the final '/'. Trailing '/' characters are not counted as part of the
* pathname. The caller must free the memory.
*
* @param path The path to parse.
*
* @return The dirname of path or NULL if we can't allocate memory. If path
* does not contain a slash, c_dirname() returns the string ".". If
* path is the string "/", it returns the string "/". If path is
* NULL or an empty string, "." is returned.
*/
char *ssh_dirname (const char *path) {
char *new = NULL;
unsigned int len;
if (path == NULL || *path == '\0') {
return strdup(".");
}
len = strlen(path);
/* Remove trailing slashes */
while(len > 0 && path[len - 1] == '/') --len;
/* We have only slashes */
if (len == 0) {
return strdup("/");
}
/* goto next slash */
while(len > 0 && path[len - 1] != '/') --len;
if (len == 0) {
return strdup(".");
} else if (len == 1) {
return strdup("/");
}
/* Remove slashes again */
while(len > 0 && path[len - 1] == '/') --len;
new = malloc(len + 1);
if (new == NULL) {
return NULL;
}
strncpy(new, path, len);
new[len] = '\0';
return new;
}
/**
* @brief basename - parse filename component.
*
* basename breaks a null-terminated pathname string into a filename component.
* ssh_basename() returns the component following the final '/'. Trailing '/'
* characters are not counted as part of the pathname.
*
* @param path The path to parse.
*
* @return The filename of path or NULL if we can't allocate memory. If path
* is a the string "/", basename returns the string "/". If path is
* NULL or an empty string, "." is returned.
*/
char *ssh_basename (const char *path) {
char *new = NULL;
const char *s;
unsigned int len;
if (path == NULL || *path == '\0') {
return strdup(".");
}
len = strlen(path);
/* Remove trailing slashes */
while(len > 0 && path[len - 1] == '/') --len;
/* We have only slashes */
if (len == 0) {
return strdup("/");
}
while(len > 0 && path[len - 1] != '/') --len;
if (len > 0) {
s = path + len;
len = strlen(s);
while(len > 0 && s[len - 1] == '/') --len;
} else {
return strdup(path);
}
new = malloc(len + 1);
if (new == NULL) {
return NULL;
}
strncpy(new, s, len);
new[len] = '\0';
return new;
}
/** @} */
/* vim: set ts=2 sw=2 et cindent: */

Просмотреть файл

@ -758,6 +758,7 @@ static int packet_wait2(SSH_SESSION *session, int type, int blocking) {
packet_parse(session);
break;
case SSH2_MSG_IGNORE:
case SSH2_MSG_DEBUG:
break;
default:
if (type && (type != session->in_packet.type)) {

Просмотреть файл

@ -21,9 +21,11 @@
* MA 02111-1307, USA.
*/
#include "libssh/priv.h"
#include <stdio.h>
#include <string.h>
#include "libssh/priv.h"
/** @brief Creates a new scp session
* @param session the SSH session to use
* @param mode one of SSH_SCP_WRITE or SSH_SCP_READ, depending if you need to drop files remotely or read them.
@ -121,6 +123,69 @@ void ssh_scp_free(ssh_scp scp){
SAFE_FREE(scp);
}
/** @brief creates a directory in a scp in sink mode
* @param dirname Name of the directory being created.
* @param perms Text form of the unix permissions for the new directory, e.g. "0755".
* @returns SSH_OK if the directory was created.
* @returns SSH_ERROR if an error happened.
* @see ssh_scp_leave_directory
*/
int ssh_scp_push_directory(ssh_scp scp, const char *dirname, const char *perms){
char buffer[1024];
int r;
uint8_t code;
char *dir;
if(scp->state != SSH_SCP_WRITE_INITED){
ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_push_directory called under invalid state");
return SSH_ERROR;
}
dir=ssh_basename(dirname);
snprintf(buffer, sizeof(buffer), "D%s 0 %s\n", perms, dir);
SAFE_FREE(dir);
r=channel_write(scp->channel,buffer,strlen(buffer));
if(r==SSH_ERROR){
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
r=channel_read(scp->channel,&code,1,0);
if(code != 0){
ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code);
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
return SSH_OK;
}
/**
* @brief Leaves a directory
* @returns SSH_OK if the directory was created.
* @returns SSH_ERROR if an error happened.
* @see ssh_scp_push_directory
*/
int ssh_scp_leave_directory(ssh_scp scp){
char buffer[1024];
int r;
uint8_t code;
if(scp->state != SSH_SCP_WRITE_INITED){
ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_leave_directory called under invalid state");
return SSH_ERROR;
}
strcpy(buffer, "E\n");
r=channel_write(scp->channel,buffer,strlen(buffer));
if(r==SSH_ERROR){
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
r=channel_read(scp->channel,&code,1,0);
if(code != 0){
ssh_set_error(scp->session,SSH_FATAL, "scp status code %ud not valid", code);
scp->state=SSH_SCP_ERROR;
return SSH_ERROR;
}
return SSH_OK;
}
/** @brief initializes the sending of a file to a scp in sink mode
* @param filename Name of the file being sent. It should not contain any path indicator
* @param size Exact size in bytes of the file being sent.
@ -132,11 +197,14 @@ int ssh_scp_push_file(ssh_scp scp, const char *filename, size_t size, const char
char buffer[1024];
int r;
uint8_t code;
char *file;
if(scp->state != SSH_SCP_WRITE_INITED){
ssh_set_error(scp->session,SSH_FATAL,"ssh_scp_push_file called under invalid state");
return SSH_ERROR;
}
snprintf(buffer,sizeof(buffer),"C%s %ld %s\n",perms, size, filename);
file=ssh_basename(filename);
snprintf(buffer, sizeof(buffer), "C%s %" PRIdS " %s\n", perms, size, file);
SAFE_FREE(file);
r=channel_write(scp->channel,buffer,strlen(buffer));
if(r==SSH_ERROR){
scp->state=SSH_SCP_ERROR;
@ -198,3 +266,12 @@ int ssh_scp_write(ssh_scp scp, const void *buffer, size_t len){
}
return SSH_OK;
}
ssh_scp_request ssh_scp_request_new(void){
ssh_scp_request r=malloc(sizeof(struct ssh_scp_request_struct));
if(r==NULL)
return NULL;
ZERO_STRUCTP(r);
return r;
}

Просмотреть файл

@ -578,28 +578,28 @@ unsigned int sftp_extensions_get_count(SFTP_SESSION *sftp) {
return sftp->ext->count;
}
const char *sftp_extensions_get_name(SFTP_SESSION *sftp, unsigned int index) {
const char *sftp_extensions_get_name(SFTP_SESSION *sftp, unsigned int idx) {
if (sftp == NULL || sftp->ext == NULL || sftp->ext->name == NULL) {
return NULL;
}
if (index > sftp->ext->count) {
if (idx > sftp->ext->count) {
return NULL;
}
return sftp->ext->name[index];
return sftp->ext->name[idx];
}
const char *sftp_extensions_get_data(SFTP_SESSION *sftp, unsigned int index) {
const char *sftp_extensions_get_data(SFTP_SESSION *sftp, unsigned int idx) {
if (sftp == NULL || sftp->ext == NULL || sftp->ext->data == NULL) {
return NULL;
}
if (index > sftp->ext->count) {
if (idx > sftp->ext->count) {
return NULL;
}
return sftp->ext->data[index];
return sftp->ext->data[idx];
}
int sftp_extension_supported(SFTP_SESSION *sftp, const char *name,
@ -2453,7 +2453,7 @@ char *sftp_readlink(SFTP_SESSION *sftp, const char *path) {
ssh_string path_s = NULL;
ssh_string link_s = NULL;
ssh_buffer buffer;
char *link;
char *lnk;
uint32_t ignored;
uint32_t id;
@ -2499,10 +2499,10 @@ char *sftp_readlink(SFTP_SESSION *sftp, const char *path) {
if (link_s == NULL) {
return NULL;
}
link = string_to_char(link_s);
lnk = string_to_char(link_s);
string_free(link_s);
return link;
return lnk;
} else if (msg->packet_type == SSH_FXP_STATUS) { /* bad response (error) */
status = parse_status_msg(msg);
sftp_message_free(msg);
@ -2616,7 +2616,7 @@ SFTP_STATVFS *sftp_statvfs(SFTP_SESSION *sftp, const char *path) {
STATUS_MESSAGE *status = NULL;
SFTP_MESSAGE *msg = NULL;
ssh_string pathstr;
ssh_string statvfs;
ssh_string ext;
ssh_buffer buffer;
uint32_t id;
@ -2629,8 +2629,8 @@ SFTP_STATVFS *sftp_statvfs(SFTP_SESSION *sftp, const char *path) {
return NULL;
}
statvfs = string_from_char("statvfs@openssh.com");
if (statvfs == NULL) {
ext = string_from_char("statvfs@openssh.com");
if (ext == NULL) {
buffer_free(buffer);
return NULL;
}
@ -2638,22 +2638,22 @@ SFTP_STATVFS *sftp_statvfs(SFTP_SESSION *sftp, const char *path) {
pathstr = string_from_char(path);
if (pathstr == NULL) {
buffer_free(buffer);
string_free(statvfs);
string_free(ext);
return NULL;
}
id = sftp_get_new_id(sftp);
if (buffer_add_u32(buffer, id) < 0 ||
buffer_add_ssh_string(buffer, statvfs) < 0 ||
buffer_add_ssh_string(buffer, ext) < 0 ||
buffer_add_ssh_string(buffer, pathstr) < 0 ||
sftp_packet_write(sftp, SSH_FXP_EXTENDED, buffer) < 0) {
buffer_free(buffer);
string_free(statvfs);
string_free(ext);
string_free(pathstr);
return NULL;
}
buffer_free(buffer);
string_free(statvfs);
string_free(ext);
string_free(pathstr);
while (msg == NULL) {
@ -2664,13 +2664,13 @@ SFTP_STATVFS *sftp_statvfs(SFTP_SESSION *sftp, const char *path) {
}
if (msg->packet_type == SSH_FXP_EXTENDED_REPLY) {
SFTP_STATVFS *statvfs = sftp_parse_statvfs(sftp, msg->payload);
SFTP_STATVFS *buf = sftp_parse_statvfs(sftp, msg->payload);
sftp_message_free(msg);
if (statvfs == NULL) {
if (buf == NULL) {
return NULL;
}
return statvfs;
return buf;
} else if (msg->packet_type == SSH_FXP_STATUS) { /* bad response (error) */
status = parse_status_msg(msg);
sftp_message_free(msg);
@ -2693,7 +2693,7 @@ SFTP_STATVFS *sftp_fstatvfs(SFTP_FILE *file) {
STATUS_MESSAGE *status = NULL;
SFTP_MESSAGE *msg = NULL;
SFTP_SESSION *sftp;
ssh_string fstatvfs;
ssh_string ext;
ssh_buffer buffer;
uint32_t id;
@ -2707,23 +2707,23 @@ SFTP_STATVFS *sftp_fstatvfs(SFTP_FILE *file) {
return NULL;
}
fstatvfs = string_from_char("fstatvfs@openssh.com");
if (fstatvfs == NULL) {
ext = string_from_char("fstatvfs@openssh.com");
if (ext == NULL) {
buffer_free(buffer);
return NULL;
}
id = sftp_get_new_id(sftp);
if (buffer_add_u32(buffer, id) < 0 ||
buffer_add_ssh_string(buffer, fstatvfs) < 0 ||
buffer_add_ssh_string(buffer, ext) < 0 ||
buffer_add_ssh_string(buffer, file->handle) < 0 ||
sftp_packet_write(sftp, SSH_FXP_EXTENDED, buffer) < 0) {
buffer_free(buffer);
string_free(fstatvfs);
string_free(ext);
return NULL;
}
buffer_free(buffer);
string_free(fstatvfs);
string_free(ext);
while (msg == NULL) {
if (sftp_read_and_dispatch(sftp) < 0) {
@ -2733,13 +2733,13 @@ SFTP_STATVFS *sftp_fstatvfs(SFTP_FILE *file) {
}
if (msg->packet_type == SSH_FXP_EXTENDED_REPLY) {
SFTP_STATVFS *statvfs = sftp_parse_statvfs(sftp, msg->payload);
SFTP_STATVFS *buf = sftp_parse_statvfs(sftp, msg->payload);
sftp_message_free(msg);
if (statvfs == NULL) {
if (buf == NULL) {
return NULL;
}
return statvfs;
return buf;
} else if (msg->packet_type == SSH_FXP_STATUS) { /* bad response (error) */
status = parse_status_msg(msg);
sftp_message_free(msg);

Просмотреть файл

@ -346,17 +346,17 @@ void do_sftp(SSH_SESSION *session){
"\tfile system id: %llu\n"
"\tbit mask of f_flag values: %llu\n"
"\tmaximum filename length: %llu\n",
sftpstatvfs->f_bsize,
sftpstatvfs->f_frsize,
sftpstatvfs->f_blocks,
sftpstatvfs->f_bfree,
sftpstatvfs->f_bavail,
sftpstatvfs->f_files,
sftpstatvfs->f_ffree,
sftpstatvfs->f_favail,
sftpstatvfs->f_fsid,
sftpstatvfs->f_flag,
sftpstatvfs->f_namemax);
(unsigned long long) sftpstatvfs->f_bsize,
(unsigned long long) sftpstatvfs->f_frsize,
(unsigned long long) sftpstatvfs->f_blocks,
(unsigned long long) sftpstatvfs->f_bfree,
(unsigned long long) sftpstatvfs->f_bavail,
(unsigned long long) sftpstatvfs->f_files,
(unsigned long long) sftpstatvfs->f_ffree,
(unsigned long long) sftpstatvfs->f_favail,
(unsigned long long) sftpstatvfs->f_fsid,
(unsigned long long) sftpstatvfs->f_flag,
(unsigned long long) sftpstatvfs->f_namemax);
sftp_statvfs_free(sftpstatvfs);
@ -377,17 +377,17 @@ void do_sftp(SSH_SESSION *session){
"\tfile system id: %llu\n"
"\tbit mask of f_flag values: %llu\n"
"\tmaximum filename length: %llu\n",
sysstatvfs.f_bsize,
sysstatvfs.f_frsize,
sysstatvfs.f_blocks,
sysstatvfs.f_bfree,
sysstatvfs.f_bavail,
sysstatvfs.f_files,
sysstatvfs.f_ffree,
sysstatvfs.f_favail,
sysstatvfs.f_fsid,
sysstatvfs.f_flag,
sysstatvfs.f_namemax);
(unsigned long long) sysstatvfs.f_bsize,
(unsigned long long) sysstatvfs.f_frsize,
(unsigned long long) sysstatvfs.f_blocks,
(unsigned long long) sysstatvfs.f_bfree,
(unsigned long long) sysstatvfs.f_bavail,
(unsigned long long) sysstatvfs.f_files,
(unsigned long long) sysstatvfs.f_ffree,
(unsigned long long) sysstatvfs.f_favail,
(unsigned long long) sysstatvfs.f_fsid,
(unsigned long long) sysstatvfs.f_flag,
(unsigned long long) sysstatvfs.f_namemax);
}
/* the connection is made */