提交 bd4850df 编写于 作者: R Rich Salz 提交者: Rich Salz

RT4227: Range-check in apps.

Implement range-checking in all counts in apps.  Turns out only a couple
of cases were missing.  And make the range-checking code more strict.
Replace almost all opt_ulong() calls with opt_long()
Reviewed-by: NViktor Dukhovni <viktor@openssl.org>
上级 2bec39eb
...@@ -180,7 +180,7 @@ int dsaparam_main(int argc, char **argv) ...@@ -180,7 +180,7 @@ int dsaparam_main(int argc, char **argv)
argv = opt_rest(); argv = opt_rest();
if (argc == 1) { if (argc == 1) {
if (!opt_int(argv[0], &num)) if (!opt_int(argv[0], &num) || num < 0)
goto end; goto end;
/* generate a key */ /* generate a key */
numbits = num; numbits = num;
......
...@@ -58,6 +58,7 @@ ...@@ -58,6 +58,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <limits.h>
#include "apps.h" #include "apps.h"
#include <openssl/bio.h> #include <openssl/bio.h>
#include <openssl/err.h> #include <openssl/err.h>
...@@ -142,7 +143,7 @@ int enc_main(int argc, char **argv) ...@@ -142,7 +143,7 @@ int enc_main(int argc, char **argv)
int ret = 1, inl, nopad = 0; int ret = 1, inl, nopad = 0;
unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH]; unsigned char key[EVP_MAX_KEY_LENGTH], iv[EVP_MAX_IV_LENGTH];
unsigned char *buff = NULL, salt[PKCS5_SALT_LEN]; unsigned char *buff = NULL, salt[PKCS5_SALT_LEN];
unsigned long n; long n;
#ifdef ZLIB #ifdef ZLIB
int do_zlib = 0; int do_zlib = 0;
BIO *bzl = NULL; BIO *bzl = NULL;
...@@ -236,7 +237,8 @@ int enc_main(int argc, char **argv) ...@@ -236,7 +237,8 @@ int enc_main(int argc, char **argv)
k = i >= 1 && p[i] == 'k'; k = i >= 1 && p[i] == 'k';
if (k) if (k)
p[i] = '\0'; p[i] = '\0';
if (!opt_ulong(opt_arg(), &n)) if (!opt_long(opt_arg(), &n)
|| n < 0 || (k && n >= LONG_MAX / 1024))
goto opthelp; goto opthelp;
if (k) if (k)
n *= 1024; n *= 1024;
......
...@@ -57,6 +57,7 @@ ...@@ -57,6 +57,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <errno.h> #include <errno.h>
#include <ctype.h> #include <ctype.h>
#include <limits.h>
#include <openssl/bio.h> #include <openssl/bio.h>
#define MAX_OPT_HELP_WIDTH 30 #define MAX_OPT_HELP_WIDTH 30
...@@ -350,30 +351,16 @@ int opt_pair(const char *name, const OPT_PAIR* pairs, int *result) ...@@ -350,30 +351,16 @@ int opt_pair(const char *name, const OPT_PAIR* pairs, int *result)
return 0; return 0;
} }
/* See if cp looks like a hex number, in case user left off the 0x */
static int scanforhex(const char *cp)
{
if (*cp == '0' && (cp[1] == 'x' || cp[1] == 'X'))
return 16;
for (; *cp; cp++)
/* Look for a hex digit that isn't a regular digit. */
if (isxdigit(*cp) && !isdigit(*cp))
return 16;
return 0;
}
/* Parse an int, put it into *result; return 0 on failure, else 1. */ /* Parse an int, put it into *result; return 0 on failure, else 1. */
int opt_int(const char *value, int *result) int opt_int(const char *value, int *result)
{ {
const char *fmt = "%d"; long l;
int base = scanforhex(value);
if (!opt_long(value, &l))
if (base == 16) return 0;
fmt = "%x"; *result = (int)l;
else if (*value == '0') if (*result != l) {
fmt = "%o"; BIO_printf(bio_err, "%s: Value \"%s\" outside integer range\n",
if (sscanf(value, fmt, result) != 1) {
BIO_printf(bio_err, "%s: Can't parse \"%s\" as a number\n",
prog, value); prog, value);
return 0; return 0;
} }
...@@ -383,15 +370,22 @@ int opt_int(const char *value, int *result) ...@@ -383,15 +370,22 @@ int opt_int(const char *value, int *result)
/* Parse a long, put it into *result; return 0 on failure, else 1. */ /* Parse a long, put it into *result; return 0 on failure, else 1. */
int opt_long(const char *value, long *result) int opt_long(const char *value, long *result)
{ {
char *endptr; int oerrno = errno;
int base = scanforhex(value); long l;
char *endp;
*result = strtol(value, &endptr, base);
if (*endptr) { l = strtol(value, &endp, 0);
BIO_printf(bio_err, if (*endp
"%s: Bad char %c in number %s\n", prog, *endptr, value); || endp == value
|| ((l == LONG_MAX || l == LONG_MIN) && errno == ERANGE)
|| (l == 0 && errno != 0)) {
BIO_printf(bio_err, "%s: Can't parse \"%s\" as a number\n",
prog, value);
errno = oerrno;
return 0; return 0;
} }
*result = l;
errno = oerrno;
return 1; return 1;
} }
...@@ -400,15 +394,22 @@ int opt_long(const char *value, long *result) ...@@ -400,15 +394,22 @@ int opt_long(const char *value, long *result)
*/ */
int opt_ulong(const char *value, unsigned long *result) int opt_ulong(const char *value, unsigned long *result)
{ {
int oerrno = errno;
char *endptr; char *endptr;
int base = scanforhex(value); unsigned long l;
*result = strtoul(value, &endptr, base); l = strtoul(value, &endptr, 0);
if (*endptr) { if (*endptr
BIO_printf(bio_err, || endptr == value
"%s: Bad char %c in number %s\n", prog, *endptr, value); || ((l == ULONG_MAX) && errno == ERANGE)
|| (l == 0 && errno != 0)) {
BIO_printf(bio_err, "%s: Can't parse \"%s\" as an unsigned number\n",
prog, value);
errno = oerrno;
return 0; return 0;
} }
*result = l;
errno = oerrno;
return 1; return 1;
} }
...@@ -421,7 +422,7 @@ enum range { OPT_V_ENUM }; ...@@ -421,7 +422,7 @@ enum range { OPT_V_ENUM };
int opt_verify(int opt, X509_VERIFY_PARAM *vpm) int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
{ {
unsigned long ul; long l;
int i; int i;
ASN1_OBJECT *otmp; ASN1_OBJECT *otmp;
X509_PURPOSE *xptmp; X509_PURPOSE *xptmp;
...@@ -468,9 +469,10 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm) ...@@ -468,9 +469,10 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
X509_VERIFY_PARAM_set_depth(vpm, i); X509_VERIFY_PARAM_set_depth(vpm, i);
break; break;
case OPT_V_ATTIME: case OPT_V_ATTIME:
opt_ulong(opt_arg(), &ul); /* If we have C99 we could use intmax_t for all time_t values */
if (ul) opt_long(opt_arg(), &l);
X509_VERIFY_PARAM_set_time(vpm, (time_t)ul); if (l)
X509_VERIFY_PARAM_set_time(vpm, (time_t)l);
break; break;
case OPT_V_VERIFY_HOSTNAME: case OPT_V_VERIFY_HOSTNAME:
if (!X509_VERIFY_PARAM_set1_host(vpm, opt_arg(), 0)) if (!X509_VERIFY_PARAM_set1_host(vpm, opt_arg(), 0))
...@@ -558,11 +560,9 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm) ...@@ -558,11 +560,9 @@ int opt_verify(int opt, X509_VERIFY_PARAM *vpm)
int opt_next(void) int opt_next(void)
{ {
char *p; char *p;
char *endptr;
const OPTIONS *o; const OPTIONS *o;
int dummy; int ival;
int base; unsigned long uval;
long val;
/* Look at current arg; at end of the list? */ /* Look at current arg; at end of the list? */
arg = NULL; arg = NULL;
...@@ -613,10 +613,6 @@ int opt_next(void) ...@@ -613,10 +613,6 @@ int opt_next(void)
} }
/* Syntax-check value. */ /* Syntax-check value. */
/*
* Do some basic syntax-checking on the value. These tests aren't
* perfect (ignore range overflow) but they catch common failures.
*/
switch (o->valtype) { switch (o->valtype) {
default: default:
case 's': case 's':
...@@ -645,35 +641,27 @@ int opt_next(void) ...@@ -645,35 +641,27 @@ int opt_next(void)
return -1; return -1;
case 'p': case 'p':
case 'n': case 'n':
base = scanforhex(arg); if (!opt_int(arg, &ival)
val = strtol(arg, &endptr, base); || (o->valtype == 'p' && ival <= 0)) {
if (*endptr == '\0') {
if (o->valtype == 'p' && val <= 0) {
BIO_printf(bio_err, BIO_printf(bio_err,
"%s: Non-positive number \"%s\" for -%s\n", "%s: Non-positive number \"%s\" for -%s\n",
prog, arg, o->name); prog, arg, o->name);
return -1; return -1;
} }
break; break;
}
BIO_printf(bio_err,
"%s: Invalid number \"%s\" for -%s\n",
prog, arg, o->name);
return -1;
case 'u': case 'u':
base = scanforhex(arg); if (!opt_ulong(arg, &uval)) {
strtoul(arg, &endptr, base);
if (*endptr == '\0')
break;
BIO_printf(bio_err, BIO_printf(bio_err,
"%s: Invalid number \"%s\" for -%s\n", "%s: Invalid number \"%s\" for -%s\n",
prog, arg, o->name); prog, arg, o->name);
return -1; return -1;
}
break;
case 'f': case 'f':
case 'F': case 'F':
if (opt_format(arg, if (opt_format(arg,
o->valtype == 'F' ? OPT_FMT_PEMDER o->valtype == 'F' ? OPT_FMT_PEMDER
: OPT_FMT_ANY, &dummy)) : OPT_FMT_ANY, &ival))
break; break;
BIO_printf(bio_err, BIO_printf(bio_err,
"%s: Invalid format \"%s\" for -%s\n", "%s: Invalid format \"%s\" for -%s\n",
......
...@@ -121,7 +121,7 @@ int pkcs8_main(int argc, char **argv) ...@@ -121,7 +121,7 @@ int pkcs8_main(int argc, char **argv)
int informat = FORMAT_PEM, outformat = FORMAT_PEM, topk8 = 0, pbe_nid = -1; int informat = FORMAT_PEM, outformat = FORMAT_PEM, topk8 = 0, pbe_nid = -1;
int private = 0; int private = 0;
#ifndef OPENSSL_NO_SCRYPT #ifndef OPENSSL_NO_SCRYPT
unsigned long scrypt_N = 0, scrypt_r = 0, scrypt_p = 0; long scrypt_N = 0, scrypt_r = 0, scrypt_p = 0;
#endif #endif
prog = opt_init(argc, argv, pkcs8_options); prog = opt_init(argc, argv, pkcs8_options);
...@@ -210,15 +210,15 @@ int pkcs8_main(int argc, char **argv) ...@@ -210,15 +210,15 @@ int pkcs8_main(int argc, char **argv)
cipher = EVP_aes_256_cbc(); cipher = EVP_aes_256_cbc();
break; break;
case OPT_SCRYPT_N: case OPT_SCRYPT_N:
if (!opt_ulong(opt_arg(), &scrypt_N)) if (!opt_long(opt_arg(), &scrypt_N) || scrypt_N <= 0)
goto opthelp; goto opthelp;
break; break;
case OPT_SCRYPT_R: case OPT_SCRYPT_R:
if (!opt_ulong(opt_arg(), &scrypt_r)) if (!opt_long(opt_arg(), &scrypt_r) || scrypt_r <= 0)
goto opthelp; goto opthelp;
break; break;
case OPT_SCRYPT_P: case OPT_SCRYPT_P:
if (!opt_ulong(opt_arg(), &scrypt_p)) if (!opt_long(opt_arg(), &scrypt_p) || scrypt_p <= 0)
goto opthelp; goto opthelp;
break; break;
#endif #endif
......
...@@ -121,9 +121,7 @@ int rand_main(int argc, char **argv) ...@@ -121,9 +121,7 @@ int rand_main(int argc, char **argv)
argc = opt_num_rest(); argc = opt_num_rest();
argv = opt_rest(); argv = opt_rest();
if (argc != 1) if (argc != 1 || !opt_int(argv[0], &num) || num < 0)
goto opthelp;
if (sscanf(argv[0], "%d", &num) != 1 || num < 0)
goto opthelp; goto opthelp;
app_RAND_load_file(NULL, (inrand != NULL)); app_RAND_load_file(NULL, (inrand != NULL));
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册