⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 security-util.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 5 页
字号:
/* * Amanda, The Advanced Maryland Automatic Network Disk Archiver * Copyright (c) 1999 University of Maryland * All Rights Reserved. * * Permission to use, copy, modify, distribute, and sell this software and its * documentation for any purpose is hereby granted without fee, provided that * the above copyright notice appear in all copies and that both that * copyright notice and this permission notice appear in supporting * documentation, and that the name of U.M. not be used in advertising or * publicity pertaining to distribution of the software without specific, * written prior permission.  U.M. makes no representations about the * suitability of this software for any purpose.  It is provided "as is" * without express or implied warranty. * * U.M. DISCLAIMS ALL WARRANTIES WITH REGARD TO THIS SOFTWARE, INCLUDING ALL * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS, IN NO EVENT SHALL U.M. * BE LIABLE FOR ANY SPECIAL, INDIRECT OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE. * * Authors: the Amanda Development Team.  Its members are listed in a * file named AUTHORS, in the root directory of this distribution. *//* * $Id: security-util.c,v 1.25 2006/07/22 12:04:47 martinea Exp $ * * sec-security.c - security and transport over sec or a sec-like command. * * XXX still need to check for initial keyword on connect so we can skip * over shell garbage and other stuff that sec might want to spew out. */#include "amanda.h"#include "util.h"#include "event.h"#include "packet.h"#include "queue.h"#include "security.h"#include "security-util.h"#include "stream.h"#include "version.h"#include "sockaddr-util.h"/* * Magic values for sec_conn->handle */#define	H_TAKEN	-1		/* sec_conn->tok was already read */#define	H_EOF	-2		/* this connection has been shut down *//* * This is a queue of open connections */struct connq_s connq = {    TAILQ_HEAD_INITIALIZER(connq.tailq), 0};static int newhandle = 1;static int newevent = 1;/* * Local functions */static void recvpkt_callback(void *, void *, ssize_t);static void stream_read_callback(void *);static void stream_read_sync_callback(void *);static void sec_tcp_conn_read_cancel(struct tcp_conn *);static void sec_tcp_conn_read_callback(void *);/* * Authenticate a stream * Nothing needed for sec.  The connection is authenticated by secd * on startup. */intsec_stream_auth(    void *	s){    (void)s;	/* Quiet unused parameter warning */    return (0);}/* * Returns the stream id for this stream.  This is just the local * port. */intsec_stream_id(    void *	s){    struct sec_stream *rs = s;    assert(rs != NULL);    return (rs->handle);}/* * Setup to handle new incoming connections */voidsec_accept(    const security_driver_t *driver,    char       *(*conf_fn)(char *, void *),    int		in,    int		out,    void	(*fn)(security_handle_t *, pkt_t *),    void       *datap){    struct tcp_conn *rc;    rc = sec_tcp_conn_get("unknown",0);    rc->read = in;    rc->write = out;    rc->accept_fn = fn;    rc->driver = driver;    rc->conf_fn = conf_fn;    rc->datap = datap;    sec_tcp_conn_read(rc);}/* * frees a handle allocated by the above */voidsec_close(    void *	inst){    struct sec_handle *rh = inst;    assert(rh != NULL);    auth_debug(1, _("sec: closing handle to %s\n"), rh->hostname);    if (rh->rs != NULL) {	/* This may be null if we get here on an error */	stream_recvpkt_cancel(rh);	security_stream_close(&rh->rs->secstr);    }    /* keep us from getting here again */    rh->sech.driver = NULL;    amfree(rh->hostname);    amfree(rh);}/* * Called when a sec connection is finished connecting and is ready * to be authenticated. */voidsec_connect_callback(    void *	cookie){    struct sec_handle *rh = cookie;    event_release(rh->rs->ev_read);    rh->rs->ev_read = NULL;    event_release(rh->ev_timeout);    rh->ev_timeout = NULL;    (*rh->fn.connect)(rh->arg, &rh->sech, S_OK);}/* * Called if a connection times out before completion. */voidsec_connect_timeout(    void *	cookie){    struct sec_handle *rh = cookie;    event_release(rh->rs->ev_read);    rh->rs->ev_read = NULL;    event_release(rh->ev_timeout);    rh->ev_timeout = NULL;    (*rh->fn.connect)(rh->arg, &rh->sech, S_TIMEOUT);}voidsec_close_connection_none(    void *h,    char *hostname){    h = h;    hostname = hostname;    return;}/* * Transmit a packet. */ssize_tstream_sendpkt(    void *	cookie,    pkt_t *	pkt){    char *buf;    struct sec_handle *rh = cookie;    size_t len;    char *s;    assert(rh != NULL);    assert(pkt != NULL);    auth_debug(1, _("sec: stream_sendpkt: enter\n"));    if (rh->rc->prefix_packet)	s = rh->rc->prefix_packet(rh, pkt);    else	s = "";    len = strlen(pkt->body) + strlen(s) + 2;    buf = alloc(len);    buf[0] = (char)pkt->type;    strncpy(&buf[1], s, len - 1);    strncpy(&buf[1 + strlen(s)], pkt->body, (len - strlen(s) - 1));    if (strlen(s) > 0)	amfree(s);    auth_debug(1,     _("sec: stream_sendpkt: %s (%d) pkt_t (len %zu) contains:\n\n\"%s\"\n\n"),      pkt_type2str(pkt->type), pkt->type, strlen(pkt->body), pkt->body);    if (security_stream_write(&rh->rs->secstr, buf, len) < 0) {	security_seterror(&rh->sech, security_stream_geterror(&rh->rs->secstr));	return (-1);    }    amfree(buf);    return (0);}/* * Set up to receive a packet asyncronously, and call back when * it has been read. */voidstream_recvpkt(    void *	cookie,    void	(*fn)(void *, pkt_t *, security_status_t),    void *	arg,    int		timeout){    struct sec_handle *rh = cookie;    assert(rh != NULL);    auth_debug(1, _("sec: recvpkt registered for %s\n"), rh->hostname);    /*     * Reset any pending timeout on this handle     */    if (rh->ev_timeout != NULL)	event_release(rh->ev_timeout);    /*     * Negative timeouts mean no timeout     */    if (timeout < 0) {	rh->ev_timeout = NULL;    } else {	rh->ev_timeout = event_register((event_id_t)timeout, EV_TIME,		stream_recvpkt_timeout, rh);    }    rh->fn.recvpkt = fn;    rh->arg = arg;    security_stream_read(&rh->rs->secstr, recvpkt_callback, rh);}/* * This is called when a handle times out before receiving a packet. */voidstream_recvpkt_timeout(    void *	cookie){    struct sec_handle *rh = cookie;    assert(rh != NULL);    auth_debug(1, _("sec: recvpkt timeout for %s\n"), rh->hostname);    stream_recvpkt_cancel(rh);    (*rh->fn.recvpkt)(rh->arg, NULL, S_TIMEOUT);}/* * Remove a async receive request from the queue */voidstream_recvpkt_cancel(    void *	cookie){    struct sec_handle *rh = cookie;    auth_debug(1, _("sec: cancelling recvpkt for %s\n"), rh->hostname);    assert(rh != NULL);    security_stream_read_cancel(&rh->rs->secstr);    if (rh->ev_timeout != NULL) {	event_release(rh->ev_timeout);	rh->ev_timeout = NULL;    }}/* * Write a chunk of data to a stream.  Blocks until completion. */inttcpm_stream_write(    void *	s,    const void *buf,    size_t	size){    struct sec_stream *rs = s;    assert(rs != NULL);    assert(rs->rc != NULL);    auth_debug(1, _("sec: stream_write: writing %zu bytes to %s:%d %d\n"),		   size, rs->rc->hostname, rs->handle,		   rs->rc->write);    if (tcpm_send_token(rs->rc, rs->rc->write, rs->handle, &rs->rc->errmsg,			     buf, size)) {	security_stream_seterror(&rs->secstr, rs->rc->errmsg);	return (-1);    }    return (0);}/* * Submit a request to read some data.  Calls back with the given * function and arg when completed. */voidtcpm_stream_read(    void *	s,    void	(*fn)(void *, void *, ssize_t),    void *	arg){    struct sec_stream *rs = s;    assert(rs != NULL);    /*     * Only one read request can be active per stream.     */    if (rs->ev_read == NULL) {	rs->ev_read = event_register((event_id_t)rs->rc, EV_WAIT,	    stream_read_callback, rs);	sec_tcp_conn_read(rs->rc);    }    rs->fn = fn;    rs->arg = arg;}/* * Write a chunk of data to a stream.  Blocks until completion. */ssize_ttcpm_stream_read_sync(    void *	s,    void **	buf){    struct sec_stream *rs = s;    assert(rs != NULL);    /*     * Only one read request can be active per stream.     */    if (rs->ev_read != NULL) {	return -1;    }    rs->ev_read = event_register((event_id_t)rs->rc, EV_WAIT,        stream_read_sync_callback, rs);    sec_tcp_conn_read(rs->rc);    event_wait(rs->ev_read);    *buf = rs->rc->pkt;    return (rs->rc->pktlen);}/* * Cancel a previous stream read request.  It's ok if we didn't have a read * scheduled. */voidtcpm_stream_read_cancel(    void *	s){    struct sec_stream *rs = s;    assert(rs != NULL);    if (rs->ev_read != NULL) {	event_release(rs->ev_read);	rs->ev_read = NULL;	sec_tcp_conn_read_cancel(rs->rc);    }}/* * Transmits a chunk of data over a rsh_handle, adding * the necessary headers to allow the remote end to decode it. */ssize_ttcpm_send_token(    struct tcp_conn *rc,    int		fd,    int		handle,    char **	errmsg,    const void *buf,    size_t	len){    guint32		nethandle;    guint32		netlength;    struct iovec	iov[3];    int			nb_iov = 3;    int			rval;    char		*encbuf;    ssize_t		encsize;    assert(SIZEOF(netlength) == 4);    auth_debug(1, "tcpm_send_token: write %zd bytes to handle %d\n",	  len, handle);    /*     * Format is:     *   32 bit length (network byte order)     *   32 bit handle (network byte order)     *   data     */    netlength = htonl(len);    iov[0].iov_base = (void *)&netlength;    iov[0].iov_len = SIZEOF(netlength);    nethandle = htonl((guint32)handle);    iov[1].iov_base = (void *)&nethandle;    iov[1].iov_len = SIZEOF(nethandle);    encbuf = (char *)buf;    encsize = len;    if(len == 0) {	nb_iov = 2;    }    else {	if (rc->driver->data_encrypt == NULL) {	    iov[2].iov_base = (void *)buf;	    iov[2].iov_len = len;	} else {	    /* (the extra (void *) cast is to quiet type-punning warnings) */	    rc->driver->data_encrypt(rc, (void *)buf, len, (void **)(void *)&encbuf, &encsize);	    iov[2].iov_base = (void *)encbuf;	    iov[2].iov_len = encsize;	    netlength = htonl(encsize);	}        nb_iov = 3;    }    rval = net_writev(fd, iov, nb_iov);    if (len != 0 && rc->driver->data_encrypt != NULL && buf != encbuf) {	amfree(encbuf);    }    if (rval < 0) {	if (errmsg)            *errmsg = newvstrallocf(*errmsg, _("write error to: %s"),				   strerror(errno));        return (-1);    }    return (0);}/* *  return -1 on error *  return  0 on EOF:   *handle = H_EOF  && *size = 0    if socket closed *  return  0 on EOF:   *handle = handle && *size = 0    if stream closed *  return size     :   *handle = handle && *size = size for data read */ssize_ttcpm_recv_token(    struct tcp_conn    *rc,    int		fd,    int *	handle,    char **	errmsg,    char **	buf,    ssize_t *	size,    int		timeout){    unsigned int netint[2];    assert(SIZEOF(netint) == 8);    switch (net_read(fd, &netint, SIZEOF(netint), timeout)) {    case -1:	if (errmsg)	    *errmsg = newvstrallocf(*errmsg, _("recv error: %s"), strerror(errno));	auth_debug(1, _("tcpm_recv_token: A return(-1)\n"));	return (-1);    case 0:	*size = 0;	*handle = H_EOF;	*errmsg = newvstrallocf(*errmsg, _("SOCKET_EOF"));	auth_debug(1, _("tcpm_recv_token: A return(0)\n"));	return (0);    default:	break;    }    *size = (ssize_t)ntohl(netint[0]);    *handle = (int)ntohl(netint[1]);    /* amanda protocol packet can be above NETWORK_BLOCK_BYTES */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -