Browse Source

Refactor error handling in secretcfg.c

Do not use errno anymore; use instead the GFSEC_ERR_* error codes.
master
Damien Goutte-Gattat 5 years ago
parent
commit
11b13f53bd
  1. 4
      src/gfsec-use.c
  2. 15
      src/secret.h
  3. 241
      src/secretcfg.c
  4. 4
      src/secretcfg.h

4
src/gfsec-use.c

@ -229,8 +229,8 @@ main(int argc, char **argv)
if ( get_config_file(cfg_file, cfg_path, sizeof(cfg_path)) == -1 )
err(EXIT_FAILURE, "Cannot find configuration file");
if ( ! (cfg = gfsec_read_config(cfg_path)) )
err(EXIT_FAILURE, "Cannot parse configuration file");
if ( gfsec_read_config(&cfg, cfg_path) != 0 )
errx(EXIT_FAILURE, "Cannot parse configuration file");
if ( ! output_file && ! (output_file = cfg->filename) )
errx(EXIT_FAILURE, "No output file specified");

15
src/secret.h

@ -19,13 +19,14 @@
#ifndef ICP20160807_SECRET_H
#define ICP20160807_SECRET_H
#define GFSEC_ERR_SYSTEM_ERROR 1
#define GFSEC_ERR_INVALID_CALL 2
#define GFSEC_ERR_NOT_ENOUGH_SHARES 3
#define GFSEC_ERR_TOO_MANY_SHARES 4
#define GFSEC_ERR_SHARE_NOT_AVAILABLE 5
#define GFSEC_ERR_INVALID_LENGTH 6
#define GFSEC_ERR_INVALID_SHARE 7
#define GFSEC_ERR_SYSTEM_ERROR -1
#define GFSEC_ERR_INVALID_CALL -2
#define GFSEC_ERR_NOT_ENOUGH_SHARES -3
#define GFSEC_ERR_TOO_MANY_SHARES -4
#define GFSEC_ERR_SHARE_NOT_AVAILABLE -5
#define GFSEC_ERR_INVALID_LENGTH -6
#define GFSEC_ERR_INVALID_SHARE -7
#define GFSEC_ERR_INVALID_CONFIG -8
#define GFSEC_SHARE_NUMBER_FULL 0
#define GFSEC_SHARE_NUMBER_AUTOASSIGN 256

241
src/secretcfg.c

