On Tue, May 10, 2022 at 08:05:00AM +0200, Theo Buehler wrote: > This moves valid_filename() to validate.c and splits out a helper > portable_filename() which can be used from the RSC code. While moving > valid_filename() is not necessary, I thought it makes sense to keep the > two functions next to each other. > > I could not find a short name with valid_ prefix for portable_filename() > that I liked. valid_posix_filename()? valid_checklist_file()? > > Also, valid_filename() could be stricter and enforce that the unique '.' > is followed by a 3-letter suffix.
I would use valid_filename() for what you call portable_filename() and then introduce a mft_filename() in mft.c that does the extra check. Or maybe rename valid_filename() to valid_mft_filename(). I don't think we need to enforce the location of the dot. That is enforced by rtype_from_file_extension() and rtype_from_mftfile(). > Index: extern.h > =================================================================== > RCS file: /cvs/src/usr.sbin/rpki-client/extern.h,v > retrieving revision 1.134 > diff -u -p -r1.134 extern.h > --- extern.h 9 May 2022 17:19:32 -0000 1.134 > +++ extern.h 10 May 2022 06:03:19 -0000 > @@ -502,6 +502,8 @@ int valid_cert(const char *, struct au > int valid_roa(const char *, struct auth *, struct roa *); > int valid_filehash(int, const char *, size_t); > int valid_hash(unsigned char *, size_t, const char *, size_t); > +int portable_filename(const char *, size_t); > +int valid_filename(const char *, size_t); > int valid_uri(const char *, size_t, const char *); > int valid_origin(const char *, const char *); > int valid_x509(char *, X509_STORE_CTX *, X509 *, struct auth *, > Index: mft.c > =================================================================== > RCS file: /cvs/src/usr.sbin/rpki-client/mft.c,v > retrieving revision 1.61 > diff -u -p -r1.61 mft.c > --- mft.c 9 May 2022 17:02:34 -0000 1.61 > +++ mft.c 10 May 2022 06:03:19 -0000 > @@ -127,27 +127,6 @@ rtype_from_file_extension(const char *fn > } > > /* > - * Validate that a filename listed on a Manifest only contains characters > - * permitted in draft-ietf-sidrops-6486bis section 4.2.2 > - */ > -static int > -valid_filename(const char *fn, size_t len) > -{ > - const unsigned char *c; > - size_t i; > - > - for (c = fn, i = 0; i < len; i++, c++) > - if (!isalnum(*c) && *c != '-' && *c != '_' && *c != '.') > - return 0; > - > - c = memchr(fn, '.', len); > - if (c == NULL || c != memrchr(fn, '.', len)) > - return 0; > - > - return 1; > -} > - > -/* > * Check that the file is an ASPA, CER, CRL, GBR or a ROA. > * Returns corresponding rtype or RTYPE_INVALID on error. > */ > Index: rsc.c > =================================================================== > RCS file: /cvs/src/usr.sbin/rpki-client/rsc.c,v > retrieving revision 1.1 > diff -u -p -r1.1 rsc.c > --- rsc.c 9 May 2022 17:02:34 -0000 1.1 > +++ rsc.c 10 May 2022 06:03:46 -0000 > @@ -147,6 +147,8 @@ rsc_parse_filenamehash(struct parse *p, > } > > if (elemsz == 2) { > + ASN1_IA5STRING *filename; > + > file = sk_ASN1_TYPE_value(seq, i++); > if (file->type != V_ASN1_IA5STRING) { > warnx("%s: RSC FileNameAndHash: want ASN.1 IA5 string," > @@ -154,25 +156,17 @@ rsc_parse_filenamehash(struct parse *p, > ASN1_tag2str(file->type), file->type); > goto out; > } > - fn = strndup((const char *)file->value.ia5string->data, > - file->value.ia5string->length); > - if (fn == NULL) > - err(1, NULL); > > - /* > - * filename must confirm to portable file name character set > - * XXX: use valid_filename() instead > - */ > - if (strchr(fn, '/') != NULL) { > - warnx("%s: path components disallowed in filename: %s", > - p->fn, fn); > - goto out; > - } > - if (strchr(fn, '\n') != NULL) { > - warnx("%s: newline disallowed in filename: %s", > - p->fn, fn); > + filename = file->value.ia5string; > + > + if (!portable_filename(filename->data, filename->length)) { > + warnx("%s: RSC FileNameAndHash: bad filename", p->fn); > goto out; > } > + > + fn = strndup(filename->data, filename->length); > + if (fn == NULL) > + err(1, NULL); > } > > /* Now hash value. */ > Index: validate.c > =================================================================== > RCS file: /cvs/src/usr.sbin/rpki-client/validate.c,v > retrieving revision 1.31 > diff -u -p -r1.31 validate.c > --- validate.c 21 Apr 2022 09:53:07 -0000 1.31 > +++ validate.c 10 May 2022 06:03:19 -0000 > @@ -275,6 +275,42 @@ valid_hash(unsigned char *buf, size_t le > } > > /* > + * Validate that a filename only contains characters from the POSIX portable > + * filename character set [A-Za-z0-9._-], see IEEE Std 1003.1-2013, 3.278. > + */ > +int > +portable_filename(const char *fn, size_t len) > +{ > + const unsigned char *c; > + size_t i; > + > + for (c = fn, i = 0; i < len; i++, c++) > + if (!isalnum(*c) && *c != '-' && *c != '_' && *c != '.') > + return 0; > + return 1; > +} > + > +/* > + * Validate that a filename listed on a Manifest only contains characters > + * permitted in draft-ietf-sidrops-6486bis section 4.2.2 > + * Also ensure that there is exactly one '.'. > + */ > +int > +valid_filename(const char *fn, size_t len) > +{ > + const unsigned char *c; > + > + if (!portable_filename(fn, len)) > + return 0; > + > + c = memchr(fn, '.', len); > + if (c == NULL || c != memrchr(fn, '.', len)) > + return 0; > + > + return 1; > +} > + > +/* > * Validate a URI to make sure it is pure ASCII and does not point backwards > * or doing some other silly tricks. To enforce the protocol pass either > * https:// or rsync:// as proto, if NULL is passed no protocol is enforced. > -- :wq Claudio