📄 security-util.c
字号:
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 + -