@ -38,9 +38,8 @@
* @param buffer A character buffer to store the line into.
* @param len Size of the \a buffer array.
*
* @return The number of characters read, or -1 if an error occured.
* If the line was too long, -1 is returned and errno is set to
* EMSGSIZE.
* @return The number of characters read, or one of the GFSEC_ERR_*
* error codes.
*/
static ssize_t
get_line(FILE *f, char *buffer, size_t len)
@ -48,19 +47,16 @@ get_line(FILE *f, char *buffer, size_t len)
int c;
size_t n = 0;
if ( ! f || ! buffer ) {
errno = EINVAL;
return -1;
}
if ( ! f || ! buffer )
return GFSEC_ERR_INVALID_CALL;
while ( (c = fgetc(f)) != '\n' ) {
if ( c == EOF )
return -1;
return GFSEC_ERR_SYSTEM_ERROR;
if ( n >= len - 1 ) { /* Line too long */
errno = EMSGSIZE;
while ( (c = fgetc(f)) != '\n' && c != EOF ) ; /* Discard line */
return -1;
return GFSEC_ERR_INVALID_CONFIG;
}
buffer[n++] = (char) c;
@ -70,32 +66,34 @@ get_line(FILE *f, char *buffer, size_t len)
return n;
}
/**
* Reads the provided string up to the first '/' character.
* The pointer is advanced to that character.
*
* @return A newly allocated copy of the part of the string
* before the '/' character. If no '/' character was found,
* NULL is returned and errno is set to EBADMSG.
* The authority pointer receives a newly allocated copy of
* the string before the '/' character.
*
* @return 0 if successful, or one of the GFSEC_ERR_*
* error codes.
*/
static char *
parse_authority(const char **uri)
static int
parse_authority(const char **uri, char **authority)
{
char *slash, *authority = NULL;
char *slash;
if ( ! uri ) {
errno = EBADMSG;
return NULL;
}
if ( ! uri || ! authority )
return GFSEC_ERR_INVALID_CALL;
if ( (slash = strchr(*uri, '/')) ) {
authority = strndup(*uri, slash - *uri);
if ( ! (*authority = strndup(*uri, slash - *uri)) )
return GFSEC_ERR_SYSTEM_ERROR;
*uri = slash;
return 0;
}
else
errno = EBADMSG;
return authority;
return GFSEC_ERR_INVALID_CONFIG;
}
/**
@ -104,25 +102,29 @@ parse_authority(const char **uri)
* The pointer is advanced to that character, or to the
* terminating NULL byte.
*
* @return A newly allocated copy of the part of the string
* before the '?' character (or the whole string if no '?'
* was found).
* The path pointer receives a newly allocated copy of the part
* of the string before the '?' character (or the whole string
* if no '?' is found).
*
* @return 0 if the path was successfully parsed, or one of
* the GFSEC_ERR_* error codes.
*/
static char *
parse_path(const char **uri)
static int
parse_path(const char **uri, char **path)
{
char *qm, *path = NULL;
char *qm;
if ( ! uri ) {
errno = EBADMSG;
return NULL;
}
if ( ! uri )
return GFSEC_ERR_INVALID_CALL;
qm = strchrnul(*uri, '?');
path = strndup(*uri, qm - *uri);
if ( ! (*path = strndup(*uri, qm - *uri)) )
return GFSEC_ERR_SYSTEM_ERROR;
*uri = qm;
return path;
return 0;
}
/**
@ -130,23 +132,22 @@ parse_path(const char **uri)
*
* @param hex The encoded hash to parse.
* @param len The length of the \a hex buffer.
* @param[out] sha256 A pointer to a newly-allocated buffer
* to store the hash value.
*
* @return A newly allocated buffer containing the
* hash value, or NULL if an error occured.
* @return 0 if the hash value was successfully parsed,
* or one of the GFSEC_ERR_* error codes.
*/
static unsigned char *
parse_sha256(const char *hex, size_t len)
static int
parse_sha256(const char *hex, size_t len, unsigned char **sha256)
{
unsigned char *sha256 = NULL;
unsigned n;
if ( len != 64 ) {
errno = EBADMSG;
return NULL;
}
if ( len != 64 )
return GFSEC_ERR_INVALID_CONFIG;
if ( ! (sha256 = malloc(32)) )
return NULL;
if ( ! (*sha256 = malloc(32)) )
return GFSEC_ERR_SYSTEM_ERROR;
for ( n = 0; n < len; n++ ) {
unsigned char h, val;
@ -159,21 +160,20 @@ parse_sha256(const char *hex, size_t len)
val = h - 'A' + 10;
else if ( h >= 'a' && h <= 'f' )
val = h - 'a' + 10;
else
n = 99;
else {
/* Invalid character in the hash. */
free(*sha256);
*sha256 = NULL;
return GFSEC_ERR_INVALID_CONFIG;
}
if ( n % 2 == 0 )
sha256[n / 2] = val << 4;
(*sha256)[n / 2] = val << 4;
else
sha256[n / 2] += val;
(*sha256)[n / 2] += val;
}
if ( n == 100 ) {
free(sha256);
sha256 = NULL;
}
return sha256;
return 0;
}
/**
@ -182,8 +182,7 @@ parse_sha256(const char *hex, size_t len)
* value.
*
* @return 0 if a correctly formed name=value pair was
* found. Otherwise, -1 is returned and errno is set to
* EBADMSG.
* found, or one of the GFSEC_ERR_* error codes.
*/
static int
parse_parameter(const char **uri, gfsec_share_t *share)
@ -197,10 +196,8 @@ parse_parameter(const char **uri, gfsec_share_t *share)
if ( **uri == '\0' )
return 0; /* Silently ignore terminal delimiter. */
if ( ! (eq = strchr(*uri, '=')) ) {
errno = EBADMSG;
return -1;
}
if ( ! (eq = strchr(*uri, '=')) )
return GFSEC_ERR_INVALID_CONFIG;
if ( strncmp(*uri, "share", eq - *uri) == 0 ) {
amp = strchrnul(++eq, '&');
@ -210,8 +207,7 @@ parse_parameter(const char **uri, gfsec_share_t *share)
}
else if ( strncmp(*uri, "sha256", eq - *uri) == 0 ) {
amp = strchrnul(++eq, '&');
if ( ! (share->hash = parse_sha256(eq, amp - eq)) )
rc = -1;
rc = parse_sha256(eq, amp - eq, &(share->hash));
*uri = amp;
}
else { /* Skip unknown parameter. */
@ -255,23 +251,21 @@ get_share_number_from_path(const char *path)
/**
* Parses the specified URI into a share object.
*
* @return 0 if the URI was successfully parsed; -1 if an error
* occured or if the URI is malformed (in that last case, errno
* is set to EBADMSG).
* @return 0 if the URI was successfully parsed, or one of the
* GFSEC_ERR_* error codes.
*/
static int
parse_uri(const char *uri, gfsec_secret_t *secret)
{
gfsec_share_t *share;
const char *p = uri;
int rc = 0;
if ( ! uri || ! secret ) {
errno = EINVAL;
return -1;
}
if ( ! uri || ! secret )
return GFSEC_ERR_INVALID_CALL;
if ( ! (share = gfsec_share_new()) )
return -1;
return GFSEC_ERR_SYSTEM_ERROR;
if ( strncmp(p, "file://", 7) == 0 && (p += 7) )
share->scheme = GFSEC_SCHEME_FILE;
@ -281,82 +275,79 @@ parse_uri(const char *uri, gfsec_secret_t *secret)
share->scheme = GFSEC_SCHEME_LABEL;
else if ( strncmp(p, "mtp://", 6) == 0 && (p += 6) )
share->scheme = GFSEC_SCHEME_MTP;
else {
errno = EBADMSG;
goto bad_uri;
}
else
rc = GFSEC_ERR_INVALID_CONFIG;
if ( ! (share->authority = parse_authority(&p)) )
goto bad_uri;
if ( rc == 0 )
rc = parse_authority(&p, &(share->authority));
if ( ! (share->path = parse_path(&p)) )
goto bad_uri;
if ( rc == 0 )
rc = parse_path(&p, &(share->path));
while ( *p ) {
if ( parse_parameter(&p, share) == -1 )
goto bad_uri;
}
while ( rc == 0 && *p )
rc = parse_parameter(&p, share);
if ( ! gfsec_share_is_full(share) ) {
if ( (share->number = get_share_number_from_path(share->path)) == 0 ) {
errno = EBADMSG;
goto bad_uri;
}
if ( rc == 0 && ! gfsec_share_is_full(share) ) {
if ( (share->number = get_share_number_from_path(share->path)) == 0 )
rc = GFSEC_ERR_INVALID_CONFIG;
}
gfsec_secret_add_share(secret, share);
return 0;
if ( rc == 0 )
rc = gfsec_secret_add_share(secret, share);
bad_uri:
gfsec_share_free(share);
if ( rc != 0 )
gfsec_share_free(share);
return -1;
return rc;
}
/**
* Parses the specified configuration file.
*
* @return A newly allocated configuration object, or NULL if
* an error occured. If the configuration file contains an
* error, errno is set to EBADMSG.
* @return
* - 0 if successful;
* - GFSEC_ERR_INVALID_CALL if an invalid pointer was passed;
* - GFSEC_ERR_SYSTEM_ERROR if an error occured when reading
* the file or allocating memory (check errno for details);
* - GFSEC_ERR_INVALID_CONFIG if the configuration file does
* not meet the expected syntax;
* - GFSEC_ERR_TOO_MANY_SHARES if the configuration describes
* a secret with too many shares (more than 255).
*/
gfsec_secret_t *
gfsec_read_config(const char *filename)
int
gfsec_read_config(gfsec_secret_t **cfg, const char *filename)
{
FILE *f;
char buffer[MAX_LINE_LENGTH];
gfsec_secret_t *cfg;
int rc;
if ( ! filename ) {
errno = EINVAL;
return NULL;
}
if ( ! cfg || ! filename )
return GFSEC_ERR_INVALID_CALL;
if ( ! (f = fopen(filename, "r")) )
return NULL;
return GFSEC_ERR_SYSTEM_ERROR;
if ( ! (cfg = gfsec_secret_new()) ) {
if ( ! (*cfg = gfsec_secret_new()) ) {
fclose(f);
return NULL;
return GFSEC_ERR_SYSTEM_ERROR;
}
cfg->threshold = 2;
(*cfg)->threshold = 2;
rc = 0;
while ( rc >= 0 ) {
ssize_t n;
n = get_line(f, buffer, sizeof(buffer));
if ( n < 0 ) {
rc = feof(f) ? 0 : -1;
break;
}
if ( n == GFSEC_ERR_SYSTEM_ERROR && feof(f) )
break; /* End of file. */
else if ( n < 0 )
rc = n; /* Abort on any other error. */
else if ( n == 0 || buffer[0] == '#' )
; /* Comment or empty line */
else if ( strncmp("OUTFILE=", buffer, 8) == 0 ) {
if ( ! (cfg->filename = strdup(buffer + 8)) )
rc = -1;
if ( ! ((*cfg)->filename = strdup(buffer + 8)) )
rc = GFSEC_ERR_SYSTEM_ERROR;
}
else if ( strncmp("MINSHARES=", buffer, 10) == 0 ) {
char *endptr;
@ -364,22 +355,20 @@ gfsec_read_config(const char *filename)
l = strtoul(buffer + 10, &endptr, 10);
if ( *endptr != '\0' || l < 2 || l > 255 )
rc = -1, errno = EBADMSG;
rc = GFSEC_ERR_INVALID_CONFIG;
else
cfg->threshold = (unsigned char) l;
}
else if ( strncmp("URI=", buffer, 4) == 0 ) {
if ( parse_uri(&(buffer[4]), cfg) == -1 )
rc = -1;
(*cfg)->threshold = (unsigned char) l;
}
else if ( strncmp("URI=", buffer, 4) == 0 )
rc = parse_uri(&(buffer[4]), *cfg);
}
fclose(f);
if ( rc == -1 ) {
gfsec_secret_free(cfg);
cfg = NULL;
if ( rc != 0 ) {
gfsec_secret_free(*cfg);
*cfg = NULL;
}
return cfg;
return rc;
}

4
src/secretcfg.h

@ -25,8 +25,8 @@
extern "C" {
#endif
gfsec_secret_t *
gfsec_read_config(const char *);
int
gfsec_read_config(gfsec_secret_t **, const char *);
#ifdef __cplusplus
}

Loading…
Cancel
Save