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

📄 security-util.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 5 页
字号:
}/* * Transmit a packet.  Add security information first. */ssize_tudpbsd_sendpkt(    void *	cookie,    pkt_t *	pkt){    struct sec_handle *rh = cookie;    struct passwd *pwd;    assert(rh != NULL);    assert(pkt != NULL);    auth_debug(1, _("udpbsd_sendpkt: enter\n"));    /*     * Initialize this datagram, and add the header     */    dgram_zero(&rh->udp->dgram);    dgram_cat(&rh->udp->dgram, pkthdr2str(rh, pkt));    /*     * Add the security info.  This depends on which kind of packet we're     * sending.     */    switch (pkt->type) {    case P_REQ:	/*	 * Requests get sent with our username in the body	 */	if ((pwd = getpwuid(geteuid())) == NULL) {	    security_seterror(&rh->sech,		_("can't get login name for my uid %ld"), (long)getuid());	    return (-1);	}	dgram_cat(&rh->udp->dgram, _("SECURITY USER %s\n"), pwd->pw_name);	break;    default:	break;    }    /*     * Add the body, and send it     */    dgram_cat(&rh->udp->dgram, pkt->body);    auth_debug(1,     _("sec: udpbsd_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 (dgram_send_addr(&rh->peer, &rh->udp->dgram) != 0) {	security_seterror(&rh->sech,	    _("send %s to %s failed: %s"), pkt_type2str(pkt->type),	    rh->hostname, strerror(errno));	return (-1);    }    return (0);}voidudp_close(    void *	cookie){    struct sec_handle *rh = cookie;    if (rh->proto_handle == NULL) {	return;    }    auth_debug(1, _("udp: close handle '%s'\n"), rh->proto_handle);    udp_recvpkt_cancel(rh);    if (rh->next) {	rh->next->prev = rh->prev;    }    else {	rh->udp->bh_last = rh->prev;    }    if (rh->prev) {	rh->prev->next = rh->next;    }    else {	rh->udp->bh_first = rh->next;    }    amfree(rh->proto_handle);    amfree(rh->hostname);    amfree(rh);}/* * Set up to receive a packet asynchronously, and call back when it has * been read. */voidudp_recvpkt(    void *	cookie,    void	(*fn)(void *, pkt_t *, security_status_t),    void *	arg,    int		timeout){    struct sec_handle *rh = cookie;    auth_debug(1, _("udp_recvpkt(cookie=%p, fn=%p, arg=%p, timeout=%u)\n"),		   cookie, fn, arg, timeout);    assert(rh != NULL);    assert(fn != NULL);    /*     * Subsequent recvpkt calls override previous ones     */    if (rh->ev_read == NULL) {	udp_addref(rh->udp, &udp_netfd_read_callback);	rh->ev_read = event_register(rh->event_id, EV_WAIT,	    udp_recvpkt_callback, rh);    }    if (rh->ev_timeout != NULL)	event_release(rh->ev_timeout);    if (timeout < 0)	rh->ev_timeout = NULL;    else	rh->ev_timeout = event_register((event_id_t)timeout, EV_TIME,					udp_recvpkt_timeout, rh);    rh->fn.recvpkt = fn;    rh->arg = arg;}/* * Remove a async receive request on this handle from the queue. * If it is the last one to be removed, then remove the event * handler for our network fd */voidudp_recvpkt_cancel(    void *	cookie){    struct sec_handle *rh = cookie;    assert(rh != NULL);    if (rh->ev_read != NULL) {	udp_delref(rh->udp);	event_release(rh->ev_read);	rh->ev_read = NULL;    }    if (rh->ev_timeout != NULL) {	event_release(rh->ev_timeout);	rh->ev_timeout = NULL;    }}/* * This is called when a handle is woken up because data read off of the * net is for it. */voidudp_recvpkt_callback(    void *	cookie){    struct sec_handle *rh = cookie;    void (*fn)(void *, pkt_t *, security_status_t);    void *arg;    auth_debug(1, _("udp: receive handle '%s' netfd '%s'\n"),		   rh->proto_handle, rh->udp->handle);    assert(rh != NULL);    /* if it doesn't correspond to this handle, something is wrong */    assert(strcmp(rh->proto_handle, rh->udp->handle) == 0);    /* if it didn't come from the same host/port, forget it */    if (cmp_sockaddr(&rh->peer, &rh->udp->peer, 0) != 0) {	amfree(rh->udp->handle);	dbprintf(_("not from same host\n"));	dump_sockaddr(&rh->peer);	dump_sockaddr(&rh->udp->peer);	return;    }    /*     * We need to cancel the recvpkt request before calling the callback     * because the callback may reschedule us.     */    fn = rh->fn.recvpkt;    arg = rh->arg;    udp_recvpkt_cancel(rh);    /*     * Check the security of the packet.  If it is bad, then pass NULL     * to the packet handling function instead of a packet.     */    if (rh->udp->recv_security_ok &&	rh->udp->recv_security_ok(rh, &rh->udp->pkt) < 0) {	(*fn)(arg, NULL, S_ERROR);    } else {	(*fn)(arg, &rh->udp->pkt, S_OK);    }}/* * This is called when a handle times out before receiving a packet. */voidudp_recvpkt_timeout(    void *	cookie){    struct sec_handle *rh = cookie;    void (*fn)(void *, pkt_t *, security_status_t);    void *arg;    assert(rh != NULL);    assert(rh->ev_timeout != NULL);    fn = rh->fn.recvpkt;    arg = rh->arg;    udp_recvpkt_cancel(rh);    (*fn)(arg, NULL, S_TIMEOUT);}/* * Given a hostname and a port, setup a udp_handle */intudp_inithandle(    udp_handle_t *	udp,    struct sec_handle *	rh,    char *              hostname,    struct sockaddr_storage *addr,    in_port_t		port,    char *		handle,    int			sequence){    /*     * Save the hostname and port info     */    auth_debug(1, _("udp_inithandle port %u handle %s sequence %d\n"),		   (unsigned int)ntohs(port), handle, sequence);    assert(addr != NULL);    rh->hostname = stralloc(hostname);    copy_sockaddr(&rh->peer, addr);    SS_SET_PORT(&rh->peer, port);    rh->prev = udp->bh_last;    if (udp->bh_last) {	rh->prev->next = rh;    }    if (!udp->bh_first) {	udp->bh_first = rh;    }    rh->next = NULL;    udp->bh_last = rh;    rh->sequence = sequence;    rh->event_id = (event_id_t)newevent++;    amfree(rh->proto_handle);    rh->proto_handle = stralloc(handle);    rh->fn.connect = NULL;    rh->arg = NULL;    rh->ev_read = NULL;    rh->ev_timeout = NULL;    auth_debug(1, _("udp: adding handle '%s'\n"), rh->proto_handle);    return(0);}/* * Callback for received packets.  This is the function bsd_recvpkt * registers with the event handler.  It is called when the event handler * realizes that data is waiting to be read on the network socket. */voidudp_netfd_read_callback(    void *	cookie){    struct udp_handle *udp = cookie;    struct sec_handle *rh;    int a;    char hostname[NI_MAXHOST];    in_port_t port;    char *errmsg = NULL;    int result;    auth_debug(1, _("udp_netfd_read_callback(cookie=%p)\n"), cookie);    assert(udp != NULL);    #ifndef TEST							/* { */    /*     * Receive the packet.     */    dgram_zero(&udp->dgram);    if (dgram_recv(&udp->dgram, 0, &udp->peer) < 0)	return;#endif /* !TEST */						/* } */    /*     * Parse the packet.     */    if (str2pkthdr(udp) < 0)	return;    /*     * If there are events waiting on this handle, we're done     */    rh = udp->bh_first;    while(rh != NULL && (strcmp(rh->proto_handle, udp->handle) != 0 ||			 rh->sequence != udp->sequence ||			 cmp_sockaddr(&rh->peer, &udp->peer, 0) != 0)) {	rh = rh->next;    }    if (rh && event_wakeup(rh->event_id) > 0)	return;    /*     * If we didn't find a handle, then check for a new incoming packet.     * If no accept handler was setup, then just return.     */    if (udp->accept_fn == NULL) {	dbprintf(_("Receive packet from unknown source"));	return;    }    rh = alloc(SIZEOF(*rh));    rh->proto_handle=NULL;    rh->udp = udp;    rh->rc = NULL;    security_handleinit(&rh->sech, udp->driver);    result = getnameinfo((struct sockaddr *)&udp->peer, SS_LEN(&udp->peer),			 hostname, sizeof(hostname), NULL, 0, 0);    if (result != 0) {	dbprintf("getnameinfo failed: %s\n",		  gai_strerror(result));	security_seterror(&rh->sech, "getnameinfo failed: %s",			  gai_strerror(result));	return;    }    if (check_name_give_sockaddr(hostname,				 (struct sockaddr *)&udp->peer, &errmsg) < 0) {	security_seterror(&rh->sech, "%s",errmsg);	amfree(errmsg);	amfree(rh);	return;    }    port = SS_GET_PORT(&udp->peer);    a = udp_inithandle(udp, rh,		   hostname,		   &udp->peer,		   port,		   udp->handle,		   udp->sequence);    if (a < 0) {	auth_debug(1, _("bsd: closeX handle '%s'\n"), rh->proto_handle);	amfree(rh);	return;    }    /*     * Check the security of the packet.  If it is bad, then pass NULL     * to the accept function instead of a packet.     */    if (rh->udp->recv_security_ok(rh, &udp->pkt) < 0)	(*udp->accept_fn)(&rh->sech, NULL);    else	(*udp->accept_fn)(&rh->sech, &udp->pkt);}/* * Locate an existing connection to the given host, or create a new, * unconnected entry if none exists.  The caller is expected to check * for the lack of a connection (rc->read == -1) and set one up. */struct tcp_conn *sec_tcp_conn_get(    const char *hostname,    int		want_new){    struct tcp_conn *rc;    auth_debug(1, _("sec_tcp_conn_get: %s\n"), hostname);    if (want_new == 0) {	for (rc = connq_first(); rc != NULL; rc = connq_next(rc)) {	    if (strcasecmp(hostname, rc->hostname) == 0)		break;	}	if (rc != NULL) {	    rc->refcnt++;	    auth_debug(1,		      _("sec_tcp_conn_get: exists, refcnt to %s is now %d\n"),		       rc->hostname, rc->refcnt);	    return (rc);	}    }    auth_debug(1, _("sec_tcp_conn_get: creating new handle\n"));    /*     * We can't be creating a new handle if we are the client     */    rc = alloc(SIZEOF(*rc));    rc->read = rc->write = -1;    rc->driver = NULL;    rc->pid = -1;    rc->ev_read = NULL;    rc->toclose = 0;    rc->donotclose = 0;    strncpy(rc->hostname, hostname, SIZEOF(rc->hostname) - 1);    rc->hostname[SIZEOF(rc->hostname) - 1] = '\0';    rc->errmsg = NULL;    rc->refcnt = 1;    rc->handle = -1;    rc->pkt = NULL;    rc->accept_fn = NULL;    rc->recv_security_ok = NULL;    rc->prefix_packet = NULL;    rc->auth = 0;    rc->conf_fn = NULL;    rc->datap = NULL;    connq_append(rc);    return (rc);}/* * Delete a reference to a connection, and close it if it is the last * reference. */voidsec_tcp_conn_put(    struct tcp_conn *	rc){    amwait_t status;    assert(rc->refcnt > 0);    --rc->refcnt;    auth_debug(1, _("sec_tcp_conn_put: decrementing refcnt for %s to %d\n"),		   rc->hostname, rc->refcnt);    if (rc->refcnt > 0) {	return;    }    auth_debug(1, _("sec_tcp_conn_put: closing connection to %s\n"), rc->hostname);    if (rc->read != -1)	aclose(rc->read);    if (rc->write != -1)	aclose(rc->write);    if (rc->pid != -1) {	waitpid(rc->pid, &status, WNOHANG);    }    if (rc->ev_read != NULL)	event_release(rc->ev_read);    if (rc->errmsg != NULL)	amfree(rc->errmsg);    connq_remove(rc);    amfree(rc->pkt);    if(!rc->donotclose)	amfree(rc); /* someone might still use it           */		    /* eg. in sec_tcp_conn_read_callback if */		    /*     event_wakeup call us.            */}/* * Turn on read events for a conn.  Or, increase a ev_read_refcnt if we are * already receiving read events. */voidsec_tcp_conn_read(    struct tcp_conn *	rc){    assert (rc != NULL);    if (rc->ev_read != NULL) {	rc->ev_read_refcnt++;	auth_debug(1,	      _("sec: conn_read: incremented ev_read_refcnt to %d for %s\n"),	       rc->ev_read_refcnt, rc->hostname);	return;    }    auth_debug(1, _("sec: conn_read registering event handler for %s\n"),		   rc->hostname);    rc->ev_read = event_register((event_id_t)rc->read, EV_READFD,		sec_tcp_conn_read_callback, rc);    rc->ev_read_refcnt = 1;}static voidsec_tcp_conn_read_cancel(    struct tcp_conn *	rc){    --rc->ev_read_refcnt;    auth_debug(1,       _("sec: conn_read_cancel: decremented ev_read_refcnt to %d for %s\n"),	rc->ev_read_refcnt, rc->hostname);    if (rc->ev_read_refcnt > 0) {	return;    }    auth_debug(1,                _("sec: conn_read_cancel: releasing event handler for %s\n"),	         rc->hostname);    event_release(rc->ev_read);    rc->ev_read = NULL;}/* * This is called when a handle is woken up because data read off of the * net is for it. */static voidrecvpkt_callback(    void *	cookie,    void *	buf,    ssize_t	bufsize){

⌨️ 快捷键说明

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