Skip to content
GitLab
Explore
Sign in
Register
Primary navigation
Search or go to…
Project
Synchronet
Manage
Activity
Members
Labels
Plan
Issues
Issue boards
Milestones
Wiki
Code
Merge requests
Repository
Branches
Commits
Tags
Repository graph
Compare revisions
Snippets
Build
Pipelines
Jobs
Pipeline schedules
Artifacts
Deploy
Releases
Package registry
Container Registry
Model registry
Operate
Environments
Terraform modules
Monitor
Incidents
Analyze
Value stream analytics
Contributor analytics
CI/CD analytics
Repository analytics
Model experiments
Help
Help
Support
GitLab documentation
Compare GitLab plans
Community forum
Contribute to GitLab
Provide feedback
Keyboard shortcuts
?
Snippets
Groups
Projects
Show more breadcrumbs
Main
Synchronet
Commits
02be7ecc
Commit
02be7ecc
authored
3 months ago
by
Deucе
Browse files
Options
Downloads
Patches
Plain Diff
Eliminate egregious and unneeded allocations.
parent
76b6856b
No related branches found
Branches containing commit
No related tags found
Tags containing commit
No related merge requests found
Pipeline
#7349
passed
3 months ago
Stage: build
Stage: test
Stage: cleanup
Changes
4
Pipelines
1
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
src/ssh/client.c
+6
-2
6 additions, 2 deletions
src/ssh/client.c
src/ssh/ssh-trans.c
+107
-274
107 additions, 274 deletions
src/ssh/ssh-trans.c
src/ssh/ssh-trans.h
+74
-7
74 additions, 7 deletions
src/ssh/ssh-trans.h
src/ssh/ssh.h
+12
-11
12 additions, 11 deletions
src/ssh/ssh.h
with
199 additions
and
294 deletions
src/ssh/client.c
+
6
−
2
View file @
02be7ecc
...
...
@@ -129,8 +129,9 @@ rxline(uint8_t *buf, size_t bufsz, size_t *bytes_received, atomic_bool *terminat
{
size_t
pos
=
0
;
bool
lastcr
=
false
;
int
ret
=
0
;
for
(;;
)
{
while
(
!
(
*
terminate
)
)
{
int
res
=
rx
(
&
buf
[
pos
],
1
,
terminate
,
cbdata
);
if
(
res
<
0
)
return
res
;
...
...
@@ -138,11 +139,14 @@ rxline(uint8_t *buf, size_t bufsz, size_t *bytes_received, atomic_bool *terminat
lastcr
=
true
;
if
(
buf
[
pos
]
==
'\n'
&&
lastcr
)
{
*
bytes_received
=
pos
+
1
;
return
0
;
return
ret
;
}
if
(
pos
+
1
<
bufsz
)
pos
++
;
else
ret
=
DEUCE_SSH_ERROR_TOOLONG
;
}
return
DEUCE_SSH_ERROR_TERMINATED
;
}
static
int
...
...
This diff is collapsed.
Click to expand it.
src/ssh/ssh-trans.c
+
107
−
274
View file @
02be7ecc
...
...
@@ -16,49 +16,34 @@ typedef struct deuce_ssh_transport_global_config {
int
(
*
extra_line_cb
)(
uint8_t
*
buf
,
size_t
bufsz
,
void
*
cbdata
);
size_t
kex_entries
;
char
**
kex_name
;
uint32_t
*
kex_flags
;
deuce_ssh_kex_handler_t
*
kex_handler
;
deuce_ssh_kex_cleanup_t
*
kex_cleanup
;
deuce_ssh_kex_t
kex_head
;
deuce_ssh_kex_t
kex_tail
;
size_t
key_algo_entries
;
char
**
key_algo_name
;
uint32_t
*
key_algo_flags
;
deuce_ssh_key_algo_sign_t
*
key_algo_sign
;
deuce_ssh_key_algo_haskey_t
*
key_algo_haskey
;
deuce_ssh_key_algo_cleanup_t
*
key_algo_cleanup
;
deuce_ssh_key_algo_t
key_algo_head
;
deuce_ssh_key_algo_t
key_algo_tail
;
size_t
enc_entries
;
char
**
enc_name
;
uint32_t
*
enc_flags
;
uint16_t
*
enc_blocksize
;
uint16_t
*
enc_key_size
;
deuce_ssh_enc_encrypt_t
*
enc_encrypt
;
deuce_ssh_enc_decrypt_t
*
enc_decrypt
;
deuce_ssh_enc_cleanup_t
*
enc_cleanup
;
deuce_ssh_enc_t
enc_head
;
deuce_ssh_enc_t
enc_tail
;
size_t
mac_entries
;
char
**
mac_name
;
uint16_t
*
mac_digest_size
;
uint16_t
*
mac_key_size
;
deuce_ssh_mac_generate_t
*
mac_generate
;
deuce_ssh_mac_cleanup_t
*
mac_cleanup
;
deuce_ssh_mac_t
mac_head
;
deuce_ssh_mac_t
mac_tail
;
size_t
comp_entries
;
char
**
comp_name
;
uint32_t
*
comp_flags
;
uint16_t
*
comp_blocksize
;
uint16_t
*
comp_key_size
;
deuce_ssh_comp_compress_t
*
comp_compress
;
deuce_ssh_comp_uncompress_t
*
comp_uncompress
;
deuce_ssh_comp_cleanup_t
*
comp_cleanup
;
deuce_ssh_comp_t
comp_head
;
deuce_ssh_comp_t
comp_tail
;
size_t
lang_entries
;
char
**
lang_name
;
deuce_ssh_language_t
lang_head
;
deuce_ssh_language_t
lang_tail
;
}
*
deuce_ssh_transport_global_config_t
;
static
const
char
*
const
sw_ver
=
"DeuceSSH-0.0"
;
static
struct
deuce_ssh_transport_global_config
gconf
;
static
uint8_t
tx_packet
[
SSH_TOTAL_BPP_PACKET_SIZE_MAX
];
static
uint8_t
rx_packet
[
SSH_TOTAL_BPP_PACKET_SIZE_MAX
];
static
inline
bool
has_nulls
(
uint8_t
*
buf
,
size_t
buflen
)
...
...
@@ -89,56 +74,35 @@ is_20(uint8_t *buf, size_t buflen)
return
(
buf
[
4
]
==
'2'
&&
buf
[
5
]
==
'.'
&&
buf
[
6
]
==
'0'
&&
buf
[
7
]
==
'-'
);
}
static
inline
void
*
memdup
(
void
*
buf
,
size_t
bufsz
)
{
void
*
ret
=
malloc
(
bufsz
);
if
(
ret
!=
NULL
)
memcpy
(
ret
,
buf
,
bufsz
);
return
ret
;
}
static
int
version_ex
(
deuce_ssh_session_t
sess
)
{
size_t
received
;
int
res
;
uint8_t
line
[
256
];
while
(
!
sess
->
terminate
)
{
res
=
gconf
.
rx_line
(
line
,
sizeof
(
line
)
-
1
,
&
received
,
&
sess
->
terminate
,
sess
->
rx_line_cbdata
);
res
=
gconf
.
rx_line
(
rx_packet
,
sizeof
(
rx_packet
)
-
1
,
&
received
,
&
sess
->
terminate
,
sess
->
rx_line_cbdata
);
if
(
res
<
0
)
{
sess
->
terminate
=
true
;
return
res
;
}
if
(
is_version_line
(
line
,
received
))
{
if
(
has_nulls
(
line
,
received
)
||
missing_crlf
(
line
,
received
)
||
!
is_20
(
line
,
received
))
{
if
(
is_version_line
(
rx_packet
,
received
))
{
if
(
received
>
255
||
has_nulls
(
rx_packet
,
received
)
||
missing_crlf
(
rx_packet
,
received
)
||
!
is_20
(
rx_packet
,
received
))
{
sess
->
terminate
=
true
;
return
DEUCE_SSH_ERROR_INVALID
;
}
uint8_t
*
sp
=
memchr
(
line
,
' '
,
received
);
char
*
c
=
NULL
;
char
*
v
;
if
(
sp
!=
NULL
)
{
c
=
memdup
(
&
sp
[
1
],
received
-
3
-
(
sp
-
line
));
v
=
memdup
(
&
line
[
8
],
(
sp
-
line
)
-
9
);
}
else
{
v
=
memdup
(
&
line
[
8
],
received
-
10
);
}
res
=
mtx_lock
(
&
sess
->
mtx
);
free
(
sess
->
remote_software_version
);
free
(
sess
->
remote_version_comment
);
assert
(
res
==
thrd_success
);
sess
->
remote_software_version
=
v
;
sess
->
remote_version_comment
=
c
;
sess
->
remote_software_id_string_sz
=
received
-
2
;
memcpy
(
sess
->
remote_software_id_string
,
rx_packet
,
sess
->
remote_software_id_string_sz
);
sess
->
remote_software_id_string
[
sess
->
remote_software_id_string_sz
]
=
0
;
res
=
mtx_unlock
(
&
sess
->
mtx
);
assert
(
res
==
thrd_success
);
return
0
;
}
if
(
gconf
.
extra_line_cb
)
{
line
[
received
]
=
0
;
res
=
gconf
.
extra_line_cb
(
line
,
received
,
sess
->
extra_line_cbdata
);
rx_packet
[
received
]
=
0
;
res
=
gconf
.
extra_line_cb
(
rx_packet
,
received
,
sess
->
extra_line_cbdata
);
if
(
res
<
0
)
{
sess
->
terminate
=
true
;
return
res
;
...
...
@@ -161,7 +125,6 @@ rx_thread(void *arg)
while
(
!
sess
->
terminate
)
{
// Read enough to get the length
// Allocate space for packet
// Read the rest of the packet
// Decrypt
// Decompress
...
...
@@ -175,29 +138,31 @@ tx_handshake(void *arg)
{
deuce_ssh_session_t
sess
=
arg
;
int
res
;
uint8_t
line
[
255
];
size_t
sz
=
0
;
/* Handshake */
memcpy
(
line
,
"SSH-2.0-"
,
8
);
memcpy
(
tx_packet
,
"SSH-2.0-"
,
8
);
sz
+=
8
;
size_t
asz
=
strlen
(
gconf
.
software_version
);
if
(
sz
+
asz
+
2
>
255
)
return
DEUCE_SSH_ERROR_TOOLONG
;
memcpy
(
&
line
[
sz
],
gconf
.
software_version
,
asz
);
memcpy
(
&
tx_packet
[
sz
],
gconf
.
software_version
,
asz
);
sz
+=
asz
;
if
(
gconf
.
version_comment
!=
NULL
)
{
memcpy
(
&
line
[
sz
],
" "
,
1
);
memcpy
(
&
tx_packet
[
sz
],
" "
,
1
);
sz
+=
1
;
asz
=
strlen
(
gconf
.
version_comment
);
if
(
sz
+
asz
+
2
>
255
)
return
DEUCE_SSH_ERROR_TOOLONG
;
memcpy
(
&
line
[
sz
],
gconf
.
version_comment
,
asz
);
memcpy
(
&
tx_packet
[
sz
],
gconf
.
version_comment
,
asz
);
sz
+=
asz
;
}
memcpy
(
&
line
[
sz
],
"
\r\n
"
,
2
);
memcpy
(
sess
->
trans
->
id_str
,
tx_packet
,
sz
);
sess
->
trans
->
id_str_sz
=
sz
;
sess
->
trans
->
id_str
[
sz
]
=
0
;
memcpy
(
&
tx_packet
[
sz
],
"
\r\n
"
,
2
);
sz
+=
2
;
res
=
gconf
.
tx
(
line
,
sz
,
&
sess
->
terminate
,
sess
->
tx_cbdata
);
res
=
gconf
.
tx
(
tx_packet
,
sz
,
&
sess
->
terminate
,
sess
->
tx_cbdata
);
if
(
res
<
0
)
{
sess
->
terminate
=
true
;
return
res
;
...
...
@@ -208,35 +173,34 @@ tx_handshake(void *arg)
void
deuce_ssh_transport_cleanup
(
deuce_ssh_session_t
sess
)
{
if
(
sess
->
trans
->
kex_selected
!=
SIZE_MAX
)
{
if
(
gconf
.
kex_cleanup
[
sess
->
trans
->
kex_selected
]
!=
NULL
)
gconf
.
kex_cleanup
[
sess
->
trans
->
kex_selected
]
(
sess
);
sess
->
trans
->
kex_selected
=
SIZE_MAX
;
if
(
sess
->
trans
->
kex_selected
)
{
if
(
sess
->
trans
->
kex_selected
->
cleanup
!=
NULL
)
sess
->
trans
->
kex_selected
->
cleanup
(
sess
);
sess
->
trans
->
kex_selected
=
NULL
;
}
if
(
sess
->
trans
->
key_algo_selected
!=
SIZE_MAX
)
{
if
(
gconf
.
key_algo_cleanup
[
sess
->
trans
->
key_algo_selected
]
!=
NULL
)
gconf
.
key_algo_cleanup
[
sess
->
trans
->
key_algo_selected
]
(
sess
);
sess
->
trans
->
key_algo_selected
=
SIZE_MAX
;
if
(
sess
->
trans
->
key_algo_selected
)
{
if
(
sess
->
trans
->
key_algo_selected
->
cleanup
!=
NULL
)
sess
->
trans
->
key_algo_selected
->
cleanup
(
sess
);
sess
->
trans
->
key_algo_selected
=
NULL
;
}
if
(
sess
->
trans
->
enc_selected
!=
SIZE_MAX
)
{
if
(
gconf
.
enc_cleanup
[
sess
->
trans
->
enc_selected
]
!=
NULL
)
gconf
.
enc_cleanup
[
sess
->
trans
->
enc_selected
]
(
sess
);
sess
->
trans
->
enc_selected
=
SIZE_MAX
;
if
(
sess
->
trans
->
enc_selected
)
{
if
(
sess
->
trans
->
enc_selected
->
cleanup
!=
NULL
)
sess
->
trans
->
enc_selected
->
cleanup
(
sess
);
sess
->
trans
->
enc_selected
=
NULL
;
}
if
(
sess
->
trans
->
mac_selected
!=
SIZE_MAX
)
{
if
(
gconf
.
mac_cleanup
[
sess
->
trans
->
mac_selected
]
!=
NULL
)
gconf
.
mac_cleanup
[
sess
->
trans
->
mac_selected
]
(
sess
);
sess
->
trans
->
mac_selected
=
SIZE_MAX
;
if
(
sess
->
trans
->
mac_selected
)
{
if
(
sess
->
trans
->
mac_selected
->
cleanup
!=
NULL
)
sess
->
trans
->
mac_selected
->
cleanup
(
sess
);
sess
->
trans
->
mac_selected
=
NULL
;
}
if
(
sess
->
trans
->
comp_selected
!=
SIZE_MAX
)
{
if
(
gconf
.
comp_cleanup
[
sess
->
trans
->
comp_selected
]
!=
NULL
)
gconf
.
comp_cleanup
[
sess
->
trans
->
comp_selected
]
(
sess
);
sess
->
trans
->
comp_selected
=
SIZE_MAX
;
if
(
sess
->
trans
->
comp_selected
)
{
if
(
sess
->
trans
->
comp_selected
->
cleanup
!=
NULL
)
sess
->
trans
->
comp_selected
->
cleanup
(
sess
);
sess
->
trans
->
comp_selected
=
NULL
;
}
free
(
sess
->
remote_software_version
);
sess
->
remote_software_version
=
NULL
;
free
(
sess
->
remote_version_comment
);
sess
->
remote_version_comment
=
NULL
;
sess
->
remote_software_id_string_sz
=
0
;
sess
->
remote_software_id_string
[
0
]
=
0
;
if
(
sess
->
remote_languages
)
{
for
(
size_t
i
=
0
;
sess
->
remote_languages
[
i
];
i
++
)
free
(
sess
->
remote_languages
[
i
]);
...
...
@@ -265,251 +229,120 @@ deuce_ssh_transport_init(deuce_ssh_session_t sess)
thrd_join
(
thrd
,
&
tres
);
return
res
;
}
sess
->
trans
->
kex_selected
=
SIZE_MAX
;
sess
->
trans
->
key_algo_selected
=
SIZE_MAX
;
sess
->
trans
->
kex_selected
=
NULL
;
sess
->
trans
->
key_algo_selected
=
NULL
;
sess
->
trans
->
enc_selected
=
NULL
;
sess
->
trans
->
mac_selected
=
NULL
;
sess
->
trans
->
comp_selected
=
NULL
;
sess
->
trans
->
transport_thread
=
thrd
;
return
0
;
}
int
deuce_ssh_transport_register_kex
(
const
char
*
name
,
uint32_t
kex_flags
,
deuce_ssh_kex_handler_t
kex_handler
,
deuce_ssh_kex_cleanup_t
kex_cleanup
)
deuce_ssh_transport_register_kex
(
deuce_ssh_kex_t
kex
)
{
if
(
gconf
.
used
)
return
DEUCE_SSH_ERROR_TOOLATE
;
if
(
kex
->
next
)
return
DEUCE_SSH_ERROR_MUST_BE_NULL
;
if
(
gconf
.
kex_entries
+
1
==
SIZE_MAX
)
return
DEUCE_SSH_ERROR_TOOMANY
;
if
(
gconf
.
kex_head
==
NULL
)
gconf
.
kex_head
=
kex
;
if
(
gconf
.
kex_tail
!=
NULL
)
gconf
.
kex_tail
->
next
=
kex
;
gconf
.
kex_tail
=
kex
;
uint32_t
*
newflags
=
realloc
(
gconf
.
kex_flags
,
sizeof
(
gconf
.
kex_flags
[
0
])
*
(
gconf
.
kex_entries
+
1
));
if
(
newflags
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
kex_flags
=
newflags
;
gconf
.
kex_flags
[
gconf
.
kex_entries
]
=
kex_flags
;
deuce_ssh_kex_handler_t
*
newhandlers
=
realloc
(
gconf
.
kex_handler
,
sizeof
(
gconf
.
kex_handler
[
0
])
*
(
gconf
.
kex_entries
+
1
));
if
(
newhandlers
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
kex_handler
=
newhandlers
;
gconf
.
kex_handler
[
gconf
.
kex_entries
]
=
kex_handler
;
deuce_ssh_kex_cleanup_t
*
newcleanup
=
realloc
(
gconf
.
kex_cleanup
,
sizeof
(
gconf
.
kex_cleanup
[
0
])
*
(
gconf
.
kex_entries
+
1
));
if
(
newcleanup
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
kex_cleanup
=
newcleanup
;
gconf
.
kex_cleanup
[
gconf
.
kex_entries
]
=
kex_cleanup
;
char
**
newnames
=
realloc
(
gconf
.
kex_name
,
sizeof
(
gconf
.
kex_name
[
0
])
*
(
gconf
.
kex_entries
+
1
));
if
(
newnames
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
kex_name
=
newnames
;
gconf
.
kex_name
[
gconf
.
kex_entries
]
=
strdup
(
name
);
if
(
gconf
.
kex_name
[
gconf
.
kex_entries
]
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
kex_entries
++
;
return
0
;
}
int
deuce_ssh_transport_register_key_algo
(
const
char
*
name
,
uint32_t
key_algo_flags
,
deuce_ssh_key_algo_
sign_
t
key_algo
_sign
,
deuce_ssh_key_algo_haskey_t
key_algo_haskey
,
deuce_ssh_key_algo_cleanup_t
key_algo_cleanup
)
deuce_ssh_transport_register_key_algo
(
deuce_ssh_key_algo_t
key_algo
)
{
if
(
gconf
.
used
)
return
DEUCE_SSH_ERROR_TOOLATE
;
if
(
key_algo
->
next
)
return
DEUCE_SSH_ERROR_MUST_BE_NULL
;
if
(
gconf
.
key_algo_entries
+
1
==
SIZE_MAX
)
return
DEUCE_SSH_ERROR_TOOMANY
;
if
(
gconf
.
key_algo_head
==
NULL
)
gconf
.
key_algo_head
=
key_algo
;
if
(
gconf
.
key_algo_tail
!=
NULL
)
gconf
.
key_algo_tail
->
next
=
key_algo
;
gconf
.
key_algo_tail
=
key_algo
;
uint32_t
*
newflags
=
realloc
(
gconf
.
key_algo_flags
,
sizeof
(
gconf
.
key_algo_flags
[
0
])
*
(
gconf
.
key_algo_entries
+
1
));
if
(
newflags
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
key_algo_flags
=
newflags
;
gconf
.
key_algo_flags
[
gconf
.
key_algo_entries
]
=
key_algo_flags
;
deuce_ssh_key_algo_sign_t
*
newsigns
=
realloc
(
gconf
.
key_algo_sign
,
sizeof
(
gconf
.
key_algo_sign
[
0
])
*
(
gconf
.
key_algo_entries
+
1
));
if
(
newsigns
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
key_algo_sign
=
newsigns
;
gconf
.
key_algo_sign
[
gconf
.
key_algo_entries
]
=
key_algo_sign
;
deuce_ssh_key_algo_haskey_t
*
newhaskeys
=
realloc
(
gconf
.
key_algo_haskey
,
sizeof
(
gconf
.
key_algo_haskey
[
0
])
*
(
gconf
.
key_algo_entries
+
1
));
if
(
newhaskeys
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
key_algo_haskey
=
newhaskeys
;
gconf
.
key_algo_haskey
[
gconf
.
key_algo_entries
]
=
key_algo_haskey
;
deuce_ssh_key_algo_cleanup_t
*
newcleanup
=
realloc
(
gconf
.
key_algo_cleanup
,
sizeof
(
gconf
.
key_algo_cleanup
[
0
])
*
(
gconf
.
key_algo_entries
+
1
));
if
(
newcleanup
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
key_algo_cleanup
=
newcleanup
;
gconf
.
key_algo_cleanup
[
gconf
.
key_algo_entries
]
=
key_algo_cleanup
;
char
**
newnames
=
realloc
(
gconf
.
key_algo_name
,
sizeof
(
gconf
.
key_algo_name
[
0
])
*
(
gconf
.
key_algo_entries
+
1
));
if
(
newnames
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
key_algo_name
=
newnames
;
gconf
.
key_algo_name
[
gconf
.
key_algo_entries
]
=
strdup
(
name
);
if
(
gconf
.
key_algo_name
[
gconf
.
key_algo_entries
]
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
key_algo_entries
++
;
return
0
;
}
int
deuce_ssh_transport_register_enc
(
const
char
*
name
,
uint32_t
enc_flags
,
uint16_t
enc_blocksize
,
uint16_t
enc_key_size
,
deuce_ssh_enc_encrypt_t
enc_encrypt
,
deuce_ssh_enc_decrypt_t
enc_decrypt
,
deuce_ssh_key_algo_cleanup_t
enc_cleanup
)
deuce_ssh_transport_register_enc
(
deuce_ssh_enc_t
enc
)
{
if
(
gconf
.
used
)
return
DEUCE_SSH_ERROR_TOOLATE
;
if
(
enc
->
next
)
return
DEUCE_SSH_ERROR_MUST_BE_NULL
;
if
(
gconf
.
enc_entries
+
1
==
SIZE_MAX
)
return
DEUCE_SSH_ERROR_TOOMANY
;
if
(
gconf
.
enc_head
==
NULL
)
gconf
.
enc_head
=
enc
;
if
(
gconf
.
enc_tail
!=
NULL
)
gconf
.
enc_tail
->
next
=
enc
;
gconf
.
enc_tail
=
enc
;
uint32_t
*
newflags
=
realloc
(
gconf
.
enc_flags
,
sizeof
(
gconf
.
enc_flags
[
0
])
*
(
gconf
.
enc_entries
+
1
));
if
(
newflags
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
enc_flags
=
newflags
;
gconf
.
enc_flags
[
gconf
.
enc_entries
]
=
enc_flags
;
uint16_t
*
newbss
=
realloc
(
gconf
.
enc_blocksize
,
sizeof
(
gconf
.
enc_blocksize
[
0
])
*
(
gconf
.
enc_entries
+
1
));
if
(
newbss
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
enc_blocksize
=
newbss
;
gconf
.
enc_blocksize
[
gconf
.
enc_entries
]
=
enc_blocksize
;
uint16_t
*
newkss
=
realloc
(
gconf
.
enc_key_size
,
sizeof
(
gconf
.
enc_key_size
[
0
])
*
(
gconf
.
enc_entries
+
1
));
if
(
newkss
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
enc_key_size
=
newkss
;
gconf
.
enc_key_size
[
gconf
.
enc_entries
]
=
enc_key_size
;
deuce_ssh_enc_encrypt_t
*
newencrypts
=
realloc
(
gconf
.
enc_encrypt
,
sizeof
(
gconf
.
enc_encrypt
[
0
])
*
(
gconf
.
enc_entries
+
1
));
if
(
newencrypts
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
enc_encrypt
=
newencrypts
;
gconf
.
enc_encrypt
[
gconf
.
enc_entries
]
=
enc_encrypt
;
deuce_ssh_enc_decrypt_t
*
newdecrypts
=
realloc
(
gconf
.
enc_decrypt
,
sizeof
(
gconf
.
enc_decrypt
[
0
])
*
(
gconf
.
enc_entries
+
1
));
if
(
newdecrypts
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
enc_decrypt
=
newdecrypts
;
gconf
.
enc_decrypt
[
gconf
.
enc_entries
]
=
enc_decrypt
;
deuce_ssh_enc_cleanup_t
*
newcleanup
=
realloc
(
gconf
.
enc_cleanup
,
sizeof
(
gconf
.
enc_cleanup
[
0
])
*
(
gconf
.
enc_entries
+
1
));
if
(
newcleanup
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
enc_cleanup
=
newcleanup
;
gconf
.
enc_cleanup
[
gconf
.
enc_entries
]
=
enc_cleanup
;
char
**
newnames
=
realloc
(
gconf
.
enc_name
,
sizeof
(
gconf
.
enc_name
[
0
])
*
(
gconf
.
enc_entries
+
1
));
if
(
newnames
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
enc_name
=
newnames
;
gconf
.
enc_name
[
gconf
.
enc_entries
]
=
strdup
(
name
);
if
(
gconf
.
enc_name
[
gconf
.
enc_entries
]
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
enc_entries
++
;
return
0
;
}
int
deuce_ssh_transport_register_mac
(
const
char
*
name
,
uint16_t
mac_digest_size
,
uint16_t
mac_key_size
,
deuce_ssh_mac_generate_t
mac_generate
,
deuce_ssh_key_algo_cleanup_t
mac_cleanup
)
deuce_ssh_transport_register_mac
(
deuce_ssh_mac_t
mac
)
{
if
(
gconf
.
used
)
return
DEUCE_SSH_ERROR_TOOLATE
;
if
(
mac
->
next
)
return
DEUCE_SSH_ERROR_MUST_BE_NULL
;
if
(
gconf
.
mac_entries
+
1
==
SIZE_MAX
)
return
DEUCE_SSH_ERROR_TOOMANY
;
if
(
gconf
.
mac_head
==
NULL
)
gconf
.
mac_head
=
mac
;
if
(
gconf
.
mac_tail
!=
NULL
)
gconf
.
mac_tail
->
next
=
mac
;
gconf
.
mac_tail
=
mac
;
uint16_t
*
newdss
=
realloc
(
gconf
.
mac_digest_size
,
sizeof
(
gconf
.
mac_digest_size
[
0
])
*
(
gconf
.
mac_entries
+
1
));
if
(
newdss
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
mac_digest_size
=
newdss
;
gconf
.
mac_digest_size
[
gconf
.
mac_entries
]
=
mac_digest_size
;
uint16_t
*
newkss
=
realloc
(
gconf
.
mac_key_size
,
sizeof
(
gconf
.
mac_key_size
[
0
])
*
(
gconf
.
mac_entries
+
1
));
if
(
newkss
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
mac_key_size
=
newkss
;
gconf
.
mac_key_size
[
gconf
.
mac_entries
]
=
mac_key_size
;
deuce_ssh_mac_generate_t
*
newgens
=
realloc
(
gconf
.
mac_generate
,
sizeof
(
gconf
.
mac_generate
[
0
])
*
(
gconf
.
mac_entries
+
1
));
if
(
newgens
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
mac_generate
=
newgens
;
gconf
.
mac_generate
[
gconf
.
mac_entries
]
=
mac_generate
;
deuce_ssh_mac_cleanup_t
*
newcleanup
=
realloc
(
gconf
.
mac_cleanup
,
sizeof
(
gconf
.
mac_cleanup
[
0
])
*
(
gconf
.
mac_entries
+
1
));
if
(
newcleanup
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
mac_cleanup
=
newcleanup
;
gconf
.
mac_cleanup
[
gconf
.
mac_entries
]
=
mac_cleanup
;
char
**
newnames
=
realloc
(
gconf
.
mac_name
,
sizeof
(
gconf
.
mac_name
[
0
])
*
(
gconf
.
mac_entries
+
1
));
if
(
newnames
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
mac_name
=
newnames
;
gconf
.
mac_name
[
gconf
.
mac_entries
]
=
strdup
(
name
);
if
(
gconf
.
mac_name
[
gconf
.
mac_entries
]
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
mac_entries
++
;
return
0
;
}
int
deuce_ssh_transport_register_comp
(
const
char
*
name
,
deuce_ssh_comp_compress_t
comp_compress
,
deuce_ssh_comp_uncompress_t
comp_uncompress
,
deuce_ssh_key_algo_cleanup_t
comp_cleanu
p
)
deuce_ssh_transport_register_comp
(
deuce_ssh_comp_t
com
p
)
{
if
(
gconf
.
used
)
return
DEUCE_SSH_ERROR_TOOLATE
;
if
(
comp
->
next
)
return
DEUCE_SSH_ERROR_MUST_BE_NULL
;
if
(
gconf
.
comp_entries
+
1
==
SIZE_MAX
)
return
DEUCE_SSH_ERROR_TOOMANY
;
if
(
gconf
.
comp_head
==
NULL
)
gconf
.
comp_head
=
comp
;
if
(
gconf
.
comp_tail
!=
NULL
)
gconf
.
comp_tail
->
next
=
comp
;
gconf
.
comp_tail
=
comp
;
deuce_ssh_comp_compress_t
*
newcompress
=
realloc
(
gconf
.
comp_compress
,
sizeof
(
gconf
.
comp_compress
[
0
])
*
(
gconf
.
comp_entries
+
1
));
if
(
newcompress
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
comp_compress
=
newcompress
;
gconf
.
comp_compress
[
gconf
.
comp_entries
]
=
comp_compress
;
deuce_ssh_comp_uncompress_t
*
newuncompress
=
realloc
(
gconf
.
comp_uncompress
,
sizeof
(
gconf
.
comp_uncompress
[
0
])
*
(
gconf
.
comp_entries
+
1
));
if
(
newuncompress
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
comp_uncompress
=
newuncompress
;
gconf
.
comp_uncompress
[
gconf
.
comp_entries
]
=
comp_uncompress
;
deuce_ssh_comp_cleanup_t
*
newcleanup
=
realloc
(
gconf
.
comp_cleanup
,
sizeof
(
gconf
.
comp_cleanup
[
0
])
*
(
gconf
.
comp_entries
+
1
));
if
(
newcleanup
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
comp_cleanup
=
newcleanup
;
gconf
.
comp_cleanup
[
gconf
.
comp_entries
]
=
comp_cleanup
;
char
**
newnames
=
realloc
(
gconf
.
comp_name
,
sizeof
(
gconf
.
comp_name
[
0
])
*
(
gconf
.
comp_entries
+
1
));
if
(
newnames
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
comp_name
=
newnames
;
gconf
.
comp_name
[
gconf
.
comp_entries
]
=
strdup
(
name
);
if
(
gconf
.
comp_name
[
gconf
.
comp_entries
]
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
comp_entries
++
;
return
0
;
}
int
deuce_ssh_transport_register_lang
(
const
char
*
name
)
deuce_ssh_transport_register_lang
(
deuce_ssh_language_t
lang
)
{
if
(
gconf
.
used
)
return
DEUCE_SSH_ERROR_TOOLATE
;
if
(
lang
->
next
)
return
DEUCE_SSH_ERROR_MUST_BE_NULL
;
if
(
gconf
.
lang_entries
+
1
==
SIZE_MAX
)
return
DEUCE_SSH_ERROR_TOOMANY
;
if
(
gconf
.
lang_head
==
NULL
)
gconf
.
lang_head
=
lang
;
if
(
gconf
.
lang_tail
!=
NULL
)
gconf
.
lang_tail
->
next
=
lang
;
gconf
.
lang_tail
=
lang
;
char
**
newnames
=
realloc
(
gconf
.
lang_name
,
sizeof
(
gconf
.
lang_name
[
0
])
*
(
gconf
.
lang_entries
+
1
));
if
(
newnames
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
lang_name
=
newnames
;
gconf
.
lang_name
[
gconf
.
lang_entries
]
=
strdup
(
name
);
if
(
gconf
.
lang_name
[
gconf
.
lang_entries
]
==
NULL
)
return
DEUCE_SSH_ERROR_ALLOC
;
gconf
.
lang_entries
++
;
return
0
;
}
...
...
This diff is collapsed.
Click to expand it.
src/ssh/ssh-trans.h
+
74
−
7
View file @
02be7ecc
...
...
@@ -40,6 +40,20 @@
#define DEUCE_SSH_KEY_ALGO_FLAG_ENCRYPTION_CAPABLE UINT32_C(1<<0)
#define DEUCE_SSH_KEY_ALGO_FLAG_SIGNATURE_CAPABLE UINT32_C(1<<1)
#ifndef SSH_TOTAL_BPP_PACKET_SIZE_MAX
/*
* Defined in RFC 4253 s6.1, but may be larger "where they might be needed"
* and "if the identification string indicates that the other party is able to process them"
* which means that we would need to maintain a list of implementation id
* strings that support larger packets, *and* understand which message
* "need" a larger packet.
*
* That seems like a never-ending job, so I'll just allow the user to
* override this and let them sort it out if the need to.
*/
#define SSH_TOTAL_BPP_PACKET_SIZE_MAX 35000
#endif
typedef
struct
deuce_ssh_transport_packet
{
deuce_ssh_string_t
payload
;
deuce_ssh_string_t
random_padding
;
...
...
@@ -66,6 +80,59 @@ typedef int (*deuce_ssh_comp_compress_t)(uint8_t *buf, uint8_t *bufsz, deuce_ssh
typedef
int
(
*
deuce_ssh_comp_uncompress_t
)(
uint8_t
*
buf
,
uint8_t
*
bufsz
,
deuce_ssh_session_t
sess
);
typedef
void
(
*
deuce_ssh_comp_cleanup_t
)(
deuce_ssh_session_t
sess
);
typedef
struct
deuce_ssh_kex
{
struct
deuce_ssh_kex
*
next
;
deuce_ssh_kex_handler_t
handler
;
deuce_ssh_kex_cleanup_t
cleanup
;
uint32_t
flags
;
char
name
[];
}
*
deuce_ssh_kex_t
;
typedef
struct
deuce_ssh_key_algo
{
struct
deuce_ssh_key_algo
*
next
;
deuce_ssh_key_algo_sign_t
sign
;
deuce_ssh_key_algo_haskey_t
haskey
;
deuce_ssh_key_algo_cleanup_t
cleanup
;
uint32_t
flags
;
char
name
[];
}
*
deuce_ssh_key_algo_t
;
typedef
struct
deuce_ssh_enc
{
struct
deuce_ssh_enc
*
next
;
deuce_ssh_enc_encrypt_t
encrypt
;
deuce_ssh_enc_decrypt_t
decrypt
;
deuce_ssh_enc_cleanup_t
cleanup
;
uint32_t
flags
;
uint16_t
blocksize
;
uint16_t
key_size
;
char
name
[];
}
*
deuce_ssh_enc_t
;
typedef
struct
deuce_ssh_mac
{
struct
deuce_ssh_mac
*
next
;
deuce_ssh_mac_generate_t
generate
;
deuce_ssh_mac_cleanup_t
cleanup
;
uint16_t
*
digest_size
;
uint16_t
*
key_size
;
char
name
[];
}
*
deuce_ssh_mac_t
;
typedef
struct
deuce_ssh_comp
{
struct
deuce_ssh_comp
*
next
;
deuce_ssh_comp_compress_t
compress
;
deuce_ssh_comp_uncompress_t
uncompress
;
deuce_ssh_comp_cleanup_t
cleanup
;
uint32_t
flags
;
uint16_t
blocksize
;
uint16_t
key_size
;
char
name
[];
}
*
deuce_ssh_comp_t
;
typedef
struct
deuce_ssh_language
{
struct
deuce_ssh_language
*
next
;
char
name
;
}
*
deuce_ssh_language_t
;
typedef
struct
deuce_ssh_transport_state
{
uint32_t
tx_seq
;
uint32_t
rx_seq
;
...
...
@@ -73,10 +140,12 @@ typedef struct deuce_ssh_transport_state {
/* Transport options */
thrd_t
transport_thread
;
size_t
id_str_sz
;
char
id_str
[
254
];
/* KEX options */
void
*
kex_cbdata
;
size
_t
kex_selected
;
deuce_ssh_kex
_t
kex_selected
;
/* KEX outputs */
size_t
shared_secret_sz
;
...
...
@@ -84,16 +153,14 @@ typedef struct deuce_ssh_transport_state {
size_t
exchange_hash_sz
;
uint8_t
*
exchange_hash
;
/* Public Key Algorithms */
void
*
key_algo_cbdata
;
size_t
key_algo_selected
;
deuce_ssh_key_algo_t
key_algo_selected
;
void
*
enc_cbdata
;
size
_t
enc_selected
;
deuce_ssh_enc
_t
enc_selected
;
void
*
mac_cbdata
;
size
_t
mac_selected
;
deuce_ssh_mac
_t
mac_selected
;
void
*
comp_cbdata
;
size
_t
comp_selected
;
deuce_ssh_comp
_t
comp_selected
;
}
*
deuce_ssh_transport_state_t
;
...
...
This diff is collapsed.
Click to expand it.
src/ssh/ssh.h
+
12
−
11
View file @
02be7ecc
...
...
@@ -14,15 +14,16 @@ _Static_assert(0, "threads.h support required");
#include
<stdbool.h>
#include
<threads.h>
#define DEUCE_SSH_ERROR_NONE 0
#define DEUCE_SSH_ERROR_PARSE -1
#define DEUCE_SSH_ERROR_INVALID -2
#define DEUCE_SSH_ERROR_ALLOC -3
#define DEUCE_SSH_ERROR_INIT -4
#define DEUCE_SSH_ERROR_TERMINATED -5
#define DEUCE_SSH_ERROR_TOOLATE -6
#define DEUCE_SSH_ERROR_TOOMANY -7
#define DEUCE_SSH_ERROR_TOOLONG -8
#define DEUCE_SSH_ERROR_NONE 0
#define DEUCE_SSH_ERROR_PARSE -1
#define DEUCE_SSH_ERROR_INVALID -2
#define DEUCE_SSH_ERROR_ALLOC -3
#define DEUCE_SSH_ERROR_INIT -4
#define DEUCE_SSH_ERROR_TERMINATED -5
#define DEUCE_SSH_ERROR_TOOLATE -6
#define DEUCE_SSH_ERROR_TOOMANY -7
#define DEUCE_SSH_ERROR_TOOLONG -8
#define DEUCE_SSH_ERROR_MUST_BE_NULL -9
typedef
struct
deuce_ssh_transport_state
*
deuce_ssh_transport_state_t
;
typedef
int
(
*
deuce_ssh_transport_io_cb_t
)(
uint8_t
*
buf
,
size_t
bufsz
,
atomic_bool
*
terminate
,
void
*
cbdata
);
...
...
@@ -37,8 +38,8 @@ typedef struct deuce_ssh_session {
bool
is_server
;
/* Transport Remote information */
char
*
remote_software_
version
;
char
*
remote_
version_comment
;
size_t
remote_software_
id_string_sz
;
char
remote_
software_id_string
[
254
]
;
char
**
remote_languages
;
void
*
tx_cbdata
;
...
...
This diff is collapsed.
Click to expand it.
Preview
0%
Loading
Try again
or
attach a new file
.
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Save comment
Cancel
Please
register
or
sign in
to comment