Page Menu
Home
Phorge
Search
Configure Global Search
Log In
Files
F3072066
tls.c
No One
Temporary
Actions
Download File
Edit File
Delete File
View Transforms
Subscribe
Flag For Later
Award Token
Size
7 KB
Referenced Files
None
Subscribers
None
tls.c
View Options
#include
<compat.h>
// IWYU pragma: keep
#include
<stdbool.h>
#include
<stdint.h>
#include
<stdlib.h>
#include
<string.h>
#include
<tlsuv/tlsuv.h>
#include
<tlsuv/tls_engine.h>
#include
"ant.h"
#include
"ptr.h"
#include
"errors.h"
#include
"modules/tls.h"
#include
"modules/buffer.h"
typedef
struct
ant_tls_context_wrap_s
{
ant_value_t
obj
;
tls_context
*
ctx
;
tlsuv_private_key_t
key
;
tlsuv_certificate_t
cert
;
bool
closed
;
}
ant_tls_context_wrap_t
;
enum
{
TLS_CONTEXT_NATIVE_TAG
=
0x544c5343u
};
// TLSC
static
ant_value_t
g_tls_context_proto
=
0
;
static
void
tls_context_free
(
ant_tls_context_wrap_t
*
wrap
)
{
if
(
!
wrap
||
wrap
->
closed
)
return
;
wrap
->
closed
=
true
;
if
(
wrap
->
cert
&&
wrap
->
cert
->
free
)
wrap
->
cert
->
free
(
wrap
->
cert
);
if
(
wrap
->
key
&&
wrap
->
key
->
free
)
wrap
->
key
->
free
(
wrap
->
key
);
if
(
wrap
->
ctx
&&
wrap
->
ctx
->
free_ctx
)
wrap
->
ctx
->
free_ctx
(
wrap
->
ctx
);
wrap
->
cert
=
NULL
;
wrap
->
key
=
NULL
;
wrap
->
ctx
=
NULL
;
}
static
ant_tls_context_wrap_t
*
tls_context_data
(
ant_value_t
value
)
{
if
(
!
js_check_native_tag
(
value
,
TLS_CONTEXT_NATIVE_TAG
))
return
NULL
;
return
(
ant_tls_context_wrap_t
*
)
js_get_native_ptr
(
value
);
}
static
bool
tls_value_bytes
(
ant_t
*
js
,
ant_value_t
value
,
const
char
**
bytes_out
,
size_t
*
len_out
,
ant_value_t
*
error_out
)
{
ant_value_t
str_value
=
0
;
const
uint8_t
*
buffer_bytes
=
NULL
;
if
(
error_out
)
*
error_out
=
js_mkundef
();
if
(
bytes_out
)
*
bytes_out
=
NULL
;
if
(
len_out
)
*
len_out
=
0
;
if
(
vtype
(
value
)
==
T_UNDEF
||
vtype
(
value
)
==
T_NULL
)
return
true
;
if
(
buffer_source_get_bytes
(
js
,
value
,
&
buffer_bytes
,
len_out
))
{
if
(
bytes_out
)
*
bytes_out
=
(
const
char
*
)
buffer_bytes
;
return
true
;
}
str_value
=
js_tostring_val
(
js
,
value
);
if
(
is_err
(
str_value
))
{
if
(
error_out
)
*
error_out
=
str_value
;
return
false
;
}
if
(
!
bytes_out
||
!
len_out
)
return
true
;
*
bytes_out
=
js_getstr
(
js
,
str_value
,
len_out
);
if
(
!*
bytes_out
)
{
if
(
error_out
)
*
error_out
=
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"Invalid TLS input"
);
return
false
;
}
return
true
;
}
static
ant_value_t
tls_make_error
(
ant_t
*
js
,
tls_context
*
ctx
,
long
code
,
const
char
*
fallback
)
{
const
char
*
message
=
fallback
;
if
(
ctx
&&
ctx
->
strerror
)
{
const
char
*
detail
=
ctx
->
strerror
(
code
);
if
(
detail
&&
*
detail
)
message
=
detail
;
}
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"%s"
,
message
?
message
:
"TLS error"
);
}
static
ant_value_t
js_tls_context_close
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
ant_tls_context_wrap_t
*
wrap
=
tls_context_data
(
js_getthis
(
js
));
if
(
!
wrap
)
return
js_getthis
(
js
);
tls_context_free
(
wrap
);
js_set_native_ptr
(
wrap
->
obj
,
NULL
);
js_set_native_tag
(
wrap
->
obj
,
0
);
return
js_getthis
(
js
);
}
static
void
tls_init_context_proto
(
ant_t
*
js
)
{
if
(
g_tls_context_proto
)
return
;
g_tls_context_proto
=
js_mkobj
(
js
);
js_set
(
js
,
g_tls_context_proto
,
"close"
,
js_mkfun
(
js_tls_context_close
));
}
static
ant_value_t
js_tls_create_context
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
ant_value_t
options
=
nargs
>
0
?
args
[
0
]
:
js_mkundef
();
ant_value_t
obj
=
0
;
ant_value_t
error
=
js_mkundef
();
ant_tls_context_wrap_t
*
wrap
=
NULL
;
ant_value_t
ca_v
=
js_mkundef
();
ant_value_t
key_v
=
js_mkundef
();
ant_value_t
cert_v
=
js_mkundef
();
ant_value_t
partial_v
=
js_mkundef
();
const
char
*
ca
=
NULL
;
const
char
*
key_data
=
NULL
;
const
char
*
cert_data
=
NULL
;
size_t
ca_len
=
0
;
size_t
key_len
=
0
;
size_t
cert_len
=
0
;
int
rc
=
0
;
if
(
vtype
(
options
)
!=
T_UNDEF
&&
vtype
(
options
)
!=
T_NULL
&&
vtype
(
options
)
!=
T_OBJ
)
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"TLS context options must be an object"
);
tls_init_context_proto
(
js
);
if
(
vtype
(
options
)
==
T_OBJ
)
{
ca_v
=
js_get
(
js
,
options
,
"ca"
);
key_v
=
js_get
(
js
,
options
,
"key"
);
cert_v
=
js_get
(
js
,
options
,
"cert"
);
partial_v
=
js_get
(
js
,
options
,
"allowPartialChain"
);
}
if
(
!
tls_value_bytes
(
js
,
ca_v
,
&
ca
,
&
ca_len
,
&
error
))
return
error
;
if
(
!
tls_value_bytes
(
js
,
key_v
,
&
key_data
,
&
key_len
,
&
error
))
return
error
;
if
(
!
tls_value_bytes
(
js
,
cert_v
,
&
cert_data
,
&
cert_len
,
&
error
))
return
error
;
wrap
=
calloc
(
1
,
sizeof
(
*
wrap
));
if
(
!
wrap
)
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"Out of memory"
);
wrap
->
ctx
=
default_tls_context
(
ca
,
ca_len
);
if
(
!
wrap
->
ctx
)
{
free
(
wrap
);
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"Failed to create TLS context"
);
}
if
(
wrap
->
ctx
->
allow_partial_chain
&&
js_truthy
(
js
,
partial_v
))
{
rc
=
wrap
->
ctx
->
allow_partial_chain
(
wrap
->
ctx
,
1
);
if
(
rc
!=
0
)
{
ant_value_t
err
=
tls_make_error
(
js
,
wrap
->
ctx
,
rc
,
"Failed to enable partial chain verification"
);
tls_context_free
(
wrap
);
free
(
wrap
);
return
err
;
}}
if
(
key_data
)
{
if
(
!
wrap
->
ctx
->
load_key
)
{
tls_context_free
(
wrap
);
free
(
wrap
);
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"TLS engine does not support loading private keys"
);
}
rc
=
wrap
->
ctx
->
load_key
(
&
wrap
->
key
,
key_data
,
key_len
);
if
(
rc
!=
0
)
{
ant_value_t
err
=
tls_make_error
(
js
,
wrap
->
ctx
,
rc
,
"Failed to load TLS private key"
);
tls_context_free
(
wrap
);
free
(
wrap
);
return
err
;
}
if
(
cert_data
)
{
if
(
!
wrap
->
ctx
->
load_cert
)
{
tls_context_free
(
wrap
);
free
(
wrap
);
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"TLS engine does not support loading certificates"
);
}
rc
=
wrap
->
ctx
->
load_cert
(
&
wrap
->
cert
,
cert_data
,
cert_len
);
if
(
rc
!=
0
)
{
ant_value_t
err
=
tls_make_error
(
js
,
wrap
->
ctx
,
rc
,
"Failed to load TLS certificate"
);
tls_context_free
(
wrap
);
free
(
wrap
);
return
err
;
}}
if
(
!
wrap
->
ctx
->
set_own_cert
)
{
tls_context_free
(
wrap
);
free
(
wrap
);
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"TLS engine does not support own certificate configuration"
);
}
rc
=
wrap
->
ctx
->
set_own_cert
(
wrap
->
ctx
,
wrap
->
key
,
wrap
->
cert
);
if
(
rc
!=
0
)
{
ant_value_t
err
=
tls_make_error
(
js
,
wrap
->
ctx
,
rc
,
"Failed to configure TLS certificate"
);
tls_context_free
(
wrap
);
free
(
wrap
);
return
err
;
}
}
else
if
(
cert_data
)
{
tls_context_free
(
wrap
);
free
(
wrap
);
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"TLS certificate requires a private key"
);
}
obj
=
js_mkobj
(
js
);
js_set_proto_init
(
obj
,
g_tls_context_proto
);
wrap
->
obj
=
obj
;
js_set_native_ptr
(
obj
,
wrap
);
js_set_native_tag
(
obj
,
TLS_CONTEXT_NATIVE_TAG
);
return
obj
;
}
static
ant_value_t
js_tls_is_context
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
ant_tls_context_wrap_t
*
wrap
=
nargs
>
0
?
tls_context_data
(
args
[
0
])
:
NULL
;
return
js_bool
(
wrap
&&
!
wrap
->
closed
&&
wrap
->
ctx
);
}
static
ant_value_t
js_tls_set_config_path
(
ant_t
*
js
,
ant_value_t
*
args
,
int
nargs
)
{
ant_value_t
str_value
=
js_mkundef
();
const
char
*
path
=
NULL
;
int
rc
=
0
;
if
(
nargs
<
1
||
vtype
(
args
[
0
])
==
T_UNDEF
||
vtype
(
args
[
0
])
==
T_NULL
)
{
rc
=
tlsuv_set_config_path
(
NULL
);
if
(
rc
!=
0
)
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"%s"
,
uv_strerror
(
rc
));
return
js_mkundef
();
}
str_value
=
js_tostring_val
(
js
,
args
[
0
]);
if
(
is_err
(
str_value
))
return
str_value
;
path
=
js_getstr
(
js
,
str_value
,
NULL
);
if
(
!
path
)
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"Invalid TLS config path"
);
rc
=
tlsuv_set_config_path
(
path
);
if
(
rc
!=
0
)
return
js_mkerr_typed
(
js
,
JS_ERR_TYPE
,
"%s"
,
uv_strerror
(
rc
));
return
js_mkundef
();
}
ant_value_t
internal_tls_library
(
ant_t
*
js
)
{
ant_value_t
lib
=
js_mkobj
(
js
);
ant_value_t
version
=
js_mkstr
(
js
,
"unknown"
,
7
);
tls_context
*
ctx
=
default_tls_context
(
NULL
,
0
);
const
char
*
version_str
=
NULL
;
if
(
ctx
&&
ctx
->
version
)
{
version_str
=
ctx
->
version
();
if
(
version_str
)
version
=
js_mkstr
(
js
,
version_str
,
strlen
(
version_str
));
}
if
(
ctx
&&
ctx
->
free_ctx
)
ctx
->
free_ctx
(
ctx
);
tls_init_context_proto
(
js
);
js_set
(
js
,
lib
,
"version"
,
version
);
js_set
(
js
,
lib
,
"createContext"
,
js_mkfun
(
js_tls_create_context
));
js_set
(
js
,
lib
,
"isContext"
,
js_mkfun
(
js_tls_is_context
));
js_set
(
js
,
lib
,
"setConfigPath"
,
js_mkfun
(
js_tls_set_config_path
));
return
lib
;
}
File Metadata
Details
Attached
Mime Type
text/x-c
Expires
Sat, Apr 4, 12:58 AM (2 d)
Storage Engine
blob
Storage Format
Raw Data
Storage Handle
520893
Default Alt Text
tls.c (7 KB)
Attached To
Mode
rANT Ant
Attached
Detach File
Event Timeline
Log In to Comment