911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * CDDL HEADER START
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * The contents of this file are subject to the terms of the
911106dfb16696472af8c1b7b4c554a829354fa8jm * Common Development and Distribution License (the "License").
911106dfb16696472af8c1b7b4c554a829354fa8jm * You may not use this file except in compliance with the License.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
911106dfb16696472af8c1b7b4c554a829354fa8jm * or http://www.opensolaris.org/os/licensing.
911106dfb16696472af8c1b7b4c554a829354fa8jm * See the License for the specific language governing permissions
911106dfb16696472af8c1b7b4c554a829354fa8jm * and limitations under the License.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * When distributing Covered Code, include this CDDL HEADER in each
911106dfb16696472af8c1b7b4c554a829354fa8jm * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
911106dfb16696472af8c1b7b4c554a829354fa8jm * If applicable, add the following below this CDDL HEADER, with the
911106dfb16696472af8c1b7b4c554a829354fa8jm * fields enclosed by brackets "[]" replaced with your own identifying
911106dfb16696472af8c1b7b4c554a829354fa8jm * information: Portions Copyright [yyyy] [name of copyright owner]
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * CDDL HEADER END
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
db1a607eb6d6da9154ca7153026a4fba0ee309eajoyce mcintosh * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
911106dfb16696472af8c1b7b4c554a829354fa8jm * Use is subject to license terms.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * Description: Module contains supporting functions used by functions
911106dfb16696472af8c1b7b4c554a829354fa8jm * defined in vs_svc.c. It also contains some internal(static) functions.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <stdarg.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <stdio.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <stdlib.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <unistd.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <errno.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <time.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <fcntl.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <syslog.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <ctype.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <strings.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <string.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <limits.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <pthread.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <sys/types.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <sys/socket.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <sys/debug.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <netinet/in.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm#include <arpa/inet.h>
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm#include "vs_incl.h"
911106dfb16696472af8c1b7b4c554a829354fa8jm#include "vs_icap.h"
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/* prototypes of local functions */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_option_request(vs_scan_ctx_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_send_option_req(vs_scan_ctx_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_read_option_resp(vs_scan_ctx_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_respmod_request(vs_scan_ctx_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_may_preview(vs_scan_ctx_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic char *vs_icap_find_ext(char *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_send_preview(vs_scan_ctx_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_send_respmod_hdr(vs_scan_ctx_t *, int);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_create_respmod_hdr(vs_scan_ctx_t *, int);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_uri_encode(char *, int, char *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_uri_illegal_char(char);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_read_respmod_resp(vs_scan_ctx_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_read_resp_code(vs_scan_ctx_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_read_hdr(vs_scan_ctx_t *, vs_hdr_t *, int);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_set_scan_result(vs_scan_ctx_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_read_encap_hdr(vs_scan_ctx_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void vs_icap_read_encap_data(vs_scan_ctx_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_create_repair_file(vs_scan_ctx_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_read_resp_body(vs_scan_ctx_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_read_body_chunk(vs_scan_ctx_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_send_chunk(vs_scan_ctx_t *, int);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_send_termination(vs_scan_ctx_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_readline(vs_scan_ctx_t *, char *, int);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_write(int, char *, int);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_read(int, char *, int);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/* process options and respmod headers */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void vs_icap_parse_hdrs(char, char *, char **, char **);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_opt_value(vs_scan_ctx_t *, int, char *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_opt_ext(vs_scan_ctx_t *, int, char *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_resp_violations(vs_scan_ctx_t *, int, char *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_resp_violation_rec(vs_scan_ctx_t *, int);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_resp_infection(vs_scan_ctx_t *, int, char *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_resp_virus_id(vs_scan_ctx_t *, int, char *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_resp_encap(vs_scan_ctx_t *, int, char *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_resp_istag(vs_scan_ctx_t *, int, char *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void vs_icap_istag_to_scanstamp(char *, vs_scanstamp_t);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/* Utility functions for handling OPTIONS data: vs_options_t */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void vs_icap_free_options(vs_options_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void vs_icap_copy_options(vs_options_t *, vs_options_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void vs_icap_update_options(vs_scan_ctx_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_compare_se(int, char *, int);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic iovec_t *vs_icap_make_strvec(char *, const char *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic iovec_t *vs_icap_copy_strvec(iovec_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int vs_icap_check_ext(char *, iovec_t *);
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void vs_icap_trimspace(char *);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/* icap response message */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic char *vs_icap_resp_str(int);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * local variables
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/* option headers - and handler functions */
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_hdr_t option_hdrs[] = {
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_OPT_SERVICE, "Service", vs_icap_opt_value},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_OPT_ISTAG, "ISTag", vs_icap_opt_value},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_OPT_METHODS, "Methods", vs_icap_opt_value},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_OPT_ALLOW, "Allow", vs_icap_opt_value},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_OPT_PREVIEW, "Preview", vs_icap_opt_value},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_OPT_XFER_PREVIEW, "Transfer-Preview", vs_icap_opt_ext},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_OPT_XFER_COMPLETE, "Transfer-Complete", vs_icap_opt_ext},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_OPT_MAX_CONNECTIONS, "Max-Connections", vs_icap_opt_value},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_OPT_TTL, "Options-TTL", vs_icap_opt_value},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_OPT_X_DEF_INFO, "X-Definition-Info", vs_icap_opt_value}
911106dfb16696472af8c1b7b4c554a829354fa8jm};
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/* resp hdrs - and handler functions */
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_hdr_t resp_hdrs[] = {
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_ENCAPSULATED, "Encapsulated", vs_icap_resp_encap},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_ISTAG, "ISTag", vs_icap_resp_istag},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_X_VIRUS_ID, "X-Virus-ID", vs_icap_resp_virus_id},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_X_INFECTION, "X-Infection-Found", vs_icap_resp_infection},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_X_VIOLATIONS, "X-Violations-Found", vs_icap_resp_violations}
911106dfb16696472af8c1b7b4c554a829354fa8jm};
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/* ICAP response code to string mappings */
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_resp_msg_t icap_resp[] = {
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_CONTINUE, "Continue"},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_OK, "OK"},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_CREATED, "Virus Detected and Repaired"},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_NO_CONT_NEEDED, "No Content Necessary"},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_BAD_REQ, "Bad Request"},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_FORBIDDEN, "File Infected and not repaired"},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_NOT_FOUND, "URI not found"},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_NOT_ALLOWED, "Method not allowed"},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_TIMEOUT, "Request timedout"},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_INTERNAL_ERR, "Internal server error"},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_NOT_IMPL, "Method not implemented"},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_SERV_UNAVAIL, "Service unavailable/overloaded"},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_ICAP_VER_UNSUPP, "ICAP version not supported"},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_SCAN_ERR, "Error scanning file"},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_NO_LICENSE, "No AV License"},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_RES_UNAVAIL, "Resource unavailable"},
911106dfb16696472af8c1b7b4c554a829354fa8jm { VS_RESP_UNKNOWN, "Unknown Error"},
911106dfb16696472af8c1b7b4c554a829354fa8jm};
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic const char *EXT_SEPARATOR = ",";
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic vs_options_t vs_options[VS_SE_MAX];
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic pthread_mutex_t vs_opt_mutex = PTHREAD_MUTEX_INITIALIZER;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_init
911106dfb16696472af8c1b7b4c554a829354fa8jm * initialization performed when daemon is loaded
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmvoid
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_init()
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) pthread_mutex_lock(&vs_opt_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) memset(vs_options, 0, sizeof (vs_options_t));
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) pthread_mutex_unlock(&vs_opt_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_fini
911106dfb16696472af8c1b7b4c554a829354fa8jm * cleanup performed when daemon is unloaded
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmvoid
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_fini()
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int i;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) pthread_mutex_lock(&vs_opt_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm for (i = 0; i < VS_SE_MAX; i++)
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_icap_free_options(&vs_options[i]);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) pthread_mutex_unlock(&vs_opt_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_config
911106dfb16696472af8c1b7b4c554a829354fa8jm *
53c110294d8b1410cabc201a52f94b03ae2ef448jm * When a new VSCAN configuration is specified, this will be
911106dfb16696472af8c1b7b4c554a829354fa8jm * called per scan engine. If the scan engine host or port has
911106dfb16696472af8c1b7b4c554a829354fa8jm * changed delete the vs_options entry for that scan engine.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmvoid
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_config(int idx, char *host, int port)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) pthread_mutex_lock(&vs_opt_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_compare_se(idx, host, port) != 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_icap_free_options(&vs_options[idx]);
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) strlcpy(vs_options[idx].vso_host, host,
911106dfb16696472af8c1b7b4c554a829354fa8jm sizeof (vs_options[idx].vso_host));
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_options[idx].vso_port = port;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) pthread_mutex_unlock(&vs_opt_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_scan_file
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Create a context (vs_scan_ctx_t) for the scan operation and initialize
911106dfb16696472af8c1b7b4c554a829354fa8jm * its options info. If the scan engine connection's IP or port is different
911106dfb16696472af8c1b7b4c554a829354fa8jm * from that held in vs_options the vs_options info is old and should
911106dfb16696472af8c1b7b4c554a829354fa8jm * be deleted (vs_icap_free_options). Otherwise, copy the vs_options info
911106dfb16696472af8c1b7b4c554a829354fa8jm * into the context.
911106dfb16696472af8c1b7b4c554a829354fa8jm * file name, size and decsriptor are also copied into the context
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Handle the ICAP protocol communication with the external Scan Engine to
911106dfb16696472af8c1b7b4c554a829354fa8jm * perform the scan
911106dfb16696472af8c1b7b4c554a829354fa8jm * - send an OPTIONS request if necessary
911106dfb16696472af8c1b7b4c554a829354fa8jm * - send RESPMOD scan request
911106dfb16696472af8c1b7b4c554a829354fa8jm * - process the response and save any cleaned data to file
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: result->vsr_rc
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmint
bfc848c632c9eacb2a640246d96e198f1b185c03jmvs_icap_scan_file(vs_eng_ctx_t *eng, char *devname, char *fname,
911106dfb16696472af8c1b7b4c554a829354fa8jm uint64_t fsize, int flags, vs_result_t *result)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_scan_ctx_t ctx;
911106dfb16696472af8c1b7b4c554a829354fa8jm int fd;
911106dfb16696472af8c1b7b4c554a829354fa8jm
bfc848c632c9eacb2a640246d96e198f1b185c03jm fd = open(devname, O_RDONLY);
bfc848c632c9eacb2a640246d96e198f1b185c03jm
bfc848c632c9eacb2a640246d96e198f1b185c03jm /* retry once on ENOENT as /dev link may not be created yet */
bfc848c632c9eacb2a640246d96e198f1b185c03jm if ((fd == -1) && (errno == ENOENT)) {
bfc848c632c9eacb2a640246d96e198f1b185c03jm (void) sleep(1);
bfc848c632c9eacb2a640246d96e198f1b185c03jm fd = open(devname, O_RDONLY);
bfc848c632c9eacb2a640246d96e198f1b185c03jm }
bfc848c632c9eacb2a640246d96e198f1b185c03jm
bfc848c632c9eacb2a640246d96e198f1b185c03jm if (fd == -1) {
bfc848c632c9eacb2a640246d96e198f1b185c03jm syslog(LOG_ERR, "Failed to open device %s - %s",
bfc848c632c9eacb2a640246d96e198f1b185c03jm devname, strerror(errno));
911106dfb16696472af8c1b7b4c554a829354fa8jm result->vsr_rc = VS_RESULT_ERROR;
911106dfb16696472af8c1b7b4c554a829354fa8jm return (result->vsr_rc);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* initialize context */
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) memset(&ctx, 0, sizeof (vs_scan_ctx_t));
bfc848c632c9eacb2a640246d96e198f1b185c03jm ctx.vsc_idx = eng->vse_eidx;
bfc848c632c9eacb2a640246d96e198f1b185c03jm (void) strlcpy(ctx.vsc_host, eng->vse_host, sizeof (ctx.vsc_host));
bfc848c632c9eacb2a640246d96e198f1b185c03jm ctx.vsc_port = eng->vse_port;
bfc848c632c9eacb2a640246d96e198f1b185c03jm ctx.vsc_sockfd = eng->vse_sockfd;
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx.vsc_fd = fd;
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx.vsc_fname = fname;
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx.vsc_fsize = fsize;
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx.vsc_flags = flags;
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx.vsc_result = result;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Hooks for future saving of repaired data, not yet in use */
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx.vsc_flags |= VS_NO_REPAIR;
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx.vsc_repair = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx.vsc_repair_fname = NULL;
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx.vsc_repair_fd = -1;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* take a copy of vs_options[idx] if they match the SE specified */
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) pthread_mutex_lock(&vs_opt_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_compare_se(ctx.vsc_idx, ctx.vsc_host, ctx.vsc_port) == 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_icap_copy_options(&ctx.vsc_options,
911106dfb16696472af8c1b7b4c554a829354fa8jm &vs_options[ctx.vsc_idx]);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) pthread_mutex_unlock(&vs_opt_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /*
911106dfb16696472af8c1b7b4c554a829354fa8jm * default the result to scan engine error.
911106dfb16696472af8c1b7b4c554a829354fa8jm * Any non scan-engine errors will reset it to VS_RESULT_ERROR
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jm result->vsr_rc = VS_RESULT_SE_ERROR;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* do the scan */
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_option_request(&ctx) == 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) vs_icap_respmod_request(&ctx);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) close(fd);
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_icap_free_options(&ctx.vsc_options);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (result->vsr_rc);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/* ********************************************************************* */
911106dfb16696472af8c1b7b4c554a829354fa8jm/* Local Function definitions */
911106dfb16696472af8c1b7b4c554a829354fa8jm/* ********************************************************************* */
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_option_request
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Send ICAP options message and await/process the response.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * The ICAP options request needs to be sent when a connection
911106dfb16696472af8c1b7b4c554a829354fa8jm * is first made with the scan engine. Unless the scan engine
911106dfb16696472af8c1b7b4c554a829354fa8jm * determines that the options will never expire (which we save
911106dfb16696472af8c1b7b4c554a829354fa8jm * as optione_req_time == -1) the request should be resent after
911106dfb16696472af8c1b7b4c554a829354fa8jm * the expiry time specified by the icap server.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: 0 - success
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 - error
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_option_request(vs_scan_ctx_t *ctx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm if (ctx->vsc_options.vso_req_time != -1 &&
911106dfb16696472af8c1b7b4c554a829354fa8jm ((time(0) - ctx->vsc_options.vso_req_time) >
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_options.vso_ttl)) {
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_send_option_req(ctx) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_read_option_resp(ctx) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_icap_update_options(ctx);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_send_option_req
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Send an OPTIONS request to the scan engine
911106dfb16696472af8c1b7b4c554a829354fa8jm * The Symantec ICAP server REQUIRES the resource name (VS_SERVICE_NAME)
911106dfb16696472af8c1b7b4c554a829354fa8jm * after the IP address, otherwise it closes the connection.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: 0 - success
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 - error
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_send_option_req(vs_scan_ctx_t *ctx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm char my_host_name[MAXHOSTNAMELEN];
911106dfb16696472af8c1b7b4c554a829354fa8jm int bufsp = VS_BUF_SZ;
911106dfb16696472af8c1b7b4c554a829354fa8jm char *buf0 = ctx->vsc_info.vsi_send_buf;
911106dfb16696472af8c1b7b4c554a829354fa8jm char *bufp = buf0;
911106dfb16696472af8c1b7b4c554a829354fa8jm int tlen;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (gethostname(my_host_name, sizeof (my_host_name)) != 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm /* non SE error */
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_result->vsr_rc = VS_RESULT_ERROR;
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) memset(ctx->vsc_info.vsi_send_buf, 0,
911106dfb16696472af8c1b7b4c554a829354fa8jm sizeof (ctx->vsc_info.vsi_send_buf));
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm tlen = snprintf(bufp, bufsp, "OPTIONS icap://%s:%d/%s %s\r\n",
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_host, ctx->vsc_port, VS_SERVICE_NAME, VS_ICAP_VER);
911106dfb16696472af8c1b7b4c554a829354fa8jm bufp += tlen;
911106dfb16696472af8c1b7b4c554a829354fa8jm bufsp -= tlen;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm tlen = snprintf(bufp, bufsp, "Host: %s\r\n\r\n", my_host_name);
911106dfb16696472af8c1b7b4c554a829354fa8jm bufp += tlen;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_write(ctx->vsc_sockfd, buf0, (bufp - buf0)) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_read_option_resp
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: 0 - success
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 - error
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_read_option_resp(vs_scan_ctx_t *ctx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_read_resp_code(ctx) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (ctx->vsc_info.vsi_icap_rc != VS_RESP_OK) {
911106dfb16696472af8c1b7b4c554a829354fa8jm syslog(LOG_ERR, "ICAP protocol error "
911106dfb16696472af8c1b7b4c554a829354fa8jm "- unexpected option response: %s",
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_icap_resp_str(ctx->vsc_info.vsi_icap_rc));
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_read_hdr(ctx, option_hdrs, VS_OPT_HDR_MAX) != 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((ctx->vsc_options.vso_scanstamp[0] == 0) ||
911106dfb16696472af8c1b7b4c554a829354fa8jm (ctx->vsc_options.vso_respmod == 0) ||
911106dfb16696472af8c1b7b4c554a829354fa8jm (ctx->vsc_options.vso_req_time == 0)) {
911106dfb16696472af8c1b7b4c554a829354fa8jm syslog(LOG_ERR, "ICAP protocol error "
911106dfb16696472af8c1b7b4c554a829354fa8jm "- missing or invalid option response hdrs");
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_respmod_request
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Send respmod request and receive and process ICAP response.
911106dfb16696472af8c1b7b4c554a829354fa8jm * Preview:
911106dfb16696472af8c1b7b4c554a829354fa8jm * ICAP allows for an optional "preview" request. In the option negotiation,
911106dfb16696472af8c1b7b4c554a829354fa8jm * the server may ask for a list of types to be previewed, or to be sent
911106dfb16696472af8c1b7b4c554a829354fa8jm * complete (no preview).
911106dfb16696472af8c1b7b4c554a829354fa8jm * This is advisory. It is ok to skip the preview step, as done when the file
911106dfb16696472af8c1b7b4c554a829354fa8jm * is smaller than the preview_len.
911106dfb16696472af8c1b7b4c554a829354fa8jm * Process Response:
911106dfb16696472af8c1b7b4c554a829354fa8jm * - read and parse the RESPMOD response headers
911106dfb16696472af8c1b7b4c554a829354fa8jm * - populate the result structure
911106dfb16696472af8c1b7b4c554a829354fa8jm * - read any encapsulated response headers
911106dfb16696472af8c1b7b4c554a829354fa8jm * - read any encapsulated response body and, if it represents cleaned
911106dfb16696472af8c1b7b4c554a829354fa8jm * file data, overwrite the file with it
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: 0 - success
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 - error
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_respmod_request(vs_scan_ctx_t *ctx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int rv;
911106dfb16696472af8c1b7b4c554a829354fa8jm int bytes_sent, send_len;
911106dfb16696472af8c1b7b4c554a829354fa8jm uint64_t resid = ctx->vsc_fsize;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_may_preview(ctx)) {
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((rv = vs_icap_send_preview(ctx)) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_read_respmod_resp(ctx) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (ctx->vsc_info.vsi_icap_rc != VS_RESP_CONTINUE)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm bytes_sent = rv;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* If > block (VS_BUF_SZ) remains, re-align to block boundary */
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((ctx->vsc_fsize - (uint64_t)bytes_sent) > VS_BUF_SZ) {
911106dfb16696472af8c1b7b4c554a829354fa8jm send_len = VS_BUF_SZ - bytes_sent;
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((rv = vs_icap_send_chunk(ctx, send_len)) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm bytes_sent += rv;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm resid -= (uint64_t)bytes_sent;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm } else {
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_send_respmod_hdr(ctx, 0) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Send the remainder of the file... */
911106dfb16696472af8c1b7b4c554a829354fa8jm while (resid) {
911106dfb16696472af8c1b7b4c554a829354fa8jm send_len = (resid > VS_BUF_SZ) ? VS_BUF_SZ : resid;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((rv = vs_icap_send_chunk(ctx, send_len)) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (rv == 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm resid -= (uint64_t)rv;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_send_termination(ctx) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* sending of ICAP request complete */
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_read_respmod_resp(ctx) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_may_preview
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: 1 - preview
911106dfb16696472af8c1b7b4c554a829354fa8jm * 0 - don't preview
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_may_preview(vs_scan_ctx_t *ctx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int in_list = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm char *ext;
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_options_t *opts = &ctx->vsc_options;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (opts->vso_xfer_how == VS_PREVIEW_NONE)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* if the file is smaller than the preview size, don't preview */
911106dfb16696472af8c1b7b4c554a829354fa8jm if (ctx->vsc_fsize < (uint64_t)ctx->vsc_options.vso_preview_len)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm switch (opts->vso_xfer_how) {
911106dfb16696472af8c1b7b4c554a829354fa8jm case VS_PREVIEW_ALL:
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm case VS_PREVIEW_EXCEPT:
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Preview everything except types in xfer_complete */
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((ext = vs_icap_find_ext(ctx->vsc_fname)) != 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm in_list = vs_icap_check_ext(ext,
911106dfb16696472af8c1b7b4c554a829354fa8jm opts->vso_xfer_complete);
911106dfb16696472af8c1b7b4c554a829354fa8jm return ((in_list) ? 0 : 1);
911106dfb16696472af8c1b7b4c554a829354fa8jm case VS_PREVIEW_LIST:
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Preview only types in the the xfer_preview list */
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((ext = vs_icap_find_ext(ctx->vsc_fname)) != 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm in_list = vs_icap_check_ext(ext,
911106dfb16696472af8c1b7b4c554a829354fa8jm opts->vso_xfer_preview);
911106dfb16696472af8c1b7b4c554a829354fa8jm return ((in_list) ? 1 : 0);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_find_ext
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: ptr to file's extension in fname
911106dfb16696472af8c1b7b4c554a829354fa8jm * 0 if no extension
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic char *
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_find_ext(char *fname)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm char *last_comp, *ext_str = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((last_comp = strrchr(fname, '/')) != 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm last_comp++;
911106dfb16696472af8c1b7b4c554a829354fa8jm } else {
911106dfb16696472af8c1b7b4c554a829354fa8jm last_comp = fname;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Get file extension */
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((ext_str = strrchr(last_comp, '.')) != 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm ext_str++;
911106dfb16696472af8c1b7b4c554a829354fa8jm if (strlen(ext_str) == 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm ext_str = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (ext_str);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_send_preview
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: bytes sent (preview + alignment)
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 - error
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_send_preview(vs_scan_ctx_t *ctx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int preview_len = ctx->vsc_options.vso_preview_len;
911106dfb16696472af8c1b7b4c554a829354fa8jm int bytes_sent;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Send a RESPMOD request with "preview" mode. */
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_send_respmod_hdr(ctx, 'P') < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((bytes_sent = vs_icap_send_chunk(ctx, preview_len)) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (bytes_sent < preview_len)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_send_termination(ctx) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (bytes_sent);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_send_respmod_hdr
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Create and send the RESPMOD request headers to the scan engine.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: 0 success
911106dfb16696472af8c1b7b4c554a829354fa8jm * < 0 error
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_send_respmod_hdr(vs_scan_ctx_t *ctx, int ispreview)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int len;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((len = vs_icap_create_respmod_hdr(ctx, ispreview)) == -1) {
911106dfb16696472af8c1b7b4c554a829354fa8jm /* non SE error */
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_result->vsr_rc = VS_RESULT_ERROR;
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* send the headers */
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_write(ctx->vsc_sockfd,
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_info.vsi_send_buf, len) < 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_create_respmod_hdr
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Create the RESPMOD request headers.
911106dfb16696472af8c1b7b4c554a829354fa8jm * - RESPMOD, Host, Allow, [Preview], Encapsulated, encapsulated request hdr,
911106dfb16696472af8c1b7b4c554a829354fa8jm * encapsulated response hdr
911106dfb16696472af8c1b7b4c554a829354fa8jm * Encapsulated data is sent separately subsequent to vs_icap_send_respmod_hdr,
911106dfb16696472af8c1b7b4c554a829354fa8jm * via calls to vs_icap_send_chunk.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * The Symantec ICAP server REQUIRES the resource name (VS_SERVICE_NAME)
911106dfb16696472af8c1b7b4c554a829354fa8jm * after the IP address, otherwise it closes the connection.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: -1 error
911106dfb16696472af8c1b7b4c554a829354fa8jm * length of headers data
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_create_respmod_hdr(vs_scan_ctx_t *ctx, int ispreview)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm char my_host_name[MAXHOSTNAMELEN];
911106dfb16696472af8c1b7b4c554a829354fa8jm int hbufsp = VS_BUF_SZ;
911106dfb16696472af8c1b7b4c554a829354fa8jm char *hbuf0 = ctx->vsc_info.vsi_send_buf;
911106dfb16696472af8c1b7b4c554a829354fa8jm char *hbufp = hbuf0;
911106dfb16696472af8c1b7b4c554a829354fa8jm char *encap_hdr, *encap_off0, *req_hdr, *res_hdr, *res_body;
911106dfb16696472af8c1b7b4c554a829354fa8jm int preview_len = ctx->vsc_options.vso_preview_len;
911106dfb16696472af8c1b7b4c554a829354fa8jm int tlen;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (gethostname(my_host_name, sizeof (my_host_name)) != 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm /* non SE error */
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_result->vsr_rc = VS_RESULT_ERROR;
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) memset(hbufp, 0, hbufsp);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* First the ICAP "request" part. (at offset 0) */
911106dfb16696472af8c1b7b4c554a829354fa8jm tlen = snprintf(hbufp, hbufsp, "RESPMOD icap://%s:%d/%s %s\r\n",
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_host, ctx->vsc_port, VS_SERVICE_NAME, VS_ICAP_VER);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (tlen >= hbufsp)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm hbufp += tlen; hbufsp -= tlen;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm tlen = snprintf(hbufp, hbufsp, "Host: %s\r\n", my_host_name);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (tlen >= hbufsp)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm hbufp += tlen; hbufsp -= tlen;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm tlen = snprintf(hbufp, hbufsp, "Allow: 204\r\n");
911106dfb16696472af8c1b7b4c554a829354fa8jm if (tlen >= hbufsp)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm hbufp += tlen; hbufsp -= tlen;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (ispreview) {
911106dfb16696472af8c1b7b4c554a829354fa8jm tlen = snprintf(hbufp, hbufsp, "Preview: %d\r\n", preview_len);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (tlen >= hbufsp)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm hbufp += tlen; hbufsp -= tlen;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Reserve space to later insert encapsulation offsets, & blank line */
911106dfb16696472af8c1b7b4c554a829354fa8jm encap_hdr = hbufp;
911106dfb16696472af8c1b7b4c554a829354fa8jm tlen = snprintf(hbufp, hbufsp, "%*.*s\r\n\r\n",
911106dfb16696472af8c1b7b4c554a829354fa8jm VS_ENCAP_SZ, VS_ENCAP_SZ, "");
911106dfb16696472af8c1b7b4c554a829354fa8jm if (tlen >= hbufsp)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm hbufp += tlen; hbufsp -= tlen;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* "offset zero" for the encapsulated parts that follow */
911106dfb16696472af8c1b7b4c554a829354fa8jm encap_off0 = hbufp;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Encapsulated request header (req_hdr) & blank line */
911106dfb16696472af8c1b7b4c554a829354fa8jm req_hdr = hbufp;
911106dfb16696472af8c1b7b4c554a829354fa8jm tlen = snprintf(hbufp, hbufsp, "GET http://%s", my_host_name);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (tlen >= hbufsp)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm hbufp += tlen; hbufsp -= tlen;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm tlen = vs_icap_uri_encode(hbufp, hbufsp, ctx->vsc_fname);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (tlen < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm hbufp += tlen; hbufsp -= tlen;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm tlen = snprintf(hbufp, hbufsp, " HTTP/1.1\r\n\r\n");
911106dfb16696472af8c1b7b4c554a829354fa8jm if (tlen >= hbufsp)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm hbufp += tlen; hbufsp -= tlen;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Encapsulated response header (res_hdr) & blank line */
911106dfb16696472af8c1b7b4c554a829354fa8jm res_hdr = hbufp;
911106dfb16696472af8c1b7b4c554a829354fa8jm tlen = snprintf(hbufp, hbufsp, "HTTP/1.1 200 OK\r\n");
911106dfb16696472af8c1b7b4c554a829354fa8jm if (tlen >= hbufsp)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm hbufp += tlen; hbufsp -= tlen;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm tlen = snprintf(hbufp, hbufsp, "Transfer-Encoding: chunked\r\n\r\n");
911106dfb16696472af8c1b7b4c554a829354fa8jm if (tlen >= hbufsp)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm hbufp += tlen; hbufsp -= tlen;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* response body section - res-body ("chunked data") */
911106dfb16696472af8c1b7b4c554a829354fa8jm res_body = hbufp;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Insert offsets in encap_hdr */
911106dfb16696472af8c1b7b4c554a829354fa8jm tlen = snprintf(encap_hdr, VS_ENCAP_SZ, "Encapsulated: "
911106dfb16696472af8c1b7b4c554a829354fa8jm "req-hdr=%d, res-hdr=%d, res-body=%d",
911106dfb16696472af8c1b7b4c554a829354fa8jm req_hdr - encap_off0, res_hdr - encap_off0, res_body - encap_off0);
911106dfb16696472af8c1b7b4c554a829354fa8jm /* undo the null from snprintf */
911106dfb16696472af8c1b7b4c554a829354fa8jm encap_hdr[tlen] = ' ';
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* return length */
911106dfb16696472af8c1b7b4c554a829354fa8jm return (hbufp - hbuf0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_read_respmod_resp
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Used for both preview and final RESMOD response
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_read_respmod_resp(vs_scan_ctx_t *ctx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_read_resp_code(ctx) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_read_hdr(ctx, resp_hdrs, VS_RESP_HDR_MAX) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (ctx->vsc_info.vsi_icap_rc == VS_RESP_CONTINUE) {
911106dfb16696472af8c1b7b4c554a829354fa8jm /* A VS_RESP_CONTINUE should not have encapsulated data */
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((ctx->vsc_info.vsi_res_hdr) ||
911106dfb16696472af8c1b7b4c554a829354fa8jm (ctx->vsc_info.vsi_res_body)) {
911106dfb16696472af8c1b7b4c554a829354fa8jm syslog(LOG_ERR, "ICAP protocol error -"
911106dfb16696472af8c1b7b4c554a829354fa8jm "- encapsulated data in Continue response");
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm } else {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_set_scan_result(ctx) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (ctx->vsc_info.vsi_res_hdr) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_read_encap_hdr(ctx) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (ctx->vsc_info.vsi_res_body)
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_icap_read_encap_data(ctx);
911106dfb16696472af8c1b7b4c554a829354fa8jm else if (ctx->vsc_result->vsr_rc == VS_RESULT_CLEANED)
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_result->vsr_rc = VS_RESULT_FORBIDDEN;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_read_resp_code
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Get the response code from the icap response messages
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_read_resp_code(vs_scan_ctx_t *ctx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm char *buf = ctx->vsc_info.vsi_recv_buf;
911106dfb16696472af8c1b7b4c554a829354fa8jm int retval;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Break on error or non-blank line. */
911106dfb16696472af8c1b7b4c554a829354fa8jm for (;;) {
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) memset(buf, '\0', VS_BUF_SZ);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((retval = vs_icap_readline(ctx, buf, VS_BUF_SZ)) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (retval && buf[0]) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (MATCH(buf, VS_ICAP_VER)) {
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) sscanf(buf+8, "%d",
911106dfb16696472af8c1b7b4c554a829354fa8jm &ctx->vsc_info.vsi_icap_rc);
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm syslog(LOG_ERR, "ICAP protocol error -"
911106dfb16696472af8c1b7b4c554a829354fa8jm "- expected ICAP/1.0, received %s", buf);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_read_hdr
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Reads all response headers.
911106dfb16696472af8c1b7b4c554a829354fa8jm * As each line is read it is parsed and passed to the appropriate handler.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: 0 - success
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 - error
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_read_hdr(vs_scan_ctx_t *ctx, vs_hdr_t hdrs[], int num_hdrs)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm char *buf = ctx->vsc_info.vsi_recv_buf;
911106dfb16696472af8c1b7b4c554a829354fa8jm int i, retval;
911106dfb16696472af8c1b7b4c554a829354fa8jm char *name, *val;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Break on error or blank line. */
911106dfb16696472af8c1b7b4c554a829354fa8jm for (;;) {
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) memset(buf, '\0', VS_BUF_SZ);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((retval = vs_icap_readline(ctx, buf, VS_BUF_SZ)) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Empty line (CR/LF) normal break */
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((retval == 0) || (!buf[0]))
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_icap_parse_hdrs(':', buf, &name, &val);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm for (i = 0; i < num_hdrs; i++) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (strcmp(name, hdrs[i].vsh_name) == 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm hdrs[i].vsh_func(ctx, hdrs[i].vsh_id, val);
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return ((retval >= 0) ? 0 : -1);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_set_scan_result
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Sets the vs_result_t vsr_rc from the icap_resp_code and
911106dfb16696472af8c1b7b4c554a829354fa8jm * any violation information in vs_result_t
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: 0 - success
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 - error
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_set_scan_result(vs_scan_ctx_t *ctx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int i;
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_result_t *result = ctx->vsc_result;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (!result->vsr_scanstamp)
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) strlcpy(result->vsr_scanstamp,
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_options.vso_scanstamp, sizeof (vs_scanstamp_t));
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm switch (ctx->vsc_info.vsi_icap_rc) {
911106dfb16696472af8c1b7b4c554a829354fa8jm case VS_RESP_NO_CONT_NEEDED:
911106dfb16696472af8c1b7b4c554a829354fa8jm result->vsr_rc = VS_RESULT_CLEAN;
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm case VS_RESP_OK:
911106dfb16696472af8c1b7b4c554a829354fa8jm /* if we have no violations , that means all ok */
911106dfb16696472af8c1b7b4c554a829354fa8jm if (result->vsr_nviolations == 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm result->vsr_rc = VS_RESULT_CLEAN;
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Any infections not repaired? */
911106dfb16696472af8c1b7b4c554a829354fa8jm result->vsr_rc = VS_RESULT_CLEANED;
911106dfb16696472af8c1b7b4c554a829354fa8jm for (i = 0; i < result->vsr_nviolations; i++) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (result->vsr_vrec[i].vr_res !=
911106dfb16696472af8c1b7b4c554a829354fa8jm VS_RES_FILE_REPAIRED) {
911106dfb16696472af8c1b7b4c554a829354fa8jm result->vsr_rc = VS_RESULT_FORBIDDEN;
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm case VS_RESP_CREATED :
911106dfb16696472af8c1b7b4c554a829354fa8jm /* file is repaired */
911106dfb16696472af8c1b7b4c554a829354fa8jm result->vsr_rc = VS_RESULT_CLEANED;
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm case VS_RESP_FORBIDDEN:
911106dfb16696472af8c1b7b4c554a829354fa8jm /* file is infected and could not be repaired */
911106dfb16696472af8c1b7b4c554a829354fa8jm result->vsr_rc = VS_RESULT_FORBIDDEN;
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm default:
911106dfb16696472af8c1b7b4c554a829354fa8jm syslog(LOG_ERR, "ICAP protocol error "
911106dfb16696472af8c1b7b4c554a829354fa8jm "- unsupported scan result: %s",
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_icap_resp_str(ctx->vsc_info.vsi_icap_rc));
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_read_encap_hdr
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Read the encapsulated response header to determine the length of
911106dfb16696472af8c1b7b4c554a829354fa8jm * encapsulated data and, in some cases, to detect the infected state
911106dfb16696472af8c1b7b4c554a829354fa8jm * of the file.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Use of http response code:
911106dfb16696472af8c1b7b4c554a829354fa8jm * Trend IWSS does not return virus information in the RESPMOD response
911106dfb16696472af8c1b7b4c554a829354fa8jm * headers unless the OPTIONAL "include X_Infection_Found" checkbox is
911106dfb16696472af8c1b7b4c554a829354fa8jm * checked and "disable_infected_url_block=yes" is set in intscan.ini.
911106dfb16696472af8c1b7b4c554a829354fa8jm * Thus if we haven't already detected the infected/cleaned status
911106dfb16696472af8c1b7b4c554a829354fa8jm * (ie if vsr_rc == VS_RESULT_CLEAN) we attempt to detect the
911106dfb16696472af8c1b7b4c554a829354fa8jm * infected/cleaned state of a file from a combination of the ICAP and
911106dfb16696472af8c1b7b4c554a829354fa8jm * http resp codes.
911106dfb16696472af8c1b7b4c554a829354fa8jm * Here are the response code values that Trend IWSS returns:
911106dfb16696472af8c1b7b4c554a829354fa8jm * - clean: icap resp = VS_RESP_NO_CONT_NEEDED
911106dfb16696472af8c1b7b4c554a829354fa8jm * - quarantine: icap resp = VS_RESP_OK, http resp = VS_RESP_FORBIDDEN
911106dfb16696472af8c1b7b4c554a829354fa8jm * - cleaned: icap resp = VS_RESP_OK, http resp = VS_RESP_OK
911106dfb16696472af8c1b7b4c554a829354fa8jm * For all other vendors' scan engines (so far) the infected/cleaned
911106dfb16696472af8c1b7b4c554a829354fa8jm * state of the file has already been detected from the RESPMOD
911106dfb16696472af8c1b7b4c554a829354fa8jm * response headers.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_read_encap_hdr(vs_scan_ctx_t *ctx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm char *buf = ctx->vsc_info.vsi_recv_buf;
911106dfb16696472af8c1b7b4c554a829354fa8jm char *name, *value;
911106dfb16696472af8c1b7b4c554a829354fa8jm int retval;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Break on error or blank line. */
911106dfb16696472af8c1b7b4c554a829354fa8jm for (;;) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((retval = vs_icap_readline(ctx, buf, VS_BUF_SZ)) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Empty line (CR/LF) normal break */
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((retval == 0) || (!buf[0]))
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (MATCH(buf, "HTTP/1.1")) {
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) sscanf(buf + 8, "%d",
911106dfb16696472af8c1b7b4c554a829354fa8jm &ctx->vsc_info.vsi_http_rc);
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_info.vsi_html_content = B_TRUE;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* if not yet detected infection, interpret http_rc */
911106dfb16696472af8c1b7b4c554a829354fa8jm if (ctx->vsc_result->vsr_rc == VS_RESULT_CLEAN) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((ctx->vsc_info.vsi_icap_rc == VS_RESP_OK) &&
911106dfb16696472af8c1b7b4c554a829354fa8jm (ctx->vsc_info.vsi_http_rc == VS_RESP_OK)) {
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_result->vsr_rc =
911106dfb16696472af8c1b7b4c554a829354fa8jm VS_RESULT_CLEANED;
911106dfb16696472af8c1b7b4c554a829354fa8jm } else {
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_result->vsr_rc =
911106dfb16696472af8c1b7b4c554a829354fa8jm VS_RESULT_FORBIDDEN;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm } else {
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_icap_parse_hdrs(':', buf, &name, &value);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (name && (MATCH(name, "Content-Length"))) {
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) sscanf(value, "%d",
911106dfb16696472af8c1b7b4c554a829354fa8jm &ctx->vsc_info.vsi_content_len);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_read_encap_data
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Read the encapsulated response data.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * If the response data represents cleaned file data (for an infected file)
911106dfb16696472af8c1b7b4c554a829354fa8jm * and VS_NO_REPAIR is not set, open repair file to save the reponse body
911106dfb16696472af8c1b7b4c554a829354fa8jm * data in. Set the repair flag in the scan context. The repair flag is used
911106dfb16696472af8c1b7b4c554a829354fa8jm * during the processing of the response data. If the flag is set then the
911106dfb16696472af8c1b7b4c554a829354fa8jm * data is written to file. If any error occurs which invalidates the repaired
911106dfb16696472af8c1b7b4c554a829354fa8jm * data file the repair flag gets reset to 0, and the data will be discarded.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * The result is reset to VS_RESULT_FORBIDDEN until all of the cleaned data
911106dfb16696472af8c1b7b4c554a829354fa8jm * has been successfully received and processed. It is then reset to
911106dfb16696472af8c1b7b4c554a829354fa8jm * VS_RESULT_CLEANED.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * If the data doesn't represent cleaned file data, or we cannot (or don't
911106dfb16696472af8c1b7b4c554a829354fa8jm * want to) write the cleaned data to file, the data is discarded (repair flag
911106dfb16696472af8c1b7b4c554a829354fa8jm * in ctx == 0).
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_read_encap_data(vs_scan_ctx_t *ctx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm if (ctx->vsc_result->vsr_rc == VS_RESULT_CLEANED) {
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_result->vsr_rc = VS_RESULT_FORBIDDEN;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (!(ctx->vsc_flags & VS_NO_REPAIR)) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_create_repair_file(ctx) == 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_repair = B_TRUE;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_read_resp_body handles errors internally;
911106dfb16696472af8c1b7b4c554a829354fa8jm * resets ctx->vsc_repair
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) vs_icap_read_resp_body(ctx);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (ctx->vsc_repair_fd != -1) {
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) close(ctx->vsc_repair_fd);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (ctx->vsc_repair) {
911106dfb16696472af8c1b7b4c554a829354fa8jm /* repair file contains the cleaned data */
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_result->vsr_rc = VS_RESULT_CLEANED;
911106dfb16696472af8c1b7b4c554a829354fa8jm } else {
911106dfb16696472af8c1b7b4c554a829354fa8jm /* error occured processing data. Remove repair file */
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) unlink(ctx->vsc_repair_fname);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_create_repair_file
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Create and open a file to save cleaned data in.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_create_repair_file(vs_scan_ctx_t *ctx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm if (ctx->vsc_repair_fname == NULL)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((ctx->vsc_repair_fd = open(ctx->vsc_repair_fname,
911106dfb16696472af8c1b7b4c554a829354fa8jm O_RDWR | O_CREAT | O_EXCL | O_TRUNC, 0644)) == -1) {
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_read_resp_body
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Repeatedly call vs_icap_read_body_chunk until it returns:
911106dfb16696472af8c1b7b4c554a829354fa8jm * 0 indicating that there's no more data to read or
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 indicating a read error -> reset ctx->vsc_repair 0
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: 0 success
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 error
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_read_resp_body(vs_scan_ctx_t *ctx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int retval;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm while ((retval = vs_icap_read_body_chunk(ctx)) > 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm ;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (retval < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_repair = B_FALSE;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (retval);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_read_body_chunk
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Read the chunk size, then read the chunk of data and write the
911106dfb16696472af8c1b7b4c554a829354fa8jm * data to file repair_fd (or discard it).
911106dfb16696472af8c1b7b4c554a829354fa8jm * If the data cannot be successfully written to file, set repair
911106dfb16696472af8c1b7b4c554a829354fa8jm * flag in ctx to 0, and discard all subsequent data.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: chunk size
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 on error
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_read_body_chunk(vs_scan_ctx_t *ctx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm char *lbuf = ctx->vsc_info.vsi_recv_buf;
911106dfb16696472af8c1b7b4c554a829354fa8jm unsigned int chunk_size, resid;
911106dfb16696472af8c1b7b4c554a829354fa8jm int rsize;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Read and parse the chunk size. */
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((vs_icap_readline(ctx, lbuf, VS_BUF_SZ) < 0) ||
911106dfb16696472af8c1b7b4c554a829354fa8jm (!sscanf(lbuf, "%x", &chunk_size))) {
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Read and save/discard chunk */
911106dfb16696472af8c1b7b4c554a829354fa8jm resid = chunk_size;
911106dfb16696472af8c1b7b4c554a829354fa8jm while (resid) {
911106dfb16696472af8c1b7b4c554a829354fa8jm rsize = (resid < VS_BUF_SZ) ? resid : VS_BUF_SZ;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((rsize = vs_icap_read(ctx->vsc_sockfd, lbuf, rsize)) <= 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (ctx->vsc_repair) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_write(ctx->vsc_repair_fd, lbuf, rsize) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_repair = B_FALSE;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm resid -= rsize;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Eat one CR/LF after the data */
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_readline(ctx, lbuf, VS_BUF_SZ) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (lbuf[0]) {
911106dfb16696472af8c1b7b4c554a829354fa8jm syslog(LOG_ERR, "ICAP protocol error - expected blank line");
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (chunk_size);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/* *********************************************************************** */
911106dfb16696472af8c1b7b4c554a829354fa8jm/* Utility read, write functions */
911106dfb16696472af8c1b7b4c554a829354fa8jm/* *********************************************************************** */
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_write
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Return: 0 if all data successfully written
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 otherwise
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_write(int fd, char *buf, int buflen)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm char *ptr = buf;
911106dfb16696472af8c1b7b4c554a829354fa8jm int resid = buflen;
911106dfb16696472af8c1b7b4c554a829354fa8jm int bytes_sent = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm while (resid > 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm errno = 0;
bfc848c632c9eacb2a640246d96e198f1b185c03jm bytes_sent = write(fd, ptr, resid);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (bytes_sent < 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (errno == EINTR)
911106dfb16696472af8c1b7b4c554a829354fa8jm continue;
911106dfb16696472af8c1b7b4c554a829354fa8jm else
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm resid -= bytes_sent;
911106dfb16696472af8c1b7b4c554a829354fa8jm ptr += bytes_sent;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_read
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: bytes_read (== len unless EOF hit before len bytes read)
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 error
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_read(int fd, char *buf, int len)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm char *ptr = buf;
911106dfb16696472af8c1b7b4c554a829354fa8jm int resid = len;
911106dfb16696472af8c1b7b4c554a829354fa8jm int bytes_read = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm while (resid > 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm errno = 0;
bfc848c632c9eacb2a640246d96e198f1b185c03jm bytes_read = read(fd, ptr, resid);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (bytes_read < 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (errno == EINTR)
911106dfb16696472af8c1b7b4c554a829354fa8jm continue;
911106dfb16696472af8c1b7b4c554a829354fa8jm else
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm resid -= bytes_read;
911106dfb16696472af8c1b7b4c554a829354fa8jm ptr += bytes_read;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (len - resid);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_send_chunk
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Send a "chunk" of file data, containing:
911106dfb16696472af8c1b7b4c554a829354fa8jm * - Length (in hex) CR/NL
911106dfb16696472af8c1b7b4c554a829354fa8jm * - [optiona data]
911106dfb16696472af8c1b7b4c554a829354fa8jm * - CR/NL
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: data length sent (not including encapsulation)
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 - error
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_send_chunk(vs_scan_ctx_t *ctx, int chunk_len)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm char *hdr = ctx->vsc_info.vsi_send_hdr;
911106dfb16696472af8c1b7b4c554a829354fa8jm char *dbuf = ctx->vsc_info.vsi_send_buf;
911106dfb16696472af8c1b7b4c554a829354fa8jm char *tail;
911106dfb16696472af8c1b7b4c554a829354fa8jm char head[VS_HDR_SZ + 1];
911106dfb16696472af8c1b7b4c554a829354fa8jm int nread = 0, hlen, tlen = 2;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (chunk_len > VS_BUF_SZ)
911106dfb16696472af8c1b7b4c554a829354fa8jm chunk_len = VS_BUF_SZ;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Read the data. */
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((nread = vs_icap_read(ctx->vsc_fd, dbuf, chunk_len)) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (nread > 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm /* wrap data in a header and trailer */
911106dfb16696472af8c1b7b4c554a829354fa8jm hlen = snprintf(head, sizeof (head), "%x\r\n", nread);
911106dfb16696472af8c1b7b4c554a829354fa8jm hdr += (VS_HDR_SZ - hlen);
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) memcpy(hdr, head, hlen);
db1a607eb6d6da9154ca7153026a4fba0ee309eajoyce mcintosh tail = dbuf + nread;
911106dfb16696472af8c1b7b4c554a829354fa8jm tail[0] = '\r';
911106dfb16696472af8c1b7b4c554a829354fa8jm tail[1] = '\n';
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_write(ctx->vsc_sockfd, hdr,
911106dfb16696472af8c1b7b4c554a829354fa8jm hlen + nread + tlen) < 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (nread);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_send_termination
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Send 0 length termination to scan engine: "0\r\n\r\n"
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: 0 - success
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 - error
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_send_termination(vs_scan_ctx_t *ctx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_write(ctx->vsc_sockfd, VS_TERMINATION,
911106dfb16696472af8c1b7b4c554a829354fa8jm strlen(VS_TERMINATION)) < 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_readline
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Read a line of response data from the socket. \n indicates end of line.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: bytes read
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 - error
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_readline(vs_scan_ctx_t *ctx, char *buf, int buflen)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm char c;
911106dfb16696472af8c1b7b4c554a829354fa8jm int i, retval;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm i = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm for (;;) {
911106dfb16696472af8c1b7b4c554a829354fa8jm errno = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm retval = recv(ctx->vsc_sockfd, &c, 1, 0);
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm if (retval < 0 && errno == EINTR)
911106dfb16696472af8c1b7b4c554a829354fa8jm continue;
911106dfb16696472af8c1b7b4c554a829354fa8jm
53c110294d8b1410cabc201a52f94b03ae2ef448jm if (retval <= 0) {
bfc848c632c9eacb2a640246d96e198f1b185c03jm if (vscand_get_state() != VS_STATE_SHUTDOWN) {
bfc848c632c9eacb2a640246d96e198f1b185c03jm syslog(LOG_ERR, "Error receiving data from "
bfc848c632c9eacb2a640246d96e198f1b185c03jm "Scan Engine: %s", strerror(errno));
bfc848c632c9eacb2a640246d96e198f1b185c03jm }
53c110294d8b1410cabc201a52f94b03ae2ef448jm return (-1);
53c110294d8b1410cabc201a52f94b03ae2ef448jm }
53c110294d8b1410cabc201a52f94b03ae2ef448jm
911106dfb16696472af8c1b7b4c554a829354fa8jm buf[i++] = c;
911106dfb16696472af8c1b7b4c554a829354fa8jm if (c == '\n')
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (i >= (buflen - 2))
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm buf[i] = '\0';
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* remove preceding and trailing whitespace */
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_icap_trimspace(buf);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (i);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/* ************************************************************************ */
911106dfb16696472af8c1b7b4c554a829354fa8jm/* HEADER processing */
911106dfb16696472af8c1b7b4c554a829354fa8jm/* ************************************************************************ */
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_parse_hdrs
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * parse an icap hdr line to find name and value
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_parse_hdrs(char delimiter, char *line, char **name, char **val)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm char *q = line;
911106dfb16696472af8c1b7b4c554a829354fa8jm int line_len;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* strip any spaces */
911106dfb16696472af8c1b7b4c554a829354fa8jm while (*q == ' ')
911106dfb16696472af8c1b7b4c554a829354fa8jm q++;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm *name = q;
911106dfb16696472af8c1b7b4c554a829354fa8jm *val = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* Empty line is normal termination */
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((line_len = strlen(line)) == 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((q = strchr(line, delimiter)) != 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm *q++ = '\0';
911106dfb16696472af8c1b7b4c554a829354fa8jm } else {
911106dfb16696472af8c1b7b4c554a829354fa8jm q = line + line_len;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* value part follows spaces */
911106dfb16696472af8c1b7b4c554a829354fa8jm while (*q == ' ')
911106dfb16696472af8c1b7b4c554a829354fa8jm q++;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm *val = q;
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_resp_violations
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jm/*ARGSUSED*/
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_resp_violations(vs_scan_ctx_t *ctx, int hdr_id, char *line)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int i, rv, vcnt;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) sscanf(line, "%d", &vcnt);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_result->vsr_nviolations =
911106dfb16696472af8c1b7b4c554a829354fa8jm (vcnt > VS_MAX_VIOLATIONS) ? VS_MAX_VIOLATIONS : vcnt;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_info.vsi_threat_hdr = VS_RESP_X_VIOLATIONS;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm for (i = 0; i < vcnt; i++) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((rv = vs_icap_resp_violation_rec(ctx, i)) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (rv);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_resp_violation_rec
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * take all violation data (up to VS_MAX_VIOLATIONS) and save it
911106dfb16696472af8c1b7b4c554a829354fa8jm * in violation_info.
911106dfb16696472af8c1b7b4c554a829354fa8jm * each violation has 4 lines of info: doc name, virus name,
911106dfb16696472af8c1b7b4c554a829354fa8jm * virus id and resolution
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_resp_violation_rec(vs_scan_ctx_t *ctx, int vr_idx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int vline;
911106dfb16696472af8c1b7b4c554a829354fa8jm int retval = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm char *buf = ctx->vsc_info.vsi_recv_buf;
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_vrec_t *vr;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vr_idx < VS_MAX_VIOLATIONS) {
911106dfb16696472af8c1b7b4c554a829354fa8jm vr = &ctx->vsc_result->vsr_vrec[vr_idx];
911106dfb16696472af8c1b7b4c554a829354fa8jm } else {
911106dfb16696472af8c1b7b4c554a829354fa8jm vr = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm for (vline = 0; vline < VS_VIOLATION_LINES; vline++) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((retval = vs_icap_readline(ctx, buf, VS_BUF_SZ)) < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* empty line? */
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((retval == 0) || (!buf[0]))
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vr) {
911106dfb16696472af8c1b7b4c554a829354fa8jm switch (vline) {
911106dfb16696472af8c1b7b4c554a829354fa8jm case 0: /* doc name */
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm case 1: /* Threat Description */
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) strlcpy(vr->vr_desc, buf,
911106dfb16696472af8c1b7b4c554a829354fa8jm VS_DESCRIPTION_MAX);
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm case 2: /* Problem ID */
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) sscanf(buf, "%d", &vr->vr_id);
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm case 3: /* Resolution */
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) sscanf(buf, "%d", &vr->vr_res);
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_opt_value
911106dfb16696472af8c1b7b4c554a829354fa8jm * given an icap options hdr string, process value
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_opt_value(vs_scan_ctx_t *ctx, int hdr_id, char *line)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int x;
911106dfb16696472af8c1b7b4c554a829354fa8jm long val;
911106dfb16696472af8c1b7b4c554a829354fa8jm char *end;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm switch (hdr_id) {
911106dfb16696472af8c1b7b4c554a829354fa8jm case VS_OPT_PREVIEW:
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) sscanf(line, "%d", &x);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (x < VS_MIN_PREVIEW_LEN)
911106dfb16696472af8c1b7b4c554a829354fa8jm x = VS_MIN_PREVIEW_LEN;
911106dfb16696472af8c1b7b4c554a829354fa8jm if (x > VS_BUF_SZ)
911106dfb16696472af8c1b7b4c554a829354fa8jm x = VS_BUF_SZ;
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_options.vso_preview_len = x;
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm case VS_OPT_TTL:
911106dfb16696472af8c1b7b4c554a829354fa8jm if (*line == 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_options.vso_req_time = -1;
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm val = strtol(line, &end, 10);
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((end != (line + strlen(line))) || (val < 0))
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_options.vso_ttl = val;
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_options.vso_req_time = time(0);
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm case VS_OPT_ALLOW:
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) sscanf(line, "%d", &ctx->vsc_options.vso_allow);
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm case VS_OPT_SERVICE:
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) strlcpy(ctx->vsc_options.vso_service, line,
911106dfb16696472af8c1b7b4c554a829354fa8jm VS_SERVICE_SZ);
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm case VS_OPT_X_DEF_INFO:
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) strlcpy(ctx->vsc_options.vso_defninfo, line,
911106dfb16696472af8c1b7b4c554a829354fa8jm VS_DEFN_SZ);
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm case VS_OPT_METHODS:
911106dfb16696472af8c1b7b4c554a829354fa8jm if (strstr(line, "RESPMOD") != NULL)
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_options.vso_respmod = 1;
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm case VS_OPT_ISTAG:
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_icap_istag_to_scanstamp(line,
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_options.vso_scanstamp);
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm default:
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_resp_istag
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Called to handle ISTAG when received in RESPMOD response.
911106dfb16696472af8c1b7b4c554a829354fa8jm * - populate result->vsr_scanstamp from istag
911106dfb16696472af8c1b7b4c554a829354fa8jm * - update the scanstamp in vs_options and log the update.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jm/*ARGSUSED*/
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_resp_istag(vs_scan_ctx_t *ctx, int hdr_id, char *line)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_icap_istag_to_scanstamp(line, ctx->vsc_result->vsr_scanstamp);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* update the scanstamp in vs_options */
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) pthread_mutex_lock(&vs_opt_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_compare_se(ctx->vsc_idx,
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_host, ctx->vsc_port) == 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (strcmp(vs_options[ctx->vsc_idx].vso_scanstamp,
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_result->vsr_scanstamp) != 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) strlcpy(vs_options[ctx->vsc_idx].vso_scanstamp,
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_result->vsr_scanstamp,
911106dfb16696472af8c1b7b4c554a829354fa8jm sizeof (vs_scanstamp_t));
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) pthread_mutex_unlock(&vs_opt_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_istag_to_scanstamp
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Copies istag into scanstamp, stripping leading and trailing
911106dfb16696472af8c1b7b4c554a829354fa8jm * quotes '"' from istag. If the istag is invalid (too long)
911106dfb16696472af8c1b7b4c554a829354fa8jm * scanstamp will be left unchanged.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_scanstamp_t is defined to be large enough to hold the
911106dfb16696472af8c1b7b4c554a829354fa8jm * istag plus a null terminator.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_istag_to_scanstamp(char *istag, vs_scanstamp_t scanstamp)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm char *p = istag;
911106dfb16696472af8c1b7b4c554a829354fa8jm int len;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* eliminate preceding '"' */
911106dfb16696472af8c1b7b4c554a829354fa8jm if (p[0] == '"')
911106dfb16696472af8c1b7b4c554a829354fa8jm ++p;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* eliminate trailing '"' */
911106dfb16696472af8c1b7b4c554a829354fa8jm len = strlen(p);
911106dfb16696472af8c1b7b4c554a829354fa8jm if (p[len - 1] == '"')
911106dfb16696472af8c1b7b4c554a829354fa8jm --len;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (len < sizeof (vs_scanstamp_t))
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) strlcpy(scanstamp, p, len + 1);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_opt_ext
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * read the transfer preview / transfer complete headers to
911106dfb16696472af8c1b7b4c554a829354fa8jm * determine which file types can be previewed
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_opt_ext(vs_scan_ctx_t *ctx, int hdr_id, char *line)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_options_t *opt = &ctx->vsc_options;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm switch (hdr_id) {
911106dfb16696472af8c1b7b4c554a829354fa8jm case VS_OPT_XFER_PREVIEW:
911106dfb16696472af8c1b7b4c554a829354fa8jm if (opt->vso_xfer_preview) {
911106dfb16696472af8c1b7b4c554a829354fa8jm free(opt->vso_xfer_preview);
911106dfb16696472af8c1b7b4c554a829354fa8jm opt->vso_xfer_preview = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm if (strstr(line, "*")) {
911106dfb16696472af8c1b7b4c554a829354fa8jm opt->vso_xfer_how = VS_PREVIEW_ALL;
911106dfb16696472af8c1b7b4c554a829354fa8jm } else {
911106dfb16696472af8c1b7b4c554a829354fa8jm opt->vso_xfer_preview = vs_icap_make_strvec
911106dfb16696472af8c1b7b4c554a829354fa8jm (line, EXT_SEPARATOR);
911106dfb16696472af8c1b7b4c554a829354fa8jm opt->vso_xfer_how = VS_PREVIEW_LIST;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm case VS_OPT_XFER_COMPLETE :
911106dfb16696472af8c1b7b4c554a829354fa8jm if (opt->vso_xfer_complete) {
911106dfb16696472af8c1b7b4c554a829354fa8jm free(opt->vso_xfer_complete);
911106dfb16696472af8c1b7b4c554a829354fa8jm opt->vso_xfer_complete = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm if (strstr(line, "*")) {
911106dfb16696472af8c1b7b4c554a829354fa8jm opt->vso_xfer_how = VS_PREVIEW_NONE;
911106dfb16696472af8c1b7b4c554a829354fa8jm } else {
911106dfb16696472af8c1b7b4c554a829354fa8jm opt->vso_xfer_complete = vs_icap_make_strvec
911106dfb16696472af8c1b7b4c554a829354fa8jm (line, EXT_SEPARATOR);
911106dfb16696472af8c1b7b4c554a829354fa8jm opt->vso_xfer_how = VS_PREVIEW_EXCEPT;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm default:
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_resp_infection
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * read the type, resolution and threat description for each
911106dfb16696472af8c1b7b4c554a829354fa8jm * reported violation and save in ctx->vsc_result
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jm/*ARGSUSED*/
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_resp_infection(vs_scan_ctx_t *ctx, int hdr_id, char *line)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm char *name, *val;
911106dfb16696472af8c1b7b4c554a829354fa8jm int i, got = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm int type = 0, res = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm char *desc = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_vrec_t *vr = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm for (i = 0; i < VS_INFECTION_FIELDS; i++) {
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_icap_parse_hdrs('=', line, &name, &val);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm switch (i) {
911106dfb16696472af8c1b7b4c554a829354fa8jm case 0:
911106dfb16696472af8c1b7b4c554a829354fa8jm if (MATCH(name, "Type")) {
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) sscanf(val, "%d", &type);
911106dfb16696472af8c1b7b4c554a829354fa8jm got++;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm case 1:
911106dfb16696472af8c1b7b4c554a829354fa8jm if (MATCH(name, "Resolution")) {
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) sscanf(val, "%d", &res);
911106dfb16696472af8c1b7b4c554a829354fa8jm got++;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm case 2:
911106dfb16696472af8c1b7b4c554a829354fa8jm if (MATCH(name, "Threat")) {
911106dfb16696472af8c1b7b4c554a829354fa8jm desc = val;
911106dfb16696472af8c1b7b4c554a829354fa8jm got++;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm default :
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((line = strstr(val, ";")))
911106dfb16696472af8c1b7b4c554a829354fa8jm line++;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (got != VS_INFECTION_FIELDS)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /*
911106dfb16696472af8c1b7b4c554a829354fa8jm * We may have info from an X-Violations-Found record, (which provides
911106dfb16696472af8c1b7b4c554a829354fa8jm * more complete information). If so, don't destroy what we have.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((ctx->vsc_result->vsr_nviolations == 0) ||
911106dfb16696472af8c1b7b4c554a829354fa8jm (ctx->vsc_info.vsi_threat_hdr < VS_RESP_X_INFECTION)) {
911106dfb16696472af8c1b7b4c554a829354fa8jm vr = &ctx->vsc_result->vsr_vrec[0];
911106dfb16696472af8c1b7b4c554a829354fa8jm vr->vr_id = type;
911106dfb16696472af8c1b7b4c554a829354fa8jm vr->vr_res = res;
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) strlcpy(vr->vr_desc, desc, VS_DESCRIPTION_MAX);
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_result->vsr_nviolations = 1;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_info.vsi_threat_hdr = VS_RESP_X_INFECTION;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_resp_virus_id
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * X-Virus-ID is defined as being a shorter alternative to X-Infection-Found.
911106dfb16696472af8c1b7b4c554a829354fa8jm * If we already have virus information, from either X-Infection-Found or
911106dfb16696472af8c1b7b4c554a829354fa8jm * X-Violations-Found, it will be more complete, so don't overwrite it with
911106dfb16696472af8c1b7b4c554a829354fa8jm * the info from X-Virus-ID.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jm/*ARGSUSED*/
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_resp_virus_id(vs_scan_ctx_t *ctx, int hdr_id, char *line)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_vrec_t *vr = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (ctx->vsc_result->vsr_nviolations == 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm vr = &ctx->vsc_result->vsr_vrec[0];
911106dfb16696472af8c1b7b4c554a829354fa8jm vr->vr_id = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm vr->vr_res = 0;
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) strlcpy(vr->vr_desc, line, VS_DESCRIPTION_MAX);
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_result->vsr_nviolations = 1;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_info.vsi_threat_hdr = VS_RESP_X_VIRUS_ID;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_resp_encap
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * get the encapsulated header info
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jm/*ARGSUSED*/
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_resp_encap(vs_scan_ctx_t *ctx, int hdr_id, char *line)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm if (strstr(line, "res-hdr"))
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_info.vsi_res_hdr = B_TRUE;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (strstr(line, "res-body"))
911106dfb16696472af8c1b7b4c554a829354fa8jm ctx->vsc_info.vsi_res_body = B_TRUE;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * Utility functions for handling OPTIONS data: vs_options_t
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_compare_scanstamp
911106dfb16696472af8c1b7b4c554a829354fa8jm * compare scanstamp with that stored for engine idx
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: 0 - if equal
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmint
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_compare_scanstamp(int idx, vs_scanstamp_t scanstamp)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int rc;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (!scanstamp || scanstamp[0] == '\0')
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) pthread_mutex_lock(&vs_opt_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm rc = strcmp(scanstamp, vs_options[idx].vso_scanstamp);
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) pthread_mutex_unlock(&vs_opt_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (rc);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_compare_se
911106dfb16696472af8c1b7b4c554a829354fa8jm * compare host and port with that stored for engine idx
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: 0 - if equal
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_compare_se(int idx, char *host, int port)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_options[idx].vso_port != port)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (strcmp(vs_options[idx].vso_host, host) != 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_free_options
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Free dynamic parts of vs_options_t: xfer_preview, xfer_complete
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_free_options(vs_options_t *options)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm if (options->vso_xfer_preview)
911106dfb16696472af8c1b7b4c554a829354fa8jm free(options->vso_xfer_preview);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (options->vso_xfer_complete)
911106dfb16696472af8c1b7b4c554a829354fa8jm free(options->vso_xfer_complete);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) memset(options, 0, sizeof (vs_options_t));
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_copy_options
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmvoid
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_copy_options(vs_options_t *to_opt, vs_options_t *from_opt)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm *to_opt = *from_opt;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (from_opt->vso_xfer_preview) {
911106dfb16696472af8c1b7b4c554a829354fa8jm to_opt->vso_xfer_preview =
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_icap_copy_strvec(from_opt->vso_xfer_preview);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (from_opt->vso_xfer_complete) {
911106dfb16696472af8c1b7b4c554a829354fa8jm to_opt->vso_xfer_complete =
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_icap_copy_strvec(from_opt->vso_xfer_complete);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_update_options
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_update_options(vs_scan_ctx_t *ctx)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm int idx = ctx->vsc_idx;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) pthread_mutex_lock(&vs_opt_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_compare_se(idx, ctx->vsc_host, ctx->vsc_port) == 0) {
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_icap_free_options(&vs_options[idx]);
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_icap_copy_options(&vs_options[idx], &ctx->vsc_options);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) pthread_mutex_unlock(&vs_opt_mutex);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_make_strvec
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Populate a iovec_t from line, where line is a string of 'sep'
911106dfb16696472af8c1b7b4c554a829354fa8jm * separated fields. Within the copy of line in the iovec_t each
911106dfb16696472af8c1b7b4c554a829354fa8jm * field will be null terminated with leading & trailing whitespace
911106dfb16696472af8c1b7b4c554a829354fa8jm * removed. This allows for fast searching.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * The iovec_t itself and the data it points to are allocated
911106dfb16696472af8c1b7b4c554a829354fa8jm * as a single chunk.
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic iovec_t *
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_make_strvec(char *line, const char *sep)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm iovec_t *vec;
911106dfb16696472af8c1b7b4c554a829354fa8jm char *tmp, *ctx;
911106dfb16696472af8c1b7b4c554a829354fa8jm int datalen, len;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm datalen = strlen(line) + 1;
911106dfb16696472af8c1b7b4c554a829354fa8jm len = sizeof (iovec_t) + datalen;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((vec = (iovec_t *)calloc(1, len)) == 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm vec->iov_len = len;
911106dfb16696472af8c1b7b4c554a829354fa8jm vec->iov_base = (char *)vec + sizeof (iovec_t);
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) strlcpy(vec->iov_base, line, datalen);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* tokenize data for easier searching */
911106dfb16696472af8c1b7b4c554a829354fa8jm for (tmp = strtok_r(vec->iov_base, sep, &ctx); tmp;
911106dfb16696472af8c1b7b4c554a829354fa8jm tmp = strtok_r(0, sep, &ctx)) {
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (vec);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_copy_strvec
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * allocate and copy strvec
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic iovec_t *
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_copy_strvec(iovec_t *from_vec)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm iovec_t *to_vec;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((to_vec = (iovec_t *)calloc(1, from_vec->iov_len)) == 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm bcopy(from_vec, to_vec, from_vec->iov_len);
911106dfb16696472af8c1b7b4c554a829354fa8jm to_vec->iov_base = (char *)to_vec + sizeof (iovec_t);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (to_vec);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_check_ext
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: 1 - if ext in strvec
911106dfb16696472af8c1b7b4c554a829354fa8jm * 0 - otherwise
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_check_ext(char *ext, iovec_t *vec)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm char *p, *end = (char *)vec + vec->iov_len;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm for (p = vec->iov_base; p < end; p += strlen(p) + 1) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (MATCH(ext, p))
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_resp_str
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic char *
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_resp_str(int rc)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm vs_resp_msg_t *p = icap_resp;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (rc < 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm rc = -rc;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm while (p->vsm_rc != VS_RESP_UNKNOWN) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (p->vsm_rc == rc)
911106dfb16696472af8c1b7b4c554a829354fa8jm break;
911106dfb16696472af8c1b7b4c554a829354fa8jm p++;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (p->vsm_msg);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_trimspace
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Trims whitespace from both the beginning and end of a string. This
911106dfb16696472af8c1b7b4c554a829354fa8jm * function alters the string buffer in-place.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Whitespaces found at the beginning of the string are eliminated by
911106dfb16696472af8c1b7b4c554a829354fa8jm * moving forward the start of the string at the first non-whitespace
911106dfb16696472af8c1b7b4c554a829354fa8jm * character.
911106dfb16696472af8c1b7b4c554a829354fa8jm * Whitespace found at the end of the string are overwritten with nulls.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic void
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_trimspace(char *buf)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm char *p = buf;
911106dfb16696472af8c1b7b4c554a829354fa8jm char *q = buf;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (buf == 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm return;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm while (*p && isspace(*p))
911106dfb16696472af8c1b7b4c554a829354fa8jm ++p;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm while ((*q = *p++) != 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm ++q;
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm if (q != buf) {
911106dfb16696472af8c1b7b4c554a829354fa8jm while ((--q, isspace(*q)) != 0)
911106dfb16696472af8c1b7b4c554a829354fa8jm *q = '\0';
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_uri_encode
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Encode uri data (eg filename) in accordance with RFC 2396
911106dfb16696472af8c1b7b4c554a829354fa8jm * 'Illegal' characters should be replaced with %hh, where hh is
911106dfb16696472af8c1b7b4c554a829354fa8jm * the hex value of the character. For example a space would be
911106dfb16696472af8c1b7b4c554a829354fa8jm * replaced with %20.
911106dfb16696472af8c1b7b4c554a829354fa8jm * Filenames are all already UTF-8 encoded. Any UTF-8 octects that
911106dfb16696472af8c1b7b4c554a829354fa8jm * are 'illegal' characters will be encoded as described above.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Paramaters: data - string to be encoded (NULL terminated)
911106dfb16696472af8c1b7b4c554a829354fa8jm * buf - output buffer (NULL terminated)
911106dfb16696472af8c1b7b4c554a829354fa8jm * size - size of output buffer
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: strlen of encoded data on success
911106dfb16696472af8c1b7b4c554a829354fa8jm * -1 size on error (contents of buf undefined)
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_uri_encode(char *buf, int size, char *data)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm unsigned char *iptr;
911106dfb16696472af8c1b7b4c554a829354fa8jm char *optr = buf;
911106dfb16696472af8c1b7b4c554a829354fa8jm int len = strlen(data);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* modify the data */
911106dfb16696472af8c1b7b4c554a829354fa8jm for (iptr = (unsigned char *)data; *iptr; iptr++) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (vs_icap_uri_illegal_char(*iptr)) {
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((len += 2) >= size)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm (void) sprintf(optr, "%%%0x", *iptr);
911106dfb16696472af8c1b7b4c554a829354fa8jm optr += 3;
911106dfb16696472af8c1b7b4c554a829354fa8jm } else {
911106dfb16696472af8c1b7b4c554a829354fa8jm if (len >= size)
911106dfb16696472af8c1b7b4c554a829354fa8jm return (-1);
911106dfb16696472af8c1b7b4c554a829354fa8jm *optr++ = *iptr;
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm }
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm *optr = '\0';
911106dfb16696472af8c1b7b4c554a829354fa8jm return (len);
911106dfb16696472af8c1b7b4c554a829354fa8jm}
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm/*
911106dfb16696472af8c1b7b4c554a829354fa8jm * vs_icap_uri_illegal_char
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * The following us-ascii characters (UTF-8 octets) are 'illegal':
911106dfb16696472af8c1b7b4c554a829354fa8jm * < > # % " { } | \ ^ [ ] ` space, 0x01 -> 0x1F & 0x7F
911106dfb16696472af8c1b7b4c554a829354fa8jm * All non us-ascii UTF-8 octets ( >= 0x80) are illegal.
911106dfb16696472af8c1b7b4c554a829354fa8jm *
911106dfb16696472af8c1b7b4c554a829354fa8jm * Returns: 1 if character is not allowed in a URI
911106dfb16696472af8c1b7b4c554a829354fa8jm * 0 otherwise
911106dfb16696472af8c1b7b4c554a829354fa8jm */
911106dfb16696472af8c1b7b4c554a829354fa8jmstatic int
911106dfb16696472af8c1b7b4c554a829354fa8jmvs_icap_uri_illegal_char(char c)
911106dfb16696472af8c1b7b4c554a829354fa8jm{
911106dfb16696472af8c1b7b4c554a829354fa8jm static const char *uri_illegal_chars = "<>#%\" {}|\\^[]`";
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* us-ascii non printable characters or non us-ascii */
911106dfb16696472af8c1b7b4c554a829354fa8jm if ((c <= 0x1F) || (c >= 0x7F))
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm /* us-ascii dis-allowed characters */
911106dfb16696472af8c1b7b4c554a829354fa8jm if (strchr(uri_illegal_chars, c))
911106dfb16696472af8c1b7b4c554a829354fa8jm return (1);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm return (0);
911106dfb16696472af8c1b7b4c554a829354fa8jm
911106dfb16696472af8c1b7b4c554a829354fa8jm}