/*
* sanitize a string into a printable format.
*
* Copyright (C) 1998-2002 D. Hugh Redelmeier.
* Copyright (C) 2003 Michael Richardson <mcr@freeswan.org>
*
* This library is free software; you can redistribute it and/or modify it
* under the terms of the GNU Library General Public License as published by
* the Free Software Foundation; either version 2 of the License, or (at your
* option) any later version. See <http://www.fsf.org/copyleft/lgpl.txt>.
*
* This library is distributed in the hope that it will be useful, but
* WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY
* or FITNESS FOR A PARTICULAR PURPOSE. See the GNU Library General Public
* License for more details.
*/
#include <ctype.h>
#include <string.h>
#include "libreswan.h"
#include "libreswan/passert.h"
#include "constants.h"
#include "lswlog.h"
/*
* Sanitize character string in situ: turns dangerous characters into \OOO.
* With a bit of work, we could use simpler reps for \\, \r, etc.,
* but this is only to protect against something that shouldn't be used.
* Truncate resulting string to what fits in buffer.
*/
void sanitize_string(char *buf, size_t size)
{
#define UGLY_WIDTH 4 /* width for ugly character: \OOO */
size_t added = 0;
char *p;
passert(size >= UGLY_WIDTH); /* need room to swing cat */
/*
* find right side of string to be sanitized and count
* number of columns to be added. Stop on end of string
* or lack of room for more result.
*/
for (p = buf; *p != '\0' && &p[added] < &buf[size - UGLY_WIDTH]; p++) {
unsigned char c = *p;
/*
* exception is that all veritical space just becomes
* white space
*/
if (c == '\n' || c == '\r') {
*p = ' ';
continue;
}
if (c == '\\' || !isprint(c))
added += UGLY_WIDTH - 1;
}
/*
* at this point, p points after last original character to be
* included. added is how many characters are added to sanitize.
* so p[added] will point after last sanitized character.
*/
p[added] = '\0';
/*
* scan backwards, copying characters to their new home
* and inserting the expansions for ugly characters.
*
* vertical space is changed to horizontal.
*
* It is finished when no more shifting is required.
* This is a predecrement loop.
*/
while (added != 0) {
char fmtd[UGLY_WIDTH + 1];
unsigned char c;
while ((c = *--p) != '\\' && isprint(c))
p[added] = c;
added -= UGLY_WIDTH - 1;
snprintf(fmtd, sizeof(fmtd), "\\%03o", c);
memcpy(p + added, fmtd, UGLY_WIDTH);
}
return;
#undef UGLY_WIDTH
}
#ifdef SANITIZESTRING_MAIN
#include <stdio.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
void regress(void);
void libreswan_passert_fail(const char *pred_str,
const char *file_str,
unsigned long line_no)
{
fprintf(stderr, "Passert failed: %s: %d, %s\n",
file_str, line_no, pred_str);
exit(20);
}
void pexpect_log(const char *pred_str,
const char *file_str, unsigned long line_no)
{
fprintf(stderr, "Pexpect dismayed: %s: %d, %s\n",
file_str, line_no, pred_str);
}
void switch_fail(int n,
const char *file_str, unsigned long line_no)
{
fprintf(stderr, "switch failed: %s: %d, %s\n",
file_str, line_no, pred_str);
exit(20);
}
int main(int argc, char *argv[])
{
if (argc < 2) {
fprintf(stderr, "Usage: %s -r\n", argv[0]);
exit(2);
}
if (streq(argv[1], "-r")) {
regress();
fprintf(stderr, "regress() returned?!?\n");
exit(1);
}
exit(0);
}
struct rtab {
char *input;
char *output; /* NULL means error expected */
} rtab[] = {
{ "there\001 \002 \003\n\rhi", "1.2.3.0" },
{ "there\231\t\n\177\\\n\rhi", "1.2.3.0" },
{ "there\001 \002 \003\n\rhi", "1.2.3.0" },
{ NULL, NULL }
};
void regress()
{
struct rtab *r;
ip_address a;
char in[256];
int count, status;
count = 0;
status = 0;
for (r = rtab; r->input != NULL; r++) {
strcpy(in, r->input);
sanitize(in, sizeof(in));
if (!streq(in, r->output)) {
printf("Item %d failed; %s vs %s\n",
count, in, r->output);
status = 1;
}
}
exit(status);
}
#endif /* SANITIZESTRING_MAIN */