Merge my working branch 'hmac_support' into hmac_header_fixes
This commit is contained in:
+23
-5
@@ -28,14 +28,20 @@
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
#include "fko.h"
|
||||
#include "fwknop.h"
|
||||
#include "config_init.h"
|
||||
#include "spa_comm.h"
|
||||
#include "utils.h"
|
||||
#include "getpasswd.h"
|
||||
|
||||
#include "digest.h"
|
||||
#include "rijndael.h"
|
||||
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
|
||||
|
||||
/* prototypes
|
||||
*/
|
||||
static void get_keys(fko_ctx_t ctx, fko_cli_options_t *options,
|
||||
@@ -61,13 +67,14 @@ static void clean_exit(fko_ctx_t ctx, fko_cli_options_t *opts,
|
||||
int
|
||||
main(int argc, char **argv)
|
||||
{
|
||||
fko_ctx_t ctx = NULL, ctx2 = NULL;
|
||||
fko_ctx_t ctx = NULL;
|
||||
fko_ctx_t ctx2 = NULL;
|
||||
int res;
|
||||
char *spa_data, *version;
|
||||
char access_buf[MAX_LINE_LEN] = {0};
|
||||
char key[MAX_KEY_LEN+1] = {0};
|
||||
char hmac_key[MAX_KEY_LEN+1] = {0};
|
||||
int key_len = 0, hmac_key_len = 0;
|
||||
int key_len = 0, hmac_key_len = 0, enc_mode;
|
||||
FILE *key_gen_file_ptr = NULL;
|
||||
|
||||
fko_cli_options_t options;
|
||||
@@ -402,6 +409,17 @@ main(int argc, char **argv)
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* Pull the encryption mode.
|
||||
*/
|
||||
res = fko_get_spa_encryption_mode(ctx, &enc_mode);
|
||||
if(res != FKO_SUCCESS)
|
||||
{
|
||||
errmsg("fko_get_spa_encryption_mode", res);
|
||||
fko_destroy(ctx);
|
||||
fko_destroy(ctx2);
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
/* If gpg-home-dir is specified, we have to defer decrypting if we
|
||||
* use the fko_new_with_data() function because we need to set the
|
||||
* gpg home dir after the context is created, but before we attempt
|
||||
@@ -411,7 +429,7 @@ main(int argc, char **argv)
|
||||
* options, then decode it.
|
||||
*/
|
||||
res = fko_new_with_data(&ctx2, spa_data, NULL,
|
||||
0, ctx->encryption_mode, hmac_key, hmac_key_len);
|
||||
0, enc_mode, hmac_key, hmac_key_len);
|
||||
if(res != FKO_SUCCESS)
|
||||
{
|
||||
errmsg("fko_new_with_data", res);
|
||||
@@ -420,7 +438,7 @@ main(int argc, char **argv)
|
||||
return(EXIT_FAILURE);
|
||||
}
|
||||
|
||||
res = fko_set_spa_encryption_mode(ctx2, ctx->encryption_mode);
|
||||
res = fko_set_spa_encryption_mode(ctx2, enc_mode);
|
||||
if(res != FKO_SUCCESS)
|
||||
{
|
||||
errmsg("fko_set_spa_encryption_mode", res);
|
||||
@@ -927,7 +945,7 @@ get_keys(fko_ctx_t ctx, fko_cli_options_t *options,
|
||||
{
|
||||
*hmac_key_len = fko_base64_decode(options->hmac_key_base64,
|
||||
(unsigned char *) options->hmac_key);
|
||||
memcpy(hmac_key, options->hmac_key, SHA256_BLOCK_LEN);
|
||||
memcpy(hmac_key, options->hmac_key, *hmac_key_len);
|
||||
use_hmac = 1;
|
||||
}
|
||||
else if (options->use_hmac)
|
||||
|
||||
@@ -32,6 +32,7 @@
|
||||
#define FWKNOP_COMMON_H
|
||||
|
||||
#include "common.h"
|
||||
#include "fko_limits.h"
|
||||
|
||||
/* My Name and Version
|
||||
*/
|
||||
|
||||
@@ -42,7 +42,4 @@ int is_base64(const unsigned char *buf, const unsigned short int len);
|
||||
int set_file_perms(const char *file);
|
||||
int verify_file_perms_ownership(const char *file);
|
||||
|
||||
size_t strlcat(char *dst, const char *src, size_t siz);
|
||||
size_t strlcpy(char *dst, const char *src, size_t siz);
|
||||
|
||||
#endif /* UTILS_H */
|
||||
|
||||
@@ -100,6 +100,7 @@
|
||||
|
||||
#include "fko.h"
|
||||
#include "fko_limits.h"
|
||||
#include "fko_util.h"
|
||||
|
||||
/* Get our program version from VERSION (defined in config.h).
|
||||
*/
|
||||
|
||||
+30
-5
@@ -11,7 +11,7 @@ AC_PREREQ(2.62)
|
||||
|
||||
dnl Define our name, version and email.
|
||||
m4_define(my_package, [fwknop])
|
||||
m4_define(my_version, [2.0.4])
|
||||
m4_define(my_version, [2.5.0b])
|
||||
m4_define(my_bug_email, [dstuart@dstuart.org])
|
||||
|
||||
AC_INIT(my_package, my_version, my_bug_email)
|
||||
@@ -431,7 +431,7 @@ dnl
|
||||
AS_IF([ test "x$withval" = xno ], [],
|
||||
AS_IF([ test "x$withval" = x -o "x$withval" = xyes ],
|
||||
[AC_MSG_ERROR([--with-iptables requires an argument specifying a path to iptables])],
|
||||
[ IPTABLES_EXE=$withval ]
|
||||
[ FORCE_IPTABLES_EXE=$withval ]
|
||||
)
|
||||
)
|
||||
],
|
||||
@@ -449,7 +449,7 @@ dnl
|
||||
AS_IF([ test "x$withval" = xno ], [],
|
||||
AS_IF([ test "x$withval" = x -o "x$withval" = xyes ],
|
||||
[AC_MSG_ERROR([--with-ipfw requires an argument specifying a path to ipfw])],
|
||||
[ IPFW_EXE=$withval ]
|
||||
[ FORCE_IPFW_EXE=$withval ]
|
||||
)
|
||||
)
|
||||
],
|
||||
@@ -467,7 +467,7 @@ dnl
|
||||
AS_IF([ test "x$withval" = xno ], [],
|
||||
AS_IF([ test "x$withval" = x -o "x$withval" = xyes ],
|
||||
[AC_MSG_ERROR([--with-pf requires an argument specifying a path to pf])],
|
||||
[ PF_EXE=$withval ]
|
||||
[ FORCE_PF_EXE=$withval ]
|
||||
)
|
||||
)
|
||||
],
|
||||
@@ -485,7 +485,7 @@ dnl
|
||||
AS_IF([ test "x$withval" = xno ], [],
|
||||
AS_IF([ test "x$withval" = x -o "x$withval" = xyes ],
|
||||
[AC_MSG_ERROR([--with-ipf requires an argument specifying a path to ipf])],
|
||||
[ IPF_EXE=$withval ]
|
||||
[ FORCE_IPF_EXE=$withval ]
|
||||
)
|
||||
)
|
||||
],
|
||||
@@ -494,6 +494,31 @@ dnl
|
||||
]
|
||||
)
|
||||
|
||||
dnl If a firewall was forced. set the appropriate _EXE var and clear the others.
|
||||
dnl
|
||||
AS_IF([test "x$FORCE_IPTABLES_EXE" != x], [
|
||||
IPTABLES_EXE="$FORCE_IPTABLES_EXE"
|
||||
],[
|
||||
AS_IF([test "x$FORCE_IPFW_EXE" != x], [
|
||||
IPFW_EXE="$FORCE_IPFW_EXE"
|
||||
IPTABLES_EXE=""
|
||||
],[
|
||||
AS_IF([test "x$FORCE_PF_EXE" != x], [
|
||||
PF_EXE="$FORCE_PF_EXE"
|
||||
IPFW_EXE=""
|
||||
IPTABLES_EXE=""
|
||||
],[
|
||||
AS_IF([test "x$FORCE_IPF_EXE" != x], [
|
||||
IPF_EXE="$FORCE_IPF_EXE"
|
||||
PF_EXE=""
|
||||
IPFW_EXE=""
|
||||
IPTABLES_EXE=""
|
||||
]
|
||||
]
|
||||
]
|
||||
]
|
||||
))))
|
||||
|
||||
dnl Determine which firewall exe we use (if we have one).
|
||||
dnl If iptables was found or specified, it wins, then we fallback to ipfw,
|
||||
dnl then pf, and otherwise we try ipf.
|
||||
|
||||
@@ -31,6 +31,7 @@
|
||||
*****************************************************************************
|
||||
*/
|
||||
#include "base64.h"
|
||||
#include "fko_common.h"
|
||||
|
||||
static unsigned char map2[] =
|
||||
{
|
||||
|
||||
@@ -31,8 +31,6 @@
|
||||
#ifndef BASE64_H
|
||||
#define BASE64_H 1
|
||||
|
||||
#include "fko_common.h"
|
||||
|
||||
/* Prototypes
|
||||
*/
|
||||
int b64_encode(unsigned char *in, char *out, int in_len);
|
||||
|
||||
@@ -39,6 +39,7 @@
|
||||
#include <sys/time.h>
|
||||
#endif
|
||||
|
||||
#include "fko_common.h"
|
||||
#include "cipher_funcs.h"
|
||||
#include "digest.h"
|
||||
|
||||
|
||||
+1
-1
@@ -31,7 +31,7 @@
|
||||
#ifndef CIPHER_FUNCS_H
|
||||
#define CIPHER_FUNCS_H 1
|
||||
|
||||
#include "fko_common.h"
|
||||
#include "fko.h"
|
||||
#include "rijndael.h"
|
||||
#include "gpgme_funcs.h"
|
||||
|
||||
|
||||
@@ -28,9 +28,11 @@
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
#include "fko_common.h"
|
||||
#include "digest.h"
|
||||
#include "base64.h"
|
||||
|
||||
|
||||
/* Convert a raw digest into its hex string representation.
|
||||
*/
|
||||
static void
|
||||
|
||||
@@ -31,8 +31,6 @@
|
||||
#ifndef DIGEST_H
|
||||
#define DIGEST_H 1
|
||||
|
||||
#include "fko_common.h"
|
||||
|
||||
#include "md5.h"
|
||||
#include "sha1.h"
|
||||
#include "sha2.h"
|
||||
@@ -41,14 +39,6 @@
|
||||
*/
|
||||
#define MD_HEX_SIZE(x) x * 2
|
||||
|
||||
/* Predefined base64 encoded digest sizes.
|
||||
*/
|
||||
#define MD5_B64_LEN 22
|
||||
#define SHA1_B64_LEN 27
|
||||
#define SHA256_B64_LEN 43
|
||||
#define SHA384_B64_LEN 64
|
||||
#define SHA512_B64_LEN 86
|
||||
|
||||
void md5(unsigned char* out, unsigned char* in, size_t size);
|
||||
void md5_hex(char* out, unsigned char* in, size_t size);
|
||||
void md5_base64(char* out, unsigned char* in, size_t size);
|
||||
|
||||
@@ -33,8 +33,6 @@
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "digest.h"
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
@@ -126,12 +126,6 @@
|
||||
#define END_C_DECLS
|
||||
#endif /* __cplusplus */
|
||||
|
||||
/* Pull in gpgme.h if we have it.
|
||||
*/
|
||||
#if HAVE_LIBGPGME
|
||||
#include <gpgme.h>
|
||||
#endif
|
||||
|
||||
#include "fko_util.h"
|
||||
#include "fko_limits.h"
|
||||
#include "fko_state.h"
|
||||
|
||||
@@ -33,6 +33,10 @@
|
||||
|
||||
#include "fko_common.h"
|
||||
|
||||
#if HAVE_LIBGPGME
|
||||
#include <gpgme.h>
|
||||
#endif
|
||||
|
||||
#if HAVE_LIBGPGME
|
||||
/* Stucture to hold a list of the gpg signature information
|
||||
* we are interested in.
|
||||
|
||||
+31
-4
@@ -32,6 +32,7 @@
|
||||
#include "fko.h"
|
||||
#include "cipher_funcs.h"
|
||||
#include "base64.h"
|
||||
#include "digest.h"
|
||||
|
||||
#if HAVE_LIBGPGME
|
||||
#include "gpgme_funcs.h"
|
||||
@@ -54,8 +55,21 @@ _rijndael_encrypt(fko_ctx_t ctx, const char *enc_key, const int enc_key_len)
|
||||
if (! is_valid_encoded_msg_len(ctx->encoded_msg_len))
|
||||
return(FKO_ERROR_INVALID_DATA);
|
||||
|
||||
if (! is_valid_digest_len(ctx->digest_len))
|
||||
return(FKO_ERROR_INVALID_DATA);
|
||||
switch(ctx->digest_len)
|
||||
{
|
||||
case MD5_B64_LEN:
|
||||
break;
|
||||
case SHA1_B64_LEN:
|
||||
break;
|
||||
case SHA256_B64_LEN:
|
||||
break;
|
||||
case SHA384_B64_LEN:
|
||||
break;
|
||||
case SHA512_B64_LEN:
|
||||
break;
|
||||
default:
|
||||
return(FKO_ERROR_INVALID_DATA);
|
||||
}
|
||||
|
||||
pt_len = ctx->encoded_msg_len + ctx->digest_len + RIJNDAEL_BLOCKSIZE + 2;
|
||||
|
||||
@@ -217,8 +231,21 @@ gpg_encrypt(fko_ctx_t ctx, const char *enc_key)
|
||||
if (! is_valid_encoded_msg_len(ctx->encoded_msg_len))
|
||||
return(FKO_ERROR_INVALID_DATA);
|
||||
|
||||
if (! is_valid_digest_len(ctx->digest_len))
|
||||
return(FKO_ERROR_INVALID_DATA);
|
||||
switch(ctx->digest_len)
|
||||
{
|
||||
case MD5_B64_LEN:
|
||||
break;
|
||||
case SHA1_B64_LEN:
|
||||
break;
|
||||
case SHA256_B64_LEN:
|
||||
break;
|
||||
case SHA384_B64_LEN:
|
||||
break;
|
||||
case SHA512_B64_LEN:
|
||||
break;
|
||||
default:
|
||||
return(FKO_ERROR_INVALID_DATA);
|
||||
}
|
||||
|
||||
/* First make sure we have a recipient key set.
|
||||
*/
|
||||
|
||||
+15
-2
@@ -174,8 +174,21 @@ int fko_calculate_hmac(fko_ctx_t ctx,
|
||||
|
||||
free(hmac_base64);
|
||||
|
||||
if(! is_valid_digest_len(ctx->msg_hmac_len))
|
||||
return(FKO_ERROR_INVALID_DATA);
|
||||
switch(ctx->msg_hmac_len)
|
||||
{
|
||||
case MD5_B64_LEN:
|
||||
break;
|
||||
case SHA1_B64_LEN:
|
||||
break;
|
||||
case SHA256_B64_LEN:
|
||||
break;
|
||||
case SHA384_B64_LEN:
|
||||
break;
|
||||
case SHA512_B64_LEN:
|
||||
break;
|
||||
default:
|
||||
return(FKO_ERROR_INVALID_DATA);
|
||||
}
|
||||
|
||||
return FKO_SUCCESS;
|
||||
}
|
||||
|
||||
+1
-24
@@ -30,6 +30,7 @@
|
||||
*/
|
||||
#include "fko_common.h"
|
||||
#include "fko.h"
|
||||
#include "fko_util.h"
|
||||
#include <errno.h>
|
||||
|
||||
/* Validate encoded message length
|
||||
@@ -54,30 +55,6 @@ is_valid_pt_msg_len(const int len)
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* Validate digest length
|
||||
*/
|
||||
int
|
||||
is_valid_digest_len(const int len)
|
||||
{
|
||||
switch(len)
|
||||
{
|
||||
case MD5_B64_LEN:
|
||||
break;
|
||||
case SHA1_B64_LEN:
|
||||
break;
|
||||
case SHA256_B64_LEN:
|
||||
break;
|
||||
case SHA384_B64_LEN:
|
||||
break;
|
||||
case SHA512_B64_LEN:
|
||||
break;
|
||||
default:
|
||||
return(0);
|
||||
}
|
||||
|
||||
return(1);
|
||||
}
|
||||
|
||||
/* Convert an encryption_mode string to its integer value.
|
||||
*/
|
||||
int
|
||||
|
||||
@@ -31,8 +31,6 @@
|
||||
#ifndef FKO_UTIL_H
|
||||
#define FKO_UTIL_H 1
|
||||
|
||||
#include "fko_common.h"
|
||||
|
||||
/* Function prototypes
|
||||
*/
|
||||
int is_valid_encoded_msg_len(const int len);
|
||||
|
||||
+4
-1
@@ -31,7 +31,10 @@
|
||||
#ifndef GPGME_FUNCS_H
|
||||
#define GPGME_FUNCS_H 1
|
||||
|
||||
#include "fko_common.h"
|
||||
#if HAVE_LIBGPGME
|
||||
#include <gpgme.h>
|
||||
#endif
|
||||
|
||||
#include "fko.h"
|
||||
|
||||
int gpgme_encrypt(fko_ctx_t ctx, unsigned char *in, size_t len, const char *pw, unsigned char **out, size_t *out_len);
|
||||
|
||||
@@ -35,9 +35,10 @@
|
||||
#ifndef MD5_H
|
||||
#define MD5_H 1
|
||||
|
||||
#include "fko_common.h"
|
||||
#include "common.h"
|
||||
|
||||
#define MD5_DIGEST_LEN 16
|
||||
#define MD5_B64_LEN 22
|
||||
|
||||
typedef struct _MD5Context {
|
||||
uint32_t buf[4];
|
||||
|
||||
@@ -28,6 +28,7 @@
|
||||
*
|
||||
*****************************************************************************
|
||||
*/
|
||||
#include "fko_common.h"
|
||||
#include "rijndael.h"
|
||||
#include <stdlib.h>
|
||||
#include <string.h>
|
||||
|
||||
+1
-2
@@ -33,11 +33,10 @@
|
||||
* 128, 192, or 256 bits, designed by Joan Daemen and Vincent Rijmen. See
|
||||
* http://www.esat.kuleuven.ac.be/~rijmen/rijndael/ for details.
|
||||
*/
|
||||
|
||||
#ifndef RIJNDAEL_H
|
||||
#define RIJNDAEL_H 1
|
||||
|
||||
#include "fko_common.h"
|
||||
#include "common.h"
|
||||
|
||||
/* Other block sizes and key lengths are possible, but in the context of
|
||||
* the ssh protocols, 256 bits is the default.
|
||||
|
||||
+2
-1
@@ -32,7 +32,7 @@
|
||||
#ifndef SHA1_H
|
||||
#define SHA1_H 1
|
||||
|
||||
#include "fko_common.h"
|
||||
#include "common.h"
|
||||
|
||||
#ifdef WIN32
|
||||
#define BYTEORDER 1234
|
||||
@@ -46,6 +46,7 @@
|
||||
|
||||
#define SHA1_BLOCKSIZE 64
|
||||
#define SHA1_DIGEST_LEN 20
|
||||
#define SHA1_B64_LEN 27
|
||||
|
||||
typedef struct {
|
||||
uint32_t digest[8];
|
||||
|
||||
+4
-1
@@ -43,7 +43,7 @@
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
#include "fko_common.h"
|
||||
#include "common.h"
|
||||
|
||||
/*
|
||||
* Import u_intXX_t size_t type definitions from system headers. You
|
||||
@@ -70,12 +70,15 @@ extern "C" {
|
||||
#define SHA256_BLOCK_LEN 64
|
||||
#define SHA256_DIGEST_LEN 32
|
||||
#define SHA256_DIGEST_STR_LEN (SHA256_DIGEST_LEN * 2 + 1)
|
||||
#define SHA256_B64_LEN 43
|
||||
#define SHA384_BLOCK_LEN 128
|
||||
#define SHA384_DIGEST_LEN 48
|
||||
#define SHA384_DIGEST_STR_LEN (SHA384_DIGEST_LEN * 2 + 1)
|
||||
#define SHA384_B64_LEN 64
|
||||
#define SHA512_BLOCK_LEN 128
|
||||
#define SHA512_DIGEST_LEN 64
|
||||
#define SHA512_DIGEST_STR_LEN (SHA512_DIGEST_LEN * 2 + 1)
|
||||
#define SHA512_B64_LEN 86
|
||||
|
||||
|
||||
/*** SHA-256/384/512 Context Structures *******************************/
|
||||
|
||||
@@ -40,6 +40,7 @@
|
||||
#include "access.h"
|
||||
#include "utils.h"
|
||||
#include "log_msg.h"
|
||||
#include "rijndael.h"
|
||||
|
||||
/* Add an access string entry
|
||||
*/
|
||||
|
||||
@@ -121,9 +121,6 @@ process_spa_request(const fko_srv_options_t *opts, const acc_stanza_t *acc, spa_
|
||||
acc_port_list_t *port_list = NULL;
|
||||
acc_port_list_t *ple;
|
||||
|
||||
unsigned int fst_proto;
|
||||
unsigned int fst_port;
|
||||
|
||||
int res = 0;
|
||||
time_t now;
|
||||
unsigned int exp_ts;
|
||||
@@ -136,12 +133,6 @@ process_spa_request(const fko_srv_options_t *opts, const acc_stanza_t *acc, spa_
|
||||
*/
|
||||
ple = port_list;
|
||||
|
||||
/* Remember the first proto/port combo in case we need them
|
||||
* for NAT access requests.
|
||||
*/
|
||||
fst_proto = ple->proto;
|
||||
fst_port = ple->port;
|
||||
|
||||
/* Set our expire time value.
|
||||
*/
|
||||
time(&now);
|
||||
|
||||
@@ -478,9 +478,6 @@ process_spa_request(const fko_srv_options_t * const opts,
|
||||
acc_port_list_t *port_list = NULL;
|
||||
acc_port_list_t *ple;
|
||||
|
||||
unsigned int fst_proto;
|
||||
unsigned int fst_port;
|
||||
|
||||
int res = 0;
|
||||
time_t now;
|
||||
unsigned int exp_ts;
|
||||
@@ -493,12 +490,6 @@ process_spa_request(const fko_srv_options_t * const opts,
|
||||
*/
|
||||
ple = port_list;
|
||||
|
||||
/* Remember the first proto/port combo in case we need them
|
||||
* for NAT access requests.
|
||||
*/
|
||||
fst_proto = ple->proto;
|
||||
fst_port = ple->port;
|
||||
|
||||
/* Set our expire time value.
|
||||
*/
|
||||
time(&now);
|
||||
|
||||
@@ -202,9 +202,6 @@ process_spa_request(const fko_srv_options_t * const opts,
|
||||
acc_port_list_t *port_list = NULL;
|
||||
acc_port_list_t *ple;
|
||||
|
||||
unsigned int fst_proto;
|
||||
unsigned int fst_port;
|
||||
|
||||
int res = 0;
|
||||
time_t now;
|
||||
unsigned int exp_ts;
|
||||
@@ -217,12 +214,6 @@ process_spa_request(const fko_srv_options_t * const opts,
|
||||
*/
|
||||
ple = port_list;
|
||||
|
||||
/* Remember the first proto/port combo in case we need them
|
||||
* for NAT access requests.
|
||||
*/
|
||||
fst_proto = ple->proto;
|
||||
fst_port = ple->port;
|
||||
|
||||
/* Set our expire time value.
|
||||
*/
|
||||
time(&now);
|
||||
|
||||
@@ -43,6 +43,7 @@
|
||||
#include "fw_util.h"
|
||||
#include "fwknopd_errors.h"
|
||||
#include "replay_cache.h"
|
||||
#include "rijndael.h"
|
||||
|
||||
/* Validate and in some cases preprocess/reformat the SPA data. Return an
|
||||
* error code value if there is any indication the data is not valid spa data.
|
||||
|
||||
@@ -64,7 +64,4 @@ int is_base64(const unsigned char *buf, const unsigned short int len);
|
||||
int is_valid_dir(const char *path);
|
||||
int verify_file_perms_ownership(const char *file);
|
||||
|
||||
size_t strlcat(char *dst, const char *src, size_t siz);
|
||||
size_t strlcpy(char *dst, const char *src, size_t siz);
|
||||
|
||||
#endif /* UTILS_H */
|
||||
|
||||
Reference in New Issue
Block a user