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

📄 security-util.c

📁 开源备份软件源码 AMANDA, the Advanced Maryland Automatic Network Disk Archiver, is a backup system that a
💻 C
📖 第 1 页 / 共 5 页
字号:
    char *result = NULL;    FILE *fp = NULL;    int found;    struct stat sbuf;    int hostmatch;    int usermatch;    char *aservice = NULL;#ifdef WORKING_IPV6    char ipstr[INET6_ADDRSTRLEN];#else    char ipstr[INET_ADDRSTRLEN];#endif    auth_debug(1, _("check_user_amandahosts(host=%s, pwd=%p, "		   "remoteuser=%s, service=%s)\n"),		   host, pwd, remoteuser, service);    ptmp = stralloc2(pwd->pw_dir, "/.amandahosts");    if (debug_auth >= 9) {	show_stat_info(ptmp, "");;    }    if ((fp = fopen(ptmp, "r")) == NULL) {	result = vstrallocf(_("cannot open %s: %s"), ptmp, strerror(errno));	amfree(ptmp);	return result;    }    /*     * Make sure the file is owned by the Amanda user and does not     * have any group/other access allowed.     */    if (fstat(fileno(fp), &sbuf) != 0) {	result = vstrallocf(_("cannot fstat %s: %s"), ptmp, strerror(errno));	goto common_exit;    }    if (sbuf.st_uid != pwd->pw_uid) {	result = vstrallocf(_("%s: owned by id %ld, should be %ld"),			ptmp, (long)sbuf.st_uid, (long)pwd->pw_uid);	goto common_exit;    }    if ((sbuf.st_mode & 077) != 0) {	result = vstrallocf(_("%s: incorrect permissions; file must be accessible only by its owner"), ptmp);	goto common_exit;    }    /*     * Now, scan the file for the host/user/service.     */    found = 0;    while ((line = agets(fp)) != NULL) {	if (*line == 0) {	    amfree(line);	    continue;	}	auth_debug(9, _("bsd: processing line: <%s>\n"), line);	/* get the host out of the file */	if ((filehost = strtok(line, " \t")) == NULL) {	    amfree(line);	    continue;	}	/* get the username.  If no user specified, then use the local user */	if ((fileuser = strtok(NULL, " \t")) == NULL) {	    fileuser = pwd->pw_name;	}	hostmatch = (strcasecmp(filehost, host) == 0);	/*  ok if addr=127.0.0.1 and	 *  either localhost or localhost.domain is in .amandahost */	if (!hostmatch  &&	    (strcasecmp(filehost, "localhost")== 0 ||	     strcasecmp(filehost, "localhost.localdomain")== 0)) {#ifdef WORKING_IPV6	    if (addr->ss_family == (sa_family_t)AF_INET6)		inet_ntop(AF_INET6, &((struct sockaddr_in6 *)addr)->sin6_addr,			  ipstr, sizeof(ipstr));	    else#endif		inet_ntop(AF_INET, &((struct sockaddr_in *)addr)->sin_addr,			  ipstr, sizeof(ipstr));	    if (strcmp(ipstr, "127.0.0.1") == 0 ||		strcmp(ipstr, "::1") == 0)		hostmatch = 1;	}	usermatch = (strcasecmp(fileuser, remoteuser) == 0);	auth_debug(9, _("bsd: comparing \"%s\" with\n"), filehost);	auth_debug(9, _("bsd:           \"%s\" (%s)\n"), host,		       hostmatch ? _("match") : _("no match"));	auth_debug(9, _("bsd:       and \"%s\" with\n"), fileuser);	auth_debug(9, _("bsd:           \"%s\" (%s)\n"), remoteuser,		       usermatch ? _("match") : _("no match"));	/* compare */	if (!hostmatch || !usermatch) {	    amfree(line);	    continue;	}        if (!service) {	    /* success */	    amfree(line);	    found = 1;	    break;	}	/* get the services.  If no service specified, then use	 * noop/selfcheck/sendsize/sendbackup         */	aservice = strtok(NULL, " \t,");	if (!aservice) {	    if (strcmp(service,"noop") == 0 ||	       strcmp(service,"selfcheck") == 0 ||	       strcmp(service,"sendsize") == 0 ||	       strcmp(service,"sendbackup") == 0) {		/* success */		found = 1;		amfree(line);		break;	    }	    else {		amfree(line);		break;	    }	}	do {	    if (strcmp(aservice,service) == 0) {		found = 1;		break;	    }	    if (strcmp(aservice, "amdump") == 0 && 	       (strcmp(service, "noop") == 0 ||		strcmp(service, "selfcheck") == 0 ||		strcmp(service, "sendsize") == 0 ||		strcmp(service, "sendbackup") == 0)) {		found = 1;		break;	    }	} while((aservice = strtok(NULL, " \t,")) != NULL);	if (aservice && strcmp(aservice, service) == 0) {	    /* success */	    found = 1;	    amfree(line);	    break;	}	amfree(line);    }    if (! found) {	if (strcmp(service, "amindexd") == 0 ||	    strcmp(service, "amidxtaped") == 0) {	    result = vstrallocf(_("Please add the line \"%s %s amindexd amidxtaped\" to %s on the client"), host, remoteuser, ptmp);	} else if (strcmp(service, "amdump") == 0 ||		   strcmp(service, "noop") == 0 ||		   strcmp(service, "selfcheck") == 0 ||		   strcmp(service, "sendsize") == 0 ||		   strcmp(service, "sendbackup") == 0) {	    result = vstrallocf(_("Please add the line \"%s %s amdump\" to %s on the client"), host, remoteuser, ptmp);	} else {	    result = vstrallocf(_("%s: invalid service %s"), ptmp, service);	}    }common_exit:    afclose(fp);    amfree(ptmp);    return result;}/* return 1 on success, 0 on failure */intcheck_security(    struct sockaddr_storage *addr,    char *		str,    unsigned long	cksum,    char **		errstr){    char *		remotehost = NULL, *remoteuser = NULL;    char *		bad_bsd = NULL;    struct passwd *	pwptr;    uid_t		myuid;    char *		s;    char *		fp;    int			ch;    char		hostname[NI_MAXHOST];    in_port_t		port;    int			result;    (void)cksum;	/* Quiet unused parameter warning */    auth_debug(1,	       _("check_security(addr=%p, str='%s', cksum=%lu, errstr=%p\n"),		addr, str, cksum, errstr);    dump_sockaddr(addr);    *errstr = NULL;    /* what host is making the request? */    if ((result = getnameinfo((struct sockaddr *)addr, SS_LEN(addr),			      hostname, NI_MAXHOST, NULL, 0, 0)) != 0) {	dbprintf(_("getnameinfo failed: %s\n"),		  gai_strerror(result));	*errstr = vstralloc("[", "addr ", str_sockaddr(addr), ": ",			    "getnameinfo failed: ", gai_strerror(result),			    "]", NULL);	return 0;    }    remotehost = stralloc(hostname);    if( check_name_give_sockaddr(hostname,				 (struct sockaddr *)addr, errstr) < 0) {	amfree(remotehost);	return 0;    }    /* next, make sure the remote port is a "reserved" one */    port = SS_GET_PORT(addr);    if (port >= IPPORT_RESERVED) {	*errstr = vstrallocf(_("[host %s: port %u not secure]"),			remotehost, (unsigned int)port);	amfree(remotehost);	return 0;    }    /* extract the remote user name from the message */    s = str;    ch = *s++;    bad_bsd = vstrallocf(_("[host %s: bad bsd security line]"), remotehost);    if (strncmp_const_skip(s - 1, "USER ", s, ch) != 0) {	*errstr = bad_bsd;	bad_bsd = NULL;	amfree(remotehost);	return 0;    }    skip_whitespace(s, ch);    if (ch == '\0') {	*errstr = bad_bsd;	bad_bsd = NULL;	amfree(remotehost);	return 0;    }    fp = s - 1;    skip_non_whitespace(s, ch);    s[-1] = '\0';    remoteuser = stralloc(fp);    s[-1] = (char)ch;    amfree(bad_bsd);    /* lookup our local user name */    myuid = getuid();    if ((pwptr = getpwuid(myuid)) == NULL)        error(_("error [getpwuid(%d) fails]"), (int)myuid);    auth_debug(1, _("bsd security: remote host %s user %s local user %s\n"),		   remotehost, remoteuser, pwptr->pw_name);#ifndef USE_AMANDAHOSTS    s = check_user_ruserok(remotehost, pwptr, remoteuser);#else    s = check_user_amandahosts(remotehost, addr, pwptr, remoteuser, NULL);#endif    if (s != NULL) {	*errstr = vstrallocf(_("[access as %s not allowed from %s@%s: %s]"),			    pwptr->pw_name, remoteuser, remotehost, s);    }    amfree(s);    amfree(remotehost);    amfree(remoteuser);    return *errstr == NULL;}/* * Writes out the entire iovec */ssize_tnet_writev(    int			fd,    struct iovec *	iov,    int			iovcnt){    ssize_t delta, n, total;    assert(iov != NULL);    total = 0;    while (iovcnt > 0) {	/*	 * Write the iovec	 */	n = writev(fd, iov, iovcnt);	if (n < 0) {	    if (errno != EINTR)		return (-1);	    auth_debug(1, _("net_writev got EINTR\n"));	}	else if (n == 0) {	    errno = EIO;	    return (-1);	} else {	    total += n;	    /*	     * Iterate through each iov.  Figure out what we still need	     * to write out.	     */	    for (; n > 0; iovcnt--, iov++) {		/* 'delta' is the bytes written from this iovec */		delta = ((size_t)n < (size_t)iov->iov_len) ? n : (ssize_t)iov->iov_len;		/* subtract from the total num bytes written */		n -= delta;		assert(n >= 0);		/* subtract from this iovec */		iov->iov_len -= delta;		iov->iov_base = (char *)iov->iov_base + delta;		/* if this iovec isn't empty, run the writev again */		if (iov->iov_len > 0)		    break;	    }	}    }    return (total);}/* * Like read(), but waits until the entire buffer has been filled. */ssize_tnet_read(    int		fd,    void *	vbuf,    size_t	origsize,    int		timeout){    char *buf = vbuf;	/* ptr arith */    ssize_t nread;    size_t size = origsize;    auth_debug(1, _("net_read: begin %zu\n"), origsize);    while (size > 0) {	auth_debug(1, _("net_read: while %zu\n"), size);	nread = net_read_fillbuf(fd, timeout, buf, size);	if (nread < 0) {    	    auth_debug(1, _("db: net_read: end return(-1)\n"));	    return (-1);	}	if (nread == 0) {    	    auth_debug(1, _("net_read: end return(0)\n"));	    return (0);	}	buf += nread;	size -= nread;    }    auth_debug(1, _("net_read: end %zu\n"), origsize);    return ((ssize_t)origsize);}/* * net_read likes to do a lot of little reads.  Buffer it. */ssize_tnet_read_fillbuf(    int		fd,    int		timeout,    void *	buf,    size_t	size){    SELECT_ARG_TYPE readfds;    struct timeval tv;    ssize_t nread;    auth_debug(1, _("net_read_fillbuf: begin\n"));    FD_ZERO(&readfds);    FD_SET(fd, &readfds);    tv.tv_sec = timeout;    tv.tv_usec = 0;    switch (select(fd + 1, &readfds, NULL, NULL, &tv)) {    case 0:	errno = ETIMEDOUT;	/* FALLTHROUGH */    case -1:	auth_debug(1, _("net_read_fillbuf: case -1\n"));	return (-1);    case 1:	auth_debug(1, _("net_read_fillbuf: case 1\n"));	assert(FD_ISSET(fd, &readfds));	break;    default:	auth_debug(1, _("net_read_fillbuf: case default\n"));	assert(0);	break;    }    nread = read(fd, buf, size);    if (nread < 0)	return (-1);    auth_debug(1, _("net_read_fillbuf: end %zd\n"), nread);    return (nread);}/* * Display stat() information about a file. */voidshow_stat_info(    char *	a,    char *	b){    char *name = vstralloc(a, b, NULL);    struct stat sbuf;    struct passwd *pwptr;    struct passwd pw;    char *owner;    struct group *grptr;    struct group gr;    char *group;    int buflen;    char *buf;    if (stat(name, &sbuf) != 0) {	auth_debug(1, _("bsd: cannot stat %s: %s\n"), name, strerror(errno));	amfree(name);	return;    }#ifdef _SC_GETPW_R_SIZE_MAX    buflen = sysconf(_SC_GETPW_R_SIZE_MAX);    if (buflen == -1)	buflen = 1024;#else    buflen = 1024;#endif    buf = malloc(buflen);    if (getpwuid_r(sbuf.st_uid, &pw, buf, buflen, &pwptr) != 0 ||	pwptr == NULL) {	owner = alloc(NUM_STR_SIZE + 1);	g_snprintf(owner, NUM_STR_SIZE, "%ld", (long)sbuf.st_uid);    } else {	owner = stralloc(pwptr->pw_name);    }    if (getgrgid_r(sbuf.st_gid, &gr, buf, buflen, &grptr) != 0 ||	grptr == NULL) {	group = alloc(NUM_STR_SIZE + 1);	g_snprintf(group, NUM_STR_SIZE, "%ld", (long)sbuf.st_gid);    } else {	group = stralloc(grptr->gr_name);    }    auth_debug(1, _("bsd: processing file: %s\n"), name);    auth_debug(1, _("bsd:                  owner=%s group=%s mode=%03o\n"),		   owner, group,		   (int) (sbuf.st_mode & 0777));    amfree(name);    amfree(owner);    amfree(group);    amfree(buf);}intcheck_name_give_sockaddr(    const char *hostname,    struct sockaddr *addr,    char **errstr){    int result;    struct addrinfo *res = NULL, *res1;    char *canonname;    result = resolve_hostname(hostname, 0, &res, &canonname);    if (result != 0) {	dbprintf(_("check_name_give_sockaddr: resolve_hostname('%s'): %s\n"), hostname, gai_strerror(result));	*errstr = newvstrallocf(*errstr,			       _("check_name_give_sockaddr: resolve_hostname('%s'): %s"),			       hostname, gai_strerror(result));	goto error;    }    if (canonname == NULL) {	dbprintf(_("resolve_hostname('%s') did not return a canonical name\n"), hostname);	*errstr = newvstrallocf(*errstr,		_("check_name_give_sockaddr: resolve_hostname('%s') did not return a canonical name"),		hostname);	goto error;    }    if (strncasecmp(hostname, canonname, strlen(hostname)) != 0) {	dbprintf(_("%s doesn't resolve to itself, it resolves to %s\n"),		       hostname, canonname);	*errstr = newvstrallocf(*errstr,			       _("%s doesn't resolve to itself, it resolves to %s"),			       hostname, canonname);	goto error;    }    for(res1=res; res1 != NULL; res1 = res1->ai_next) {	if (cmp_sockaddr((struct sockaddr_storage *)res1->ai_addr, (struct sockaddr_storage *)addr, 1) == 0) {	    freeaddrinfo(res);	    amfree(canonname);	    return 0;	}    }    dbprintf(_("%s doesn't resolve to %s"),	    hostname, str_sockaddr((struct sockaddr_storage *)addr));    *errstr = newvstrallocf(*errstr,			   "%s doesn't resolve to %s",			   hostname, str_sockaddr((struct sockaddr_storage *)addr));error:    if (res) freeaddrinfo(res);    amfree(canonname);    return -1;}

⌨️ 快捷键说明

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