mirror of
https://github.com/tmate-io/tmate.git
synced 2024-11-30 12:04:38 +01:00
Update libssh
This commit is contained in:
parent
7be65e79db
commit
2e3661a0f6
@ -174,12 +174,16 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
char buffer[16384];
|
||||
int total=0;
|
||||
int mode;
|
||||
char *filename;
|
||||
char *filename = NULL;
|
||||
/* recursive mode doesn't work yet */
|
||||
(void)recursive;
|
||||
/* Get the file name and size*/
|
||||
if(!src->is_ssh){
|
||||
fd=fileno(src->file);
|
||||
fd = fileno(src->file);
|
||||
if (fd < 0) {
|
||||
fprintf(stderr, "Invalid file pointer, error: %s\n", strerror(errno));
|
||||
return -1;
|
||||
}
|
||||
fstat(fd,&s);
|
||||
size=s.st_size;
|
||||
mode = s.st_mode & ~S_IFMT;
|
||||
@ -201,6 +205,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
}
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"Error: %s\n",ssh_get_error(src->session));
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
} while(r != SSH_SCP_REQUEST_NEWFILE);
|
||||
@ -211,6 +216,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
// snprintf(buffer,sizeof(buffer),"C0644 %d %s\n",size,src->path);
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"error: %s\n",ssh_get_error(dest->session));
|
||||
ssh_string_free_char(filename);
|
||||
ssh_scp_free(dest->scp);
|
||||
return -1;
|
||||
}
|
||||
@ -221,6 +227,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
fprintf(stderr,"Cannot open %s for writing: %s\n",filename,strerror(errno));
|
||||
if(src->is_ssh)
|
||||
ssh_scp_deny_request(src->scp,"Cannot open local file");
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -233,6 +240,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
r=ssh_scp_read(src->scp,buffer,sizeof(buffer));
|
||||
if(r==SSH_ERROR){
|
||||
fprintf(stderr,"Error reading scp: %s\n",ssh_get_error(src->session));
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
if(r==0)
|
||||
@ -243,6 +251,7 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
break;
|
||||
if(r<0){
|
||||
fprintf(stderr,"Error reading file: %s\n",strerror(errno));
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
@ -252,18 +261,21 @@ static int do_copy(struct location *src, struct location *dest, int recursive){
|
||||
fprintf(stderr,"Error writing in scp: %s\n",ssh_get_error(dest->session));
|
||||
ssh_scp_free(dest->scp);
|
||||
dest->scp=NULL;
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
} else {
|
||||
w=fwrite(buffer,r,1,dest->file);
|
||||
if(w<=0){
|
||||
fprintf(stderr,"Error writing in local file: %s\n",strerror(errno));
|
||||
ssh_string_free_char(filename);
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
total+=r;
|
||||
|
||||
} while(total < size);
|
||||
ssh_string_free_char(filename);
|
||||
printf("wrote %d bytes\n",total);
|
||||
return 0;
|
||||
}
|
||||
@ -286,7 +298,7 @@ int main(int argc, char **argv){
|
||||
break;
|
||||
}
|
||||
}
|
||||
if(dest->is_ssh){
|
||||
if (dest->is_ssh && dest->scp != NULL) {
|
||||
r=ssh_scp_close(dest->scp);
|
||||
if(r == SSH_ERROR){
|
||||
fprintf(stderr,"Error closing scp: %s\n",ssh_get_error(dest->session));
|
||||
|
@ -60,9 +60,12 @@ struct ssh_callbacks_struct cb = {
|
||||
|
||||
static void add_cmd(char *cmd){
|
||||
int n;
|
||||
for(n=0;cmds[n] && (n<MAXCMD);n++);
|
||||
if(n==MAXCMD)
|
||||
|
||||
for (n = 0; (n < MAXCMD) && cmds[n] != NULL; n++);
|
||||
|
||||
if (n == MAXCMD) {
|
||||
return;
|
||||
}
|
||||
cmds[n]=strdup(cmd);
|
||||
}
|
||||
|
||||
|
@ -307,10 +307,13 @@ static int main_loop(ssh_channel chan) {
|
||||
}
|
||||
if(ssh_event_add_fd(event, fd, events, copy_fd_to_chan, chan) != SSH_OK) {
|
||||
printf("Couldn't add an fd to the event\n");
|
||||
ssh_event_free(event);
|
||||
return -1;
|
||||
}
|
||||
if(ssh_event_add_session(event, session) != SSH_OK) {
|
||||
printf("Couldn't add the session to the event\n");
|
||||
ssh_event_remove_fd(event, fd);
|
||||
ssh_event_free(event);
|
||||
return -1;
|
||||
}
|
||||
|
||||
|
@ -58,6 +58,8 @@ static int opts(int argc, char **argv){
|
||||
static void create_files(ssh_session session){
|
||||
ssh_channel channel=ssh_channel_new(session);
|
||||
char buffer[1];
|
||||
int rc;
|
||||
|
||||
if(channel == NULL){
|
||||
fprintf(stderr,"Error creating channel: %s\n",ssh_get_error(session));
|
||||
exit(EXIT_FAILURE);
|
||||
@ -74,8 +76,16 @@ static void create_files(ssh_session session){
|
||||
exit(EXIT_FAILURE);
|
||||
}
|
||||
while(!ssh_channel_is_eof(channel)){
|
||||
ssh_channel_read(channel,buffer,1,1);
|
||||
if (write(1,buffer,1) < 0) {
|
||||
rc = ssh_channel_read(channel,buffer,1,1);
|
||||
if (rc != 1) {
|
||||
fprintf(stderr, "Error reading from channel\n");
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
return;
|
||||
}
|
||||
|
||||
rc = write(1, buffer, 1);
|
||||
if (rc < 0) {
|
||||
fprintf(stderr, "Error writing to buffer\n");
|
||||
ssh_channel_close(channel);
|
||||
ssh_channel_free(channel);
|
||||
|
@ -31,6 +31,7 @@
|
||||
#include "libssh/crypto.h"
|
||||
|
||||
#define MAX_PUBKEY_SIZE 0x100000 /* 1M */
|
||||
#define MAX_PRIVKEY_SIZE 0x400000 /* 4M */
|
||||
|
||||
#define SSH_KEY_FLAG_EMPTY 0x0
|
||||
#define SSH_KEY_FLAG_PUBLIC 0x0001
|
||||
|
@ -379,6 +379,8 @@ LIBSSH_API int ssh_channel_write_stderr(ssh_channel channel,
|
||||
const void *data,
|
||||
uint32_t len);
|
||||
|
||||
LIBSSH_API int ssh_send_keepalive(ssh_session session);
|
||||
|
||||
/* deprecated functions */
|
||||
SSH_DEPRECATED LIBSSH_API int ssh_accept(ssh_session session);
|
||||
SSH_DEPRECATED LIBSSH_API int channel_write_stderr(ssh_channel channel,
|
||||
|
@ -55,8 +55,8 @@ int ssh_socket_get_status(ssh_socket s);
|
||||
int ssh_socket_buffered_write_bytes(ssh_socket s);
|
||||
int ssh_socket_data_available(ssh_socket s);
|
||||
int ssh_socket_data_writable(ssh_socket s);
|
||||
void ssh_socket_set_nonblocking(socket_t fd);
|
||||
void ssh_socket_set_blocking(socket_t fd);
|
||||
int ssh_socket_set_nonblocking(socket_t fd);
|
||||
int ssh_socket_set_blocking(socket_t fd);
|
||||
|
||||
void ssh_socket_set_callbacks(ssh_socket s, ssh_socket_callbacks callbacks);
|
||||
int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int revents, void *v_s);
|
||||
|
@ -271,6 +271,7 @@ int ssh_agent_get_ident_count(struct ssh_session_struct *session) {
|
||||
unsigned int type = 0;
|
||||
unsigned int c1 = 0, c2 = 0;
|
||||
uint8_t buf[4] = {0};
|
||||
int rc;
|
||||
|
||||
switch (session->version) {
|
||||
case 1:
|
||||
@ -287,9 +288,14 @@ int ssh_agent_get_ident_count(struct ssh_session_struct *session) {
|
||||
|
||||
/* send message to the agent requesting the list of identities */
|
||||
request = ssh_buffer_new();
|
||||
if (request == NULL) {
|
||||
ssh_set_error_oom(request);
|
||||
return -1;
|
||||
}
|
||||
if (buffer_add_u8(request, c1) < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Not enough space");
|
||||
return -1;
|
||||
ssh_set_error_oom(request);
|
||||
ssh_buffer_free(request);
|
||||
return -1;
|
||||
}
|
||||
|
||||
reply = ssh_buffer_new();
|
||||
@ -307,16 +313,26 @@ int ssh_agent_get_ident_count(struct ssh_session_struct *session) {
|
||||
ssh_buffer_free(request);
|
||||
|
||||
/* get message type and verify the answer */
|
||||
buffer_get_u8(reply, (uint8_t *) &type);
|
||||
rc = buffer_get_u8(reply, (uint8_t *) &type);
|
||||
if (rc != sizeof(uint8_t)) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Bad authentication reply size: %d", rc);
|
||||
ssh_buffer_free(reply);
|
||||
return -1;
|
||||
}
|
||||
|
||||
SSH_LOG(session, SSH_LOG_WARN,
|
||||
"Answer type: %d, expected answer: %d",
|
||||
type, c2);
|
||||
|
||||
if (agent_failed(type)) {
|
||||
return 0;
|
||||
ssh_buffer_free(reply);
|
||||
return 0;
|
||||
} else if (type != c2) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Bad authentication reply message type: %d", type);
|
||||
return -1;
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Bad authentication reply message type: %d", type);
|
||||
ssh_buffer_free(reply);
|
||||
return -1;
|
||||
}
|
||||
|
||||
buffer_get_u32(reply, (uint32_t *) buf);
|
||||
|
@ -1107,12 +1107,9 @@ int ssh_userauth_publickey_auto(ssh_session session,
|
||||
state = session->auth_auto_state;
|
||||
if (state->state == SSH_AUTH_AUTO_STATE_NONE) {
|
||||
#ifndef _WIN32
|
||||
/* Try authentication with ssh-agent first */
|
||||
/* Try authentication with ssh-agent first */
|
||||
rc = ssh_userauth_agent(session, username);
|
||||
if (rc == SSH_AUTH_SUCCESS) {
|
||||
return rc;
|
||||
}
|
||||
if (rc == SSH_AUTH_AGAIN)
|
||||
if (rc == SSH_AUTH_SUCCESS)
|
||||
return rc;
|
||||
#endif
|
||||
state->state = SSH_AUTH_AUTO_STATE_PUBKEY;
|
||||
|
@ -288,6 +288,8 @@ SSH_PACKET_CALLBACK(ssh_packet_data1){
|
||||
SSH_PACKET_CALLBACK(ssh_packet_close1){
|
||||
ssh_channel channel = ssh_get_channel1(session);
|
||||
uint32_t status;
|
||||
int rc;
|
||||
|
||||
(void)type;
|
||||
(void)user;
|
||||
|
||||
@ -305,7 +307,10 @@ SSH_PACKET_CALLBACK(ssh_packet_close1){
|
||||
channel->state = SSH_CHANNEL_STATE_CLOSED;
|
||||
channel->remote_eof = 1;
|
||||
|
||||
buffer_add_u8(session->out_buffer, SSH_CMSG_EXIT_CONFIRMATION);
|
||||
rc = buffer_add_u8(session->out_buffer, SSH_CMSG_EXIT_CONFIRMATION);
|
||||
if (rc < 0) {
|
||||
return SSH_PACKET_NOT_USED;
|
||||
}
|
||||
packet_send(session);
|
||||
|
||||
return SSH_PACKET_USED;
|
||||
|
@ -405,6 +405,7 @@ static void ssh_client_connection_callback(ssh_session session){
|
||||
if (dh_handshake(session) == SSH_ERROR) {
|
||||
goto error;
|
||||
}
|
||||
/* FALL THROUGH */
|
||||
case SSH_SESSION_STATE_DH:
|
||||
if(session->dh_handshake_state==DH_STATE_FINISHED){
|
||||
set_status(session,1.0f);
|
||||
@ -617,7 +618,7 @@ void ssh_disconnect(ssh_session session) {
|
||||
|
||||
enter_function();
|
||||
|
||||
if (ssh_socket_is_open(session->socket)) {
|
||||
if (session->socket != NULL && ssh_socket_is_open(session->socket)) {
|
||||
if (buffer_add_u8(session->out_buffer, SSH2_MSG_DISCONNECT) < 0) {
|
||||
goto error;
|
||||
}
|
||||
@ -642,7 +643,7 @@ void ssh_disconnect(ssh_session session) {
|
||||
}
|
||||
error:
|
||||
session->alive = 0;
|
||||
if(session->socket){
|
||||
if (session->socket != NULL){
|
||||
ssh_socket_reset(session->socket);
|
||||
}
|
||||
session->opts.fd = SSH_INVALID_SOCKET;
|
||||
|
@ -139,6 +139,7 @@ static int ssh_connect_ai_timeout(ssh_session session, const char *host,
|
||||
int timeout_ms;
|
||||
ssh_pollfd_t fds;
|
||||
int rc = 0;
|
||||
int ret;
|
||||
socklen_t len = sizeof(rc);
|
||||
|
||||
enter_function();
|
||||
@ -148,7 +149,13 @@ static int ssh_connect_ai_timeout(ssh_session session, const char *host,
|
||||
*/
|
||||
timeout_ms=timeout * 1000 + usec / 1000;
|
||||
|
||||
ssh_socket_set_nonblocking(s);
|
||||
rc = ssh_socket_set_nonblocking(s);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to set socket non-blocking for %s:%d", host, port);
|
||||
ssh_connect_socket_close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
ssh_log(session, SSH_LOG_RARE, "Trying to connect to host: %s:%d with "
|
||||
"timeout %d ms", host, port, timeout_ms);
|
||||
@ -181,11 +188,11 @@ static int ssh_connect_ai_timeout(ssh_session session, const char *host,
|
||||
leave_function();
|
||||
return -1;
|
||||
}
|
||||
rc = 0;
|
||||
rc = -1;
|
||||
|
||||
/* Get connect(2) return code. Zero means no error */
|
||||
getsockopt(s, SOL_SOCKET, SO_ERROR,(char *) &rc, &len);
|
||||
if (rc != 0) {
|
||||
ret = getsockopt(s, SOL_SOCKET, SO_ERROR,(char *) &rc, &len);
|
||||
if (ret < 0 || rc != 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Connect to %s:%d failed: %s", host, port, strerror(rc));
|
||||
ssh_connect_socket_close(s);
|
||||
@ -195,7 +202,14 @@ static int ssh_connect_ai_timeout(ssh_session session, const char *host,
|
||||
|
||||
/* s is connected ? */
|
||||
ssh_log(session, SSH_LOG_PACKET, "Socket connected with timeout\n");
|
||||
ssh_socket_set_blocking(s);
|
||||
ret = ssh_socket_set_blocking(s);
|
||||
if (ret < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to set socket as blocking connecting to %s:%d failed: %s",
|
||||
host, port, strerror(errno));
|
||||
ssh_connect_socket_close(s);
|
||||
return -1;
|
||||
}
|
||||
|
||||
leave_function();
|
||||
return s;
|
||||
@ -344,7 +358,7 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||
"Failed to resolve bind address %s (%s)",
|
||||
bind_addr,
|
||||
gai_strerror(rc));
|
||||
close(s);
|
||||
ssh_connect_socket_close(s);
|
||||
s=-1;
|
||||
break;
|
||||
}
|
||||
@ -367,7 +381,15 @@ socket_t ssh_connect_host_nonblocking(ssh_session session, const char *host,
|
||||
continue;
|
||||
}
|
||||
}
|
||||
ssh_socket_set_nonblocking(s);
|
||||
|
||||
rc = ssh_socket_set_nonblocking(s);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL,
|
||||
"Failed to set socket non-blocking for %s:%d", host, port);
|
||||
ssh_connect_socket_close(s);
|
||||
s = -1;
|
||||
continue;
|
||||
}
|
||||
|
||||
connect(s, itr->ai_addr, itr->ai_addrlen);
|
||||
break;
|
||||
|
@ -765,8 +765,14 @@ int make_sessionid(ssh_session session) {
|
||||
ssh_log(session,SSH_LOG_WARNING,"ECDH parameted missing");
|
||||
goto error;
|
||||
}
|
||||
buffer_add_ssh_string(buf,session->next_crypto->ecdh_client_pubkey);
|
||||
buffer_add_ssh_string(buf,session->next_crypto->ecdh_server_pubkey);
|
||||
rc = buffer_add_ssh_string(buf,session->next_crypto->ecdh_client_pubkey);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
rc = buffer_add_ssh_string(buf,session->next_crypto->ecdh_server_pubkey);
|
||||
if (rc < 0) {
|
||||
goto error;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
num = make_bignum_string(session->next_crypto->k);
|
||||
|
@ -38,37 +38,57 @@
|
||||
* @brief Starts ecdh-sha2-nistp256 key exchange
|
||||
*/
|
||||
int ssh_client_ecdh_init(ssh_session session){
|
||||
EC_KEY *key=NULL;
|
||||
EC_KEY *key;
|
||||
const EC_GROUP *group;
|
||||
const EC_POINT *pubkey;
|
||||
ssh_string client_pubkey;
|
||||
int len;
|
||||
int rc;
|
||||
bignum_CTX ctx=BN_CTX_new();
|
||||
enter_function();
|
||||
if (buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_INIT) < 0) {
|
||||
goto error;
|
||||
bignum_CTX ctx = BN_CTX_new();
|
||||
|
||||
rc = buffer_add_u8(session->out_buffer, SSH2_MSG_KEX_ECDH_INIT);
|
||||
if (rc < 0) {
|
||||
BN_CTX_free(ctx);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
key = EC_KEY_new_by_curve_name(NISTP256);
|
||||
if (key == NULL) {
|
||||
BN_CTX_free(ctx);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
group = EC_KEY_get0_group(key);
|
||||
|
||||
EC_KEY_generate_key(key);
|
||||
|
||||
pubkey=EC_KEY_get0_public_key(key);
|
||||
len = EC_POINT_point2oct(group,pubkey,POINT_CONVERSION_UNCOMPRESSED,
|
||||
NULL,0,ctx);
|
||||
client_pubkey=ssh_string_new(len);
|
||||
|
||||
client_pubkey = ssh_string_new(len);
|
||||
if (client_pubkey == NULL) {
|
||||
BN_CTX_free(ctx);
|
||||
EC_KEY_free(key);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
EC_POINT_point2oct(group,pubkey,POINT_CONVERSION_UNCOMPRESSED,
|
||||
ssh_string_data(client_pubkey),len,ctx);
|
||||
buffer_add_ssh_string(session->out_buffer,client_pubkey);
|
||||
BN_CTX_free(ctx);
|
||||
|
||||
rc = buffer_add_ssh_string(session->out_buffer,client_pubkey);
|
||||
if (rc < 0) {
|
||||
EC_KEY_free(key);
|
||||
ssh_string_free(client_pubkey);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
session->next_crypto->ecdh_privkey = key;
|
||||
session->next_crypto->ecdh_client_pubkey = client_pubkey;
|
||||
|
||||
rc = packet_send(session);
|
||||
leave_function();
|
||||
|
||||
return rc;
|
||||
error:
|
||||
leave_function();
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
static void ecdh_import_pubkey(ssh_session session, ssh_string pubkey_string) {
|
||||
@ -180,9 +200,9 @@ error:
|
||||
|
||||
int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet){
|
||||
/* ECDH keys */
|
||||
ssh_string q_c_string = NULL;
|
||||
ssh_string q_s_string = NULL;
|
||||
EC_KEY *ecdh_key=NULL;
|
||||
ssh_string q_c_string;
|
||||
ssh_string q_s_string;
|
||||
EC_KEY *ecdh_key;
|
||||
const EC_GROUP *group;
|
||||
const EC_POINT *ecdh_pubkey;
|
||||
bignum_CTX ctx;
|
||||
@ -192,14 +212,11 @@ int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet){
|
||||
int len;
|
||||
int rc;
|
||||
|
||||
enter_function();
|
||||
|
||||
/* Extract the client pubkey from the init packet */
|
||||
|
||||
q_c_string = buffer_get_ssh_string(packet);
|
||||
if (q_c_string == NULL) {
|
||||
ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet");
|
||||
goto error;
|
||||
ssh_set_error(session,SSH_FATAL, "No Q_C ECC point in packet");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
session->next_crypto->ecdh_client_pubkey = q_c_string;
|
||||
|
||||
@ -207,45 +224,94 @@ int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet){
|
||||
|
||||
ctx = BN_CTX_new();
|
||||
ecdh_key = EC_KEY_new_by_curve_name(NISTP256);
|
||||
if (ecdh_key == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
BN_CTX_free(ctx);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
group = EC_KEY_get0_group(ecdh_key);
|
||||
EC_KEY_generate_key(ecdh_key);
|
||||
ecdh_pubkey=EC_KEY_get0_public_key(ecdh_key);
|
||||
len = EC_POINT_point2oct(group,ecdh_pubkey,POINT_CONVERSION_UNCOMPRESSED,
|
||||
NULL,0,ctx);
|
||||
q_s_string=ssh_string_new(len);
|
||||
|
||||
EC_POINT_point2oct(group,ecdh_pubkey,POINT_CONVERSION_UNCOMPRESSED,
|
||||
ssh_string_data(q_s_string),len,ctx);
|
||||
ecdh_pubkey = EC_KEY_get0_public_key(ecdh_key);
|
||||
len = EC_POINT_point2oct(group,
|
||||
ecdh_pubkey,
|
||||
POINT_CONVERSION_UNCOMPRESSED,
|
||||
NULL,
|
||||
0,
|
||||
ctx);
|
||||
|
||||
q_s_string = ssh_string_new(len);
|
||||
if (q_s_string == NULL) {
|
||||
EC_KEY_free(ecdh_key);
|
||||
BN_CTX_free(ctx);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
EC_POINT_point2oct(group,
|
||||
ecdh_pubkey,
|
||||
POINT_CONVERSION_UNCOMPRESSED,
|
||||
ssh_string_data(q_s_string),
|
||||
len,
|
||||
ctx);
|
||||
BN_CTX_free(ctx);
|
||||
|
||||
session->next_crypto->ecdh_privkey = ecdh_key;
|
||||
session->next_crypto->ecdh_server_pubkey = q_s_string;
|
||||
|
||||
buffer_add_u8(session->out_buffer, SSH2_MSG_KEXDH_REPLY);
|
||||
/* build k and session_id */
|
||||
if (ecdh_build_k(session) < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Cannot build k number");
|
||||
goto error;
|
||||
rc = buffer_add_u8(session->out_buffer, SSH2_MSG_KEXDH_REPLY);
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
if (ssh_get_key_params(session, &privkey) == SSH_ERROR)
|
||||
goto error;
|
||||
if (make_sessionid(session) != SSH_OK) {
|
||||
ssh_set_error(session, SSH_FATAL, "Could not create a session id");
|
||||
goto error;
|
||||
|
||||
/* build k and session_id */
|
||||
rc = ecdh_build_k(session);
|
||||
if (rc < 0) {
|
||||
ssh_set_error(session, SSH_FATAL, "Cannot build k number");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* privkey is not allocated */
|
||||
rc = ssh_get_key_params(session, &privkey);
|
||||
if (rc == SSH_ERROR) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = make_sessionid(session);
|
||||
if (rc != SSH_OK) {
|
||||
ssh_set_error(session, SSH_FATAL, "Could not create a session id");
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* add host's public key */
|
||||
buffer_add_ssh_string(session->out_buffer, session->next_crypto->server_pubkey);
|
||||
rc = buffer_add_ssh_string(session->out_buffer,
|
||||
session->next_crypto->server_pubkey);
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* add ecdh public key */
|
||||
buffer_add_ssh_string(session->out_buffer,q_s_string);
|
||||
rc = buffer_add_ssh_string(session->out_buffer, q_s_string);
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
/* add signature blob */
|
||||
sig_blob = ssh_srv_pki_do_sign_sessionid(session, privkey);
|
||||
if (sig_blob == NULL) {
|
||||
ssh_set_error(session, SSH_FATAL, "Could not sign the session id");
|
||||
goto error;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
buffer_add_ssh_string(session->out_buffer, sig_blob);
|
||||
|
||||
rc = buffer_add_ssh_string(session->out_buffer, sig_blob);
|
||||
ssh_string_free(sig_blob);
|
||||
if (rc < 0) {
|
||||
ssh_set_error_oom(session);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* Free private keys as they should not be readable after this point */
|
||||
if (session->srv.rsa_key) {
|
||||
ssh_key_free(session->srv.rsa_key);
|
||||
@ -258,19 +324,21 @@ int ssh_server_ecdh_init(ssh_session session, ssh_buffer packet){
|
||||
|
||||
ssh_log(session,SSH_LOG_PROTOCOL, "SSH_MSG_KEXDH_REPLY sent");
|
||||
rc = packet_send(session);
|
||||
if (rc == SSH_ERROR)
|
||||
goto error;
|
||||
if (rc == SSH_ERROR) {
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* Send the MSG_NEWKEYS */
|
||||
if (buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS) < 0) {
|
||||
goto error;
|
||||
rc = buffer_add_u8(session->out_buffer, SSH2_MSG_NEWKEYS);
|
||||
if (rc < 0) {
|
||||
return SSH_ERROR;;
|
||||
}
|
||||
session->dh_handshake_state=DH_STATE_NEWKEYS_SENT;
|
||||
rc=packet_send(session);
|
||||
|
||||
session->dh_handshake_state = DH_STATE_NEWKEYS_SENT;
|
||||
rc = packet_send(session);
|
||||
ssh_log(session, SSH_LOG_PROTOCOL, "SSH_MSG_NEWKEYS sent");
|
||||
|
||||
return rc;
|
||||
error:
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
#endif /* WITH_SERVER */
|
||||
|
@ -460,6 +460,7 @@ int ssh_send_kex(ssh_session session, int server_kex) {
|
||||
goto error;
|
||||
}
|
||||
ssh_string_free(str);
|
||||
str = NULL;
|
||||
}
|
||||
|
||||
if (buffer_add_u8(session->out_buffer, 0) < 0) {
|
||||
|
@ -47,6 +47,9 @@ static ssh_string make_rsa1_string(ssh_string e, ssh_string n){
|
||||
|
||||
buffer = ssh_buffer_new();
|
||||
rsa = ssh_string_from_char("ssh-rsa1");
|
||||
if (rsa == NULL) {
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (buffer_add_ssh_string(buffer, rsa) < 0) {
|
||||
goto error;
|
||||
@ -375,7 +378,7 @@ SSH_PACKET_CALLBACK(ssh_packet_publickey1){
|
||||
goto error;
|
||||
}
|
||||
hostkey = make_rsa1_string(host_exp,host_mod);
|
||||
if (serverkey == NULL) {
|
||||
if (hostkey == NULL) {
|
||||
goto error;
|
||||
}
|
||||
if (build_session_id1(session, server_mod, host_mod) < 0) {
|
||||
|
@ -133,7 +133,7 @@ static char **ssh_get_knownhost_line(ssh_session session, FILE **file,
|
||||
*ptr = '\0';
|
||||
}
|
||||
|
||||
if (!buffer[0] || buffer[0] == '#') {
|
||||
if (buffer[0] == '\0' || buffer[0] == '#') {
|
||||
continue; /* skip empty lines */
|
||||
}
|
||||
|
||||
|
@ -135,7 +135,9 @@ void ssh_message_queue(ssh_session session, ssh_message message){
|
||||
}
|
||||
session->ssh_message_list = ssh_list_new();
|
||||
}
|
||||
ssh_list_append(session->ssh_message_list, message);
|
||||
if (session->ssh_message_list != NULL) {
|
||||
ssh_list_append(session->ssh_message_list, message);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -1252,6 +1254,7 @@ SSH_PACKET_CALLBACK(ssh_packet_global_request){
|
||||
|
||||
msg = ssh_message_new(session);
|
||||
if (msg == NULL) {
|
||||
ssh_string_free_char(request);
|
||||
return SSH_PACKET_NOT_USED;
|
||||
}
|
||||
msg->type = SSH_REQUEST_GLOBAL;
|
||||
|
@ -187,6 +187,7 @@ int ssh_packet_socket_callback(const void *data, size_t receivedlen, void *user)
|
||||
/* saves the status of the current operations */
|
||||
session->in_packet.len = len;
|
||||
session->packet_state = PACKET_STATE_SIZEREAD;
|
||||
/* FALL TROUGH */
|
||||
case PACKET_STATE_SIZEREAD:
|
||||
len = session->in_packet.len;
|
||||
to_be_read = len - blocksize + sizeof(uint32_t) + current_macsize;
|
||||
@ -305,10 +306,12 @@ void ssh_packet_register_socket_callback(ssh_session session, ssh_socket s){
|
||||
* @brief sets the callbacks for the packet layer
|
||||
*/
|
||||
void ssh_packet_set_callbacks(ssh_session session, ssh_packet_callbacks callbacks){
|
||||
if(session->packet_callbacks == NULL){
|
||||
session->packet_callbacks = ssh_list_new();
|
||||
}
|
||||
ssh_list_append(session->packet_callbacks, callbacks);
|
||||
if(session->packet_callbacks == NULL){
|
||||
session->packet_callbacks = ssh_list_new();
|
||||
}
|
||||
if (session->packet_callbacks != NULL) {
|
||||
ssh_list_append(session->packet_callbacks, callbacks);
|
||||
}
|
||||
}
|
||||
|
||||
/** @internal
|
||||
@ -526,6 +529,3 @@ int packet_send(ssh_session session) {
|
||||
#endif
|
||||
return packet_send2(session);
|
||||
}
|
||||
|
||||
|
||||
/* vim: set ts=2 sw=2 et cindent: */
|
||||
|
@ -144,6 +144,7 @@ int ssh_packet_socket_callback1(const void *data, size_t receivedlen, void *user
|
||||
|
||||
session->in_packet.len = len;
|
||||
session->packet_state = PACKET_STATE_SIZEREAD;
|
||||
/* FALL THROUGH */
|
||||
case PACKET_STATE_SIZEREAD:
|
||||
len = session->in_packet.len;
|
||||
/* SSH-1 has a fixed padding lenght */
|
||||
@ -158,7 +159,6 @@ int ssh_packet_socket_callback1(const void *data, size_t receivedlen, void *user
|
||||
packet = (char *)data + processed;
|
||||
|
||||
if (buffer_add_data(session->in_buffer,packet,to_be_read) < 0) {
|
||||
SAFE_FREE(packet);
|
||||
goto error;
|
||||
}
|
||||
processed += to_be_read;
|
||||
|
@ -421,8 +421,16 @@ int ssh_pki_import_privkey_file(const char *filename,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = stat(filename, &sb);
|
||||
file = fopen(filename, "rb");
|
||||
if (file == NULL) {
|
||||
ssh_pki_log("Error opening %s: %s",
|
||||
filename, strerror(errno));
|
||||
return SSH_EOF;
|
||||
}
|
||||
|
||||
rc = fstat(fileno(file), &sb);
|
||||
if (rc < 0) {
|
||||
fclose(file);
|
||||
ssh_pki_log("Error getting stat of %s: %s",
|
||||
filename, strerror(errno));
|
||||
switch (errno) {
|
||||
@ -434,11 +442,10 @@ int ssh_pki_import_privkey_file(const char *filename,
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
file = fopen(filename, "rb");
|
||||
if (file == NULL) {
|
||||
ssh_pki_log("Error opening %s: %s",
|
||||
filename, strerror(errno));
|
||||
return SSH_EOF;
|
||||
if (sb.st_size > MAX_PRIVKEY_SIZE) {
|
||||
ssh_pki_log("Private key is bigger than 4M.");
|
||||
fclose(file);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
key_buf = malloc(sb.st_size + 1);
|
||||
@ -804,8 +811,16 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey)
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
rc = stat(filename, &sb);
|
||||
file = fopen(filename, "r");
|
||||
if (file == NULL) {
|
||||
ssh_pki_log("Error opening %s: %s",
|
||||
filename, strerror(errno));
|
||||
return SSH_EOF;
|
||||
}
|
||||
|
||||
rc = fstat(fileno(file), &sb);
|
||||
if (rc < 0) {
|
||||
fclose(file);
|
||||
ssh_pki_log("Error gettint stat of %s: %s",
|
||||
filename, strerror(errno));
|
||||
switch (errno) {
|
||||
@ -817,16 +832,10 @@ int ssh_pki_import_pubkey_file(const char *filename, ssh_key *pkey)
|
||||
}
|
||||
|
||||
if (sb.st_size > MAX_PUBKEY_SIZE) {
|
||||
fclose(file);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
file = fopen(filename, "r");
|
||||
if (file == NULL) {
|
||||
ssh_pki_log("Error opening %s: %s",
|
||||
filename, strerror(errno));
|
||||
return SSH_EOF;
|
||||
}
|
||||
|
||||
key_buf = malloc(sb.st_size + 1);
|
||||
if (key_buf == NULL) {
|
||||
fclose(file);
|
||||
|
@ -411,8 +411,10 @@ int pki_key_generate_ecdsa(ssh_key key, int parameter) {
|
||||
switch (parameter) {
|
||||
case 384:
|
||||
nid = NID_secp384r1;
|
||||
break;
|
||||
case 512:
|
||||
nid = NID_secp521r1;
|
||||
break;
|
||||
case 256:
|
||||
default:
|
||||
nid = NID_X9_62_prime256v1;
|
||||
@ -850,6 +852,7 @@ ssh_string pki_publickey_to_blob(const ssh_key key)
|
||||
e = make_ecpoint_string(EC_KEY_get0_group(key->ecdsa),
|
||||
EC_KEY_get0_public_key(key->ecdsa));
|
||||
if (e == NULL) {
|
||||
ssh_buffer_free(buffer);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
|
@ -927,7 +927,7 @@ int ssh_message_auth_interactive_request(ssh_message msg, const char *name,
|
||||
r = buffer_add_ssh_string(msg->session->out_buffer, tmp);
|
||||
ssh_string_free(tmp);
|
||||
if (r < 0) {
|
||||
goto error;
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
/* echo[i] */
|
||||
@ -1003,9 +1003,6 @@ int ssh_message_auth_interactive_request(ssh_message msg, const char *name,
|
||||
}
|
||||
|
||||
return r;
|
||||
error:
|
||||
if(tmp) ssh_string_free(tmp);
|
||||
return SSH_ERROR;
|
||||
}
|
||||
|
||||
int ssh_message_auth_reply_success(ssh_message msg, int partial) {
|
||||
@ -1200,6 +1197,41 @@ int ssh_execute_message_callbacks(ssh_session session){
|
||||
return SSH_OK;
|
||||
}
|
||||
|
||||
int ssh_send_keepalive(ssh_session session)
|
||||
{
|
||||
/* TODO check the reply and all that */
|
||||
struct ssh_string_struct *req;
|
||||
int reply = 1;
|
||||
int rc = SSH_ERROR;
|
||||
|
||||
enter_function();
|
||||
req = ssh_string_from_char("keepalive@openssh.com");
|
||||
if (req == NULL) {
|
||||
ssh_set_error_oom(session);
|
||||
goto out;
|
||||
}
|
||||
|
||||
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) {
|
||||
ssh_set_error_oom(session);
|
||||
goto out;
|
||||
}
|
||||
|
||||
if (packet_send(session) == SSH_ERROR)
|
||||
goto out;
|
||||
|
||||
ssh_handle_packets(session, 0);
|
||||
|
||||
ssh_log(session, SSH_LOG_PACKET, "Sent a keepalive");
|
||||
rc = SSH_OK;
|
||||
|
||||
out:
|
||||
ssh_string_free(req);
|
||||
leave_function();
|
||||
return rc;
|
||||
}
|
||||
|
||||
/** @} */
|
||||
|
||||
/* vim: set ts=4 sw=4 et cindent: */
|
||||
|
@ -230,7 +230,10 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
|
||||
/* Check if we are in a connecting state */
|
||||
if(s->state==SSH_SOCKET_CONNECTING){
|
||||
s->state=SSH_SOCKET_ERROR;
|
||||
getsockopt(fd,SOL_SOCKET,SO_ERROR,(char *)&err,&errlen);
|
||||
r = getsockopt(fd, SOL_SOCKET, SO_ERROR, (char *)&err, &errlen);
|
||||
if (r < 0) {
|
||||
err = errno;
|
||||
}
|
||||
s->last_errno=err;
|
||||
ssh_socket_close(s);
|
||||
if(s->callbacks && s->callbacks->connected)
|
||||
@ -305,7 +308,10 @@ int ssh_socket_pollcallback(struct ssh_poll_handle_struct *p, socket_t fd, int r
|
||||
ssh_log(s->session,SSH_LOG_PACKET,"Received POLLOUT in connecting state");
|
||||
s->state = SSH_SOCKET_CONNECTED;
|
||||
ssh_poll_set_events(p,POLLOUT | POLLIN);
|
||||
ssh_socket_set_blocking(ssh_socket_get_fd_in(s));
|
||||
r = ssh_socket_set_blocking(ssh_socket_get_fd_in(s));
|
||||
if (r < 0) {
|
||||
return -1;
|
||||
}
|
||||
if(s->callbacks && s->callbacks->connected)
|
||||
s->callbacks->connected(SSH_SOCKET_CONNECTED_OK,0,s->callbacks->userdata);
|
||||
return 0;
|
||||
@ -711,23 +717,23 @@ int ssh_socket_get_status(ssh_socket s) {
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
void ssh_socket_set_nonblocking(socket_t fd) {
|
||||
int ssh_socket_set_nonblocking(socket_t fd) {
|
||||
u_long nonblocking = 1;
|
||||
ioctlsocket(fd, FIONBIO, &nonblocking);
|
||||
return ioctlsocket(fd, FIONBIO, &nonblocking);
|
||||
}
|
||||
|
||||
void ssh_socket_set_blocking(socket_t fd) {
|
||||
int ssh_socket_set_blocking(socket_t fd) {
|
||||
u_long nonblocking = 0;
|
||||
ioctlsocket(fd, FIONBIO, &nonblocking);
|
||||
return ioctlsocket(fd, FIONBIO, &nonblocking);
|
||||
}
|
||||
|
||||
#else /* _WIN32 */
|
||||
void ssh_socket_set_nonblocking(socket_t fd) {
|
||||
fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||
int ssh_socket_set_nonblocking(socket_t fd) {
|
||||
return fcntl(fd, F_SETFL, O_NONBLOCK);
|
||||
}
|
||||
|
||||
void ssh_socket_set_blocking(socket_t fd) {
|
||||
fcntl(fd, F_SETFL, 0);
|
||||
int ssh_socket_set_blocking(socket_t fd) {
|
||||
return fcntl(fd, F_SETFL, 0);
|
||||
}
|
||||
#endif /* _WIN32 */
|
||||
|
||||
|
@ -83,7 +83,8 @@ static void torture_channel_read_error(void **state) {
|
||||
assert_true(rc == SSH_OK);
|
||||
|
||||
/* send crap and for server to send us a disconnect */
|
||||
write(ssh_get_fd(session),"AAAA", 4);
|
||||
rc = write(ssh_get_fd(session),"AAAA", 4);
|
||||
assert_int_equal(rc, 4);
|
||||
|
||||
for (i=0;i<20;++i){
|
||||
rc = ssh_channel_read(channel,buffer,sizeof(buffer),0);
|
||||
|
@ -110,6 +110,7 @@ int torture_rmdirs(const char *path) {
|
||||
len = strlen(path) + strlen(dp->d_name) + 2;
|
||||
fname = malloc(len);
|
||||
if (fname == NULL) {
|
||||
closedir(d);
|
||||
return -1;
|
||||
}
|
||||
snprintf(fname, len, "%s/%s", path, dp->d_name);
|
||||
|
@ -66,22 +66,25 @@ static void torture_buffer_prepend(void **state) {
|
||||
buffer_add_data(buffer,"abcdef",6);
|
||||
buffer_prepend_data(buffer,"xyz",3);
|
||||
assert_int_equal(buffer_get_rest_len(buffer),9);
|
||||
assert_int_equal(memcmp(buffer_get_rest(buffer), "xyzabcdef", 9), 0);
|
||||
// Now remove 4 bytes and see if we can replace them
|
||||
assert_memory_equal(buffer_get_rest(buffer), "xyzabcdef", 9);
|
||||
|
||||
/* Now remove 4 bytes and see if we can replace them */
|
||||
buffer_get_u32(buffer,&v);
|
||||
assert_int_equal(buffer_get_rest_len(buffer),5);
|
||||
assert_int_equal(memcmp(buffer_get_rest(buffer), "bcdef", 5), 0);
|
||||
assert_memory_equal(buffer_get_rest(buffer), "bcdef", 5);
|
||||
|
||||
buffer_prepend_data(buffer,"aris",4);
|
||||
assert_int_equal(buffer_get_rest_len(buffer),9);
|
||||
assert_int_equal(memcmp(buffer_get_rest(buffer), "arisbcdef", 9), 0);
|
||||
assert_memory_equal(buffer_get_rest(buffer), "arisbcdef", 9);
|
||||
|
||||
/* same thing but we add 5 bytes now */
|
||||
buffer_get_u32(buffer,&v);
|
||||
assert_int_equal(buffer_get_rest_len(buffer),5);
|
||||
assert_int_equal(memcmp(buffer_get_rest(buffer), "bcdef", 5), 0);
|
||||
assert_memory_equal(buffer_get_rest(buffer), "bcdef", 5);
|
||||
|
||||
buffer_prepend_data(buffer,"12345",5);
|
||||
assert_int_equal(buffer_get_rest_len(buffer),10);
|
||||
assert_int_equal(memcmp(buffer_get_rest(buffer), "12345bcdef", 10), 0);
|
||||
|
||||
assert_memory_equal(buffer_get_rest(buffer), "12345bcdef", 10);
|
||||
}
|
||||
|
||||
/*
|
||||
@ -89,7 +92,7 @@ static void torture_buffer_prepend(void **state) {
|
||||
*/
|
||||
static void torture_buffer_get_ssh_string(void **state) {
|
||||
ssh_buffer buffer;
|
||||
int i,j,k,l;
|
||||
int i,j,k,l, rc;
|
||||
/* some values that can go wrong */
|
||||
uint32_t values[] = {0xffffffff, 0xfffffffe, 0xfffffffc, 0xffffff00,
|
||||
0x80000000, 0x80000004, 0x7fffffff};
|
||||
@ -100,13 +103,18 @@ static void torture_buffer_get_ssh_string(void **state) {
|
||||
for(j=0; j< (int)sizeof(data);++j){
|
||||
for(k=1;k<5;++k){
|
||||
buffer=buffer_new();
|
||||
assert_non_null(buffer);
|
||||
|
||||
for(l=0;l<k;++l){
|
||||
buffer_add_u32(buffer,htonl(values[i]));
|
||||
rc = buffer_add_u32(buffer,htonl(values[i]));
|
||||
assert_int_equal(rc, 0);
|
||||
}
|
||||
buffer_add_data(buffer,data,j);
|
||||
rc = buffer_add_data(buffer,data,j);
|
||||
assert_int_equal(rc, 0);
|
||||
for(l=0;l<k;++l){
|
||||
ssh_string str = buffer_get_ssh_string(buffer);
|
||||
assert_true(str==NULL);
|
||||
assert_null(str);
|
||||
ssh_string_free(str);
|
||||
}
|
||||
buffer_free(buffer);
|
||||
}
|
||||
|
@ -85,12 +85,14 @@ static char *read_file(const char *filename) {
|
||||
char *key;
|
||||
int fd;
|
||||
int size;
|
||||
int rc;
|
||||
struct stat buf;
|
||||
|
||||
assert_true(filename != NULL);
|
||||
assert_true(*filename != '\0');
|
||||
|
||||
stat(filename, &buf);
|
||||
rc = stat(filename, &buf);
|
||||
assert_int_equal(rc, 0);
|
||||
|
||||
key = malloc(buf.st_size + 1);
|
||||
assert_true(key != NULL);
|
||||
|
Loading…
Reference in New Issue
Block a user