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

📄 security-util.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 5 页
字号:
    pkt_t pkt;    struct sec_handle *rh = cookie;    assert(rh != NULL);    auth_debug(1, _("sec: recvpkt_callback: %zd\n"), bufsize);    /*     * We need to cancel the recvpkt request before calling     * the callback because the callback may reschedule us.     */    stream_recvpkt_cancel(rh);    switch (bufsize) {    case 0:	security_seterror(&rh->sech,	    _("EOF on read from %s"), rh->hostname);	(*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);	return;    case -1:	security_seterror(&rh->sech, security_stream_geterror(&rh->rs->secstr));	(*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);	return;    default:	break;    }    parse_pkt(&pkt, buf, (size_t)bufsize);    auth_debug(1,	  _("sec: received %s packet (%d) from %s, contains:\n\n\"%s\"\n\n"),	   pkt_type2str(pkt.type), pkt.type,	   rh->hostname, pkt.body);    if (rh->rc->recv_security_ok && (rh->rc->recv_security_ok)(rh, &pkt) < 0)	(*rh->fn.recvpkt)(rh->arg, NULL, S_ERROR);    else	(*rh->fn.recvpkt)(rh->arg, &pkt, S_OK);    amfree(pkt.body);}/* * Callback for tcpm_stream_read_sync */static voidstream_read_sync_callback(    void *	s){    struct sec_stream *rs = s;    assert(rs != NULL);    auth_debug(1, _("sec: stream_read_callback_sync: handle %d\n"), rs->handle);    /*     * Make sure this was for us.  If it was, then blow away the handle     * so it doesn't get claimed twice.  Otherwise, leave it alone.     *     * If the handle is EOF, pass that up to our callback.     */    if (rs->rc->handle == rs->handle) {        auth_debug(1, _("sec: stream_read_callback_sync: it was for us\n"));        rs->rc->handle = H_TAKEN;    } else if (rs->rc->handle != H_EOF) {        auth_debug(1, _("sec: stream_read_callback_sync: not for us\n"));        return;    }    /*     * Remove the event first, and then call the callback.     * We remove it first because we don't want to get in their     * way if they reschedule it.     */    tcpm_stream_read_cancel(rs);    if (rs->rc->pktlen <= 0) {	auth_debug(1, _("sec: stream_read_sync_callback: %s\n"), rs->rc->errmsg);	security_stream_seterror(&rs->secstr, rs->rc->errmsg);	if(rs->closed_by_me == 0 && rs->closed_by_network == 0)	    sec_tcp_conn_put(rs->rc);	rs->closed_by_network = 1;	return;    }    auth_debug(1,	    _("sec: stream_read_callback_sync: read %zd bytes from %s:%d\n"),	    rs->rc->pktlen, rs->rc->hostname, rs->handle);}/* * Callback for tcpm_stream_read */static voidstream_read_callback(    void *	arg){    struct sec_stream *rs = arg;    assert(rs != NULL);    auth_debug(1, _("sec: stream_read_callback: handle %d\n"), rs->handle);    /*     * Make sure this was for us.  If it was, then blow away the handle     * so it doesn't get claimed twice.  Otherwise, leave it alone.     *     * If the handle is EOF, pass that up to our callback.     */    if (rs->rc->handle == rs->handle) {	auth_debug(1, _("sec: stream_read_callback: it was for us\n"));	rs->rc->handle = H_TAKEN;    } else if (rs->rc->handle != H_EOF) {	auth_debug(1, _("sec: stream_read_callback: not for us\n"));	return;    }    /*     * Remove the event first, and then call the callback.     * We remove it first because we don't want to get in their     * way if they reschedule it.     */    tcpm_stream_read_cancel(rs);    if (rs->rc->pktlen <= 0) {	auth_debug(1, _("sec: stream_read_callback: %s\n"), rs->rc->errmsg);	security_stream_seterror(&rs->secstr, rs->rc->errmsg);	if(rs->closed_by_me == 0 && rs->closed_by_network == 0)	    sec_tcp_conn_put(rs->rc);	rs->closed_by_network = 1;	(*rs->fn)(rs->arg, NULL, rs->rc->pktlen);	return;    }    auth_debug(1, _("sec: stream_read_callback: read %zd bytes from %s:%d\n"),		   rs->rc->pktlen, rs->rc->hostname, rs->handle);    (*rs->fn)(rs->arg, rs->rc->pkt, rs->rc->pktlen);    auth_debug(1, _("sec: after callback stream_read_callback\n"));}/* * The callback for the netfd for the event handler * Determines if this packet is for this security handle, * and does the real callback if so. */static voidsec_tcp_conn_read_callback(    void *	cookie){    struct tcp_conn *	rc = cookie;    struct sec_handle *	rh;    pkt_t		pkt;    ssize_t		rval;    int			revent;    assert(cookie != NULL);    auth_debug(1, _("sec: conn_read_callback\n"));    /* Read the data off the wire.  If we get errors, shut down. */    rval = tcpm_recv_token(rc, rc->read, &rc->handle, &rc->errmsg, &rc->pkt,				&rc->pktlen, 60);    auth_debug(1, _("sec: conn_read_callback: tcpm_recv_token returned %zd\n"),		   rval);    if (rval < 0 || rc->handle == H_EOF) {	rc->pktlen = rval;	rc->handle = H_EOF;	revent = event_wakeup((event_id_t)rc);	auth_debug(1, _("sec: conn_read_callback: event_wakeup return %d\n"),		       revent);	/* delete our 'accept' reference */	if (rc->accept_fn != NULL) {	    if(rc->refcnt != 1) {		dbprintf(_("STRANGE, rc->refcnt should be 1, it is %d\n"),			  rc->refcnt);		rc->refcnt=1;	    }	    rc->accept_fn = NULL;	    sec_tcp_conn_put(rc);	}	return;    }    if(rval == 0) {	rc->pktlen = 0;	revent = event_wakeup((event_id_t)rc);	auth_debug(1,		   _("sec: conn_read_callback: event_wakeup return %d\n"), revent);	return;    }    /* If there are events waiting on this handle, we're done */    rc->donotclose = 1;    revent = event_wakeup((event_id_t)rc);    auth_debug(1, _("sec: conn_read_callback: event_wakeup return %zd\n"), rval);    rc->donotclose = 0;    if (rc->handle == H_TAKEN || rc->pktlen == 0) {	if(rc->refcnt == 0) amfree(rc);	return;    }    assert(rc->refcnt > 0);    /* If there is no accept fn registered, then drop the packet */    if (rc->accept_fn == NULL)	return;    rh = alloc(SIZEOF(*rh));    security_handleinit(&rh->sech, rc->driver);    rh->hostname = stralloc(rc->hostname);    rh->ev_timeout = NULL;    rh->rc = rc;    rh->peer = rc->peer;    rh->rs = tcpma_stream_client(rh, rc->handle);    auth_debug(1, _("sec: new connection\n"));    pkt.body = NULL;    parse_pkt(&pkt, rc->pkt, (size_t)rc->pktlen);    auth_debug(1, _("sec: calling accept_fn\n"));    if (rh->rc->recv_security_ok && (rh->rc->recv_security_ok)(rh, &pkt) < 0)	(*rc->accept_fn)(&rh->sech, NULL);    else	(*rc->accept_fn)(&rh->sech, &pkt);    amfree(pkt.body);}voidparse_pkt(    pkt_t *	pkt,    const void *buf,    size_t	bufsize){    const unsigned char *bufp = buf;    auth_debug(1, _("sec: parse_pkt: parsing buffer of %zu bytes\n"), bufsize);    pkt->type = (pktype_t)*bufp++;    bufsize--;    pkt->packet_size = bufsize+1;    pkt->body = alloc(pkt->packet_size);    if (bufsize == 0) {	pkt->body[0] = '\0';    } else {	memcpy(pkt->body, bufp, bufsize);	pkt->body[pkt->packet_size - 1] = '\0';    }    pkt->size = strlen(pkt->body);    auth_debug(1, _("sec: parse_pkt: %s (%d): \"%s\"\n"), pkt_type2str(pkt->type),		   pkt->type, pkt->body);}/* * Convert a packet header into a string */const char *pkthdr2str(    const struct sec_handle *	rh,    const pkt_t *		pkt){    static char retbuf[256];    assert(rh != NULL);    assert(pkt != NULL);    g_snprintf(retbuf, SIZEOF(retbuf), _("Amanda %d.%d %s HANDLE %s SEQ %d\n"),	VERSION_MAJOR, VERSION_MINOR, pkt_type2str(pkt->type),	rh->proto_handle, rh->sequence);    auth_debug(1, _("bsd: pkthdr2str handle '%s'\n"), rh->proto_handle);    /* check for truncation.  If only we had asprintf()... */    assert(retbuf[strlen(retbuf) - 1] == '\n');    return (retbuf);}/* * Parses out the header line in 'str' into the pkt and handle * Returns negative on parse error. */intstr2pkthdr(    udp_handle_t *	udp){    char *str;    const char *tok;    pkt_t *pkt;    pkt = &udp->pkt;    assert(udp->dgram.cur != NULL);    str = stralloc(udp->dgram.cur);    /* "Amanda %d.%d <ACK,NAK,...> HANDLE %s SEQ %d\n" */    /* Read in "Amanda" */    if ((tok = strtok(str, " ")) == NULL || strcmp(tok, "Amanda") != 0)	goto parse_error;    /* nothing is done with the major/minor numbers currently */    if ((tok = strtok(NULL, " ")) == NULL || strchr(tok, '.') == NULL)	goto parse_error;    /* Read in the packet type */    if ((tok = strtok(NULL, " ")) == NULL)	goto parse_error;    amfree(pkt->body);    pkt_init_empty(pkt, pkt_str2type(tok));    if (pkt->type == (pktype_t)-1)    	goto parse_error;    /* Read in "HANDLE" */    if ((tok = strtok(NULL, " ")) == NULL || strcmp(tok, "HANDLE") != 0)	goto parse_error;    /* parse the handle */    if ((tok = strtok(NULL, " ")) == NULL)	goto parse_error;    amfree(udp->handle);    udp->handle = stralloc(tok);    /* Read in "SEQ" */    if ((tok = strtok(NULL, " ")) == NULL || strcmp(tok, "SEQ") != 0)   	goto parse_error;    /* parse the sequence number */       if ((tok = strtok(NULL, "\n")) == NULL)	goto parse_error;    udp->sequence = atoi(tok);    /* Save the body, if any */           if ((tok = strtok(NULL, "")) != NULL)	pkt_cat(pkt, "%s", tok);    amfree(str);    return (0);parse_error:#if 0 /* XXX we have no way of passing this back up */    security_seterror(&rh->sech,	"parse error in packet header : '%s'", origstr);#endif    amfree(str);    return (-1);}char *check_user(    struct sec_handle *	rh,    const char *	remoteuser,    const char *	service){    struct passwd *pwd;    char *r;    char *result = NULL;    char *localuser = NULL;    /* lookup our local user name */    if ((pwd = getpwnam(CLIENT_LOGIN)) == NULL) {	return vstrallocf(_("getpwnam(%s) failed."), CLIENT_LOGIN);    }    /*     * Make a copy of the user name in case getpw* is called by     * any of the lower level routines.     */    localuser = stralloc(pwd->pw_name);#ifndef USE_AMANDAHOSTS    r = check_user_ruserok(rh->hostname, pwd, remoteuser);#else    r = check_user_amandahosts(rh->hostname, &rh->peer, pwd, remoteuser, service);#endif    if (r != NULL) {	result = vstrallocf(		_("user %s from %s is not allowed to execute the service %s: %s"),		remoteuser, rh->hostname, service, r);	amfree(r);    }    amfree(localuser);    return result;}/* * See if a remote user is allowed in.  This version uses ruserok() * and friends. * * Returns NULL on success, or error message on error. */char *check_user_ruserok(    const char *	host,    struct passwd *	pwd,    const char *	remoteuser){    int saved_stderr;    int fd[2];    FILE *fError;    amwait_t exitcode;    pid_t ruserok_pid;    pid_t pid;    char *es;    char *result;    int ok;    uid_t myuid = getuid();    /*     * note that some versions of ruserok (eg SunOS 3.2) look in     * "./.rhosts" rather than "~CLIENT_LOGIN/.rhosts", so we have to     * chdir ourselves.  Sigh.     *     * And, believe it or not, some ruserok()'s try an initgroup just     * for the hell of it.  Since we probably aren't root at this point     * it'll fail, and initgroup "helpfully" will blatt "Setgroups: Not owner"     * into our stderr output even though the initgroup failure is not a     * problem and is expected.  Thanks a lot.  Not.     */    if (pipe(fd) != 0) {	return stralloc2(_("pipe() fails: "), strerror(errno));    }    if ((ruserok_pid = fork()) < 0) {	return stralloc2(_("fork() fails: "), strerror(errno));    } else if (ruserok_pid == 0) {	int ec;	close(fd[0]);	fError = fdopen(fd[1], "w");	if (!fError) {	    error(_("Can't fdopen: %s"), strerror(errno));	    /*NOTREACHED*/	}	/* pamper braindead ruserok's */	if (chdir(pwd->pw_dir) != 0) {	    g_fprintf(fError, _("chdir(%s) failed: %s"),		    pwd->pw_dir, strerror(errno));	    fclose(fError);	    exit(1);	}	if (debug_auth >= 9) {	    char *dir = stralloc(pwd->pw_dir);	    auth_debug(9, _("bsd: calling ruserok(%s, %d, %s, %s)\n"), host,			   ((myuid == 0) ? 1 : 0), remoteuser, pwd->pw_name);	    if (myuid == 0) {		auth_debug(9, _("bsd: because you are running as root, "));		auth_debug(9, _("/etc/hosts.equiv will not be used\n"));	    } else {		show_stat_info("/etc/hosts.equiv", NULL);	    }	    show_stat_info(dir, "/.rhosts");	    amfree(dir);	}	saved_stderr = dup(2);	close(2);	if (open("/dev/null", O_RDWR) == -1) {            auth_debug(1, _("Could not open /dev/null: %s\n"), strerror(errno));	    ec = 1;	} else {	    ok = ruserok(host, myuid == 0, remoteuser, CLIENT_LOGIN);	    if (ok < 0) {	        ec = 1;	    } else {	        ec = 0;	    }	}	(void)dup2(saved_stderr,2);	close(saved_stderr);	exit(ec);    }    close(fd[1]);    fError = fdopen(fd[0], "r");    if (!fError) {	error(_("Can't fdopen: %s"), strerror(errno));	/*NOTREACHED*/    }    result = NULL;    while ((es = agets(fError)) != NULL) {	if (*es == 0) {	    amfree(es);	    continue;	}	if (result == NULL) {	    result = stralloc("");	} else {	    strappend(result, ": ");	}	strappend(result, es);	amfree(es);    }    close(fd[0]);    pid = wait(&exitcode);    while (pid != ruserok_pid) {	if ((pid == (pid_t) -1) && (errno != EINTR)) {	    amfree(result);	    return vstrallocf(_("ruserok wait failed: %s"), strerror(errno));	}	pid = wait(&exitcode);    }    if (!WIFEXITED(exitcode) || WEXITSTATUS(exitcode) != 0) {	amfree(result);	result = str_exit_status("ruserok child", exitcode);    } else {	amfree(result);    }    return result;}/* * Check to see if a user is allowed in.  This version uses .amandahosts * Returns an error message on failure, or NULL on success. */char *check_user_amandahosts(    const char *	host,    struct sockaddr_storage *addr,    struct passwd *	pwd,    const char *	remoteuser,    const char *	service){    char *line = NULL;    char *filehost;    const char *fileuser;    char *ptmp = NULL;

⌨️ 快捷键说明

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