mountd.c
来自「<B>Digital的Unix操作系统VAX 4.2源码</B>」· C语言 代码 · 共 2,539 行 · 第 1/5 页
C
2,539 行
#endif /* * Make saved /etc/exports time older to force * a re-build of the in core structure. */ exportstat.st_mtime--; set_exports(); mtd_export(transp); return; default: svcerr_noproc(transp); return; }}struct hostent *getclientsname(rqstp,transp) struct svc_req *rqstp; SVCXPRT *transp;{ struct in_addr claim; struct sockaddr_in actual; struct hostent *hp, *chp; static struct hostent h; static struct in_addr prev; static char *null_alias; char *machine; char *cp; char *strchr (); int i; if (rqstp->rq_cred.oa_flavor != AUTH_UNIX) { return(NULL); } actual = *svc_getcaller(transp); if (nfs_portmon) { if (ntohs(actual.sin_port) >= IPPORT_RESERVED) { return(NULL); } } /* * Don't use the unix credentials to get the machine name, * instead use the source IP address. Use cached hostent * if previous request was from same client. */ if (bcmp(&actual.sin_addr, &prev, sizeof(struct in_addr)) == 0) {#ifdef DEBUG (void)fprintf(stderr, "Found addr in hostent cache! \n");#endif DEBUG return (&h); } hp = gethostbyaddr((char *) &actual.sin_addr, sizeof(actual.sin_addr), AF_INET); if (hp == NULL) { if (ipaddr_check) { svcerr_auth(transp, AUTH_BADCRED); return(NULL); } /* else dummy one up */ h.h_name = (char *)inet_ntoa(actual.sin_addr);#ifdef DEBUG (void)fprintf(stderr, "Dummy hostent name %s\n", h.h_name);#endif DEBUG h.h_aliases = &null_alias; h.h_addrtype = AF_INET; h.h_length = sizeof (u_long); hp = &h; } else { bcopy(hp, &h, sizeof(struct hostent)); } prev = actual.sin_addr;#ifdef DEBUG (void)fprintf(stderr, "getclientsname %s\n", hp->h_name);#endif DEBUG /* * If domain_check or subdomain_check is set and * if BIND enabled, check the requester's domain spec * to be sure it is local. Check if: * 1) domain spec matches that of local host or * 2) host name is unqualified (local) */ if ((domain_check || subdomain_check) && (bindup()) != NULL) { machine = ((struct authunix_parms *) rqstp->rq_clntcred)->aup_machname; chp = gethostbyname(machine); if (chp == NULL) { svcerr_auth(transp,AUTH_BADCRED); return(NULL); } for (i=0; i<MAXADDRS; i++) { if (chp->h_addr_list[i] == NULL) return(NULL); bcopy(chp->h_addr_list[i], &claim, sizeof(struct in_addr)); if (actual.sin_addr.s_addr == claim.s_addr) break; /* not an imposter */ if (i == (MAXADDRS - 1)) return(NULL); } if ((cp = strchr (hp->h_name, '.')) != NULL) { /* qualified name */ if (strcasecmp (cp+1, _res.defdname) != NULL) { /* * Not in local domain, check * if in subdomain */ if (subdomain_check) {#ifdef DEBUG (void) fprintf (stderr, "mountd: client, %s not local domain member, check if %s is a subdomain of %s\n", hp->h_name, cp+1, _res.defdname);#endif DEBUG if ((strfind (cp+1, _res.defdname)) == NULL) { syslog(LOG_ERR, "warning: (u)mount attempt from client %s, not a local subdomain member", hp->h_name); return (NULL); } } else { syslog(LOG_ERR, "warning: (u)mount attempt from client %s, not a local domain member", hp->h_name); return(NULL); } } } }#ifdef DEBUG (void) fprintf(stderr, "%s: end ipaddr_check successful\n", pgmname);#endif DEBUG return(hp);}/* * Check mount requests, add to mounted list if ok */mtd_mount(rqstp, transp) struct svc_req *rqstp; SVCXPRT *transp;{ fhandle_t fh; struct fhstatus fhs; char *path; int fd, anc_fd; struct mountdlist *ml; struct stat statbuf; struct exports *ex, *ex2, *ancestors[MAX_LEVELS]; struct exports *saveex = NULL; int found=0, success=0, bestposs=1, index, i; int first = 1; struct dupreq *dr; char *anc_name; char rpath[MAXPATHLEN]; struct hostent *client; struct sockaddr_in addr; if ((client = getclientsname(rqstp,transp))== NULL) { svcerr_weakauth(transp); return; } path = NULL; if (!svc_getargs(transp, xdr_path, &path)) { svcerr_decode(transp); mtd_abort(); return; }#ifdef DEBUG (void) fprintf(stderr, "path is %s\n", path);#endif if ((fd = open(path, O_RDONLY, 0)) < 0) { fhs.fhs_status = errno; perror("mountd: open"); goto done; } if (fstat(fd, &statbuf) < 0) { fhs.fhs_status = errno; perror("mountd: stat"); (void) close(fd); goto done; } /* * Now, before we spend a lot of time looking through the * exports list, lets check to see if we have already handed out * a filehandle to this requestor. . . */ addr = *svc_getcaller(transp); if (dr = dupcache_check(addr.sin_addr, statbuf.st_dev, statbuf.st_ino, statbuf.st_gennum)) { if ((anc_fd = open(dr->rc_ancname, O_RDONLY, 0)) < 0) { fhs.fhs_status = errno; perror("mountd: open"); goto done; } if (nfs_getfh(fd, anc_fd, &fh) < 0) { fhs.fhs_status = errno; syslog(LOG_ERR, "nfs_getfh: %m"); goto done; } fhs.fhs_status = 0; fhs.fhs_fh = fh; (void)close(anc_fd); goto done; } /* * Expand path into its canonical form, resolving symbolic link * and ../ components. */ if (realpath(path, rpath) == NULL) {#ifdef DEBUG perror("mountd"); (void)fprintf(stderr, "Realpath failed on %s\n", path);#endif DEBUG fhs.fhs_status = EACCES; goto done; } /* * Search exports list for a directory with an entry with the * same dev_t number. Search down that dev's list looking for * an exact match. If none found, look for entries that are * an ancestor of the requested path. Check the access on the * closest match. If access is not allowed, check the next * closest, ... until either no more exported ancestors exist * or an ancestor is found with allowable access for the client. * The export options used will be those on the ancestor found. */loop_search: for (ex = exports; ex != NULL; ex = ex->ex_devptr) {#ifdef DEBUG (void) fprintf(stderr, "checking %o for %o\n", ex->ex_dev, statbuf.st_dev);#endif if (ex->ex_dev == statbuf.st_dev) { for (ex2=ex; ex2 != NULL; ex2 = ex2->ex_next) {#ifdef DEBUG (void) fprintf(stderr, "checking %s with %s for exact match dir\n", ex2->ex_name, rpath);#endif if (strcmp(ex2->ex_name, rpath) == NULL) {#ifdef DEBUG (void) fprintf(stderr, "got exact match dir\n");#endif if (ex2->ex_groups == NULL) { success = 1; break; } else { if ((check_groups(ex2->ex_groups, client->h_name))!=NULL) { success = 1; break; } else { /* * Exact match found but requester * is not an allowable host. Break * to search for an ancestor match. */ saveex = ex; break; } } } } if (success) { if ((anc_fd = open(ex2->ex_name, O_RDONLY, 0)) < 0) { fhs.fhs_status = errno; perror("mountd: open"); goto done; } anc_name = ex2->ex_name; goto hit; } if (saveex != NULL) break; if (ex2 == NULL) { /* * Exact matches failed. * Break to best match search. */#ifdef DEBUG (void) fprintf(stderr,"exact match for %s failed\n", rpath);#endif saveex = ex; break; } } } if (!saveex) { if (first) { first = 0; exportstat.st_mtime--; set_exports(); goto loop_search; } else {#ifdef DEBUG (void) fprintf(stderr, "%s: filesystem %s not found\n", pgmname, rpath);#endif DEBUG fhs.fhs_status = EACCES; goto done; } } /* * Using pointer to directory exports record with same * dev_t number, try to find best match. */ ex = saveex; if (ex->ex_dev == statbuf.st_dev) { /* * initialize ancestors */ for (i=0; i< MAX_LEVELS; i++) ancestors[i] = NULL; for (ex2 = ex; ex2 != NULL; ex2 = ex2->ex_next) { if ((strcmp(ex2->ex_name, rpath) != NULL) && (index = path_check(ex2->ex_name, rpath)) > bestposs) {#ifdef DEBUG (void) fprintf(stderr, "ancestor: %s found, level:%d is > bestposs\n", ex2->ex_name, index);#endif found = 1; ancestors[index-2] = ex2; } else if (index == bestposs) {#ifdef DEBUG (void) fprintf(stderr, "best match %s found, checking access\n", ex2->ex_name);#endif if (ex2->ex_groups == NULL) { success = 1; break; } else { if ((check_groups(ex2->ex_groups, client->h_name)) != NULL) { success = 1; break; } else ++bestposs; } } } if (success) { if ((anc_fd = open(ex2->ex_name, O_RDONLY, 0)) < 0) { fhs.fhs_status = errno; perror("mountd: open"); goto done; } anc_name = ex2->ex_name; goto hit; } if (found) { for (i= ((bestposs==1)? 0:bestposs-2); i< MAX_LEVELS-1; i++) if (ancestors[i] != NULL) {#ifdef DEBUG (void) fprintf(stderr, "Checking ancestor: %s for allowable access\n", ancestors[i]->ex_name); #endif DEBUG if (ancestors[i]->ex_groups == NULL) { success = 1; break; } else { if ((check_groups(ancestors[i]->ex_groups, client->h_name)) != NULL) { success = 1; break; } } } if (success) { if ((anc_fd = open(ancestors[i]->ex_name, O_RDONLY, 0)) < 0) { fhs.fhs_status = errno; perror("mountd: open"); goto done; } anc_name = ancestors[i]->ex_name; goto hit; } } } fhs.fhs_status = EACCES; goto done; hit: if (nfs_getfh(fd, anc_fd, &fh) < 0) { fhs.fhs_status = errno; syslog(LOG_ERR, "nfs_getfh: %m"); (void)close(anc_fd); goto done; } fhs.fhs_status = 0; fhs.fhs_fh = fh; (void)close(anc_fd); /* * Now that we have a "New" mount request, lets tuck it into the * dupreq cache so that if the client retransmits, we can reply * with the filehandle immediately. */ dupcache_enter(addr.sin_addr, statbuf.st_dev, statbuf.st_ino, statbuf.st_gennum, anc_name);done:#ifdef DEBUG (void) fprintf(stderr, "*** ng cache and export list ***\n"); print_ngcache(); print_exports(exports);#endif DEBUG (void) close(fd); if (!svc_sendreply(transp, xdr_fhstatus, &fhs)) { syslog(LOG_ERR, "couldn't reply to MOUNT rpc call"); mtd_abort(); } else { for (ml = mountlist; ml != NULL; ml = ml->ml_nxt) { if (strcmp(ml->ml_path, rpath) == 0 && strcmp(ml->ml_name, client->h_name) == 0) break; } if (ml == NULL) { ml = (struct mountdlist *)exmalloc(sizeof(struct mountdlist)); ml->ml_path = (char *)exmalloc(strlen(rpath) + 1); (void) strcpy(ml->ml_path, rpath); ml->ml_name = (char *)exmalloc(strlen(client->h_name) + 1); (void) strcpy(ml->ml_name, client->h_name); ml->ml_nxt = mountlist; mountlist = ml; ml->ml_pos = rmtab_insert(client->h_name, rpath); } } svc_freeargs(transp, xdr_path, &path);}/* * Check if machine is in groups structure. If not, call YP. */check_groups(headgl, mach) struct groups *headgl; char *mach;{ struct groups *gl; int length; /* * first check for exact match on machine name */ for (gl = headgl; gl != NULL; gl = gl->g_next){ #ifdef DEBUG (void) fprintf(stderr, "checking machines: %s for %s\n", gl->g_name, mach);#endif if (strcasecmp(gl->g_name, mach) == 0) { gl->g_hbit = 1; return(TRUE); } else if (((length = local_hostname_length(mach)) != NULL) && (strlen(gl->g_name) == length) && (strncasecmp(gl->g_name, mach, length) == 0)) { gl->g_hbit = 1; return(TRUE); } } /* * now check netgroups */ for (gl = headgl; gl != NULL; gl = gl->g_next){ #ifdef DEBUG (void) fprintf(stderr, "checking innetgr: %s for %s\n", gl->g_name, mach);#endif if (gl->g_hbit) continue; if (innetgr_cache (gl->g_name, mach, &gl->g_hbit)) { return(TRUE); } } return(FALSE);}/* * Check the pathnames of the export name and the desired mount * pathname. */path_check(list_name, name) char *list_name, *name;{ char *ch1, *ch2; char *ch11, *ch22; char s1, s2; int done, level=0; char *index(); #ifdef DEBUG (void) fprintf(stderr, "path_check %s with %s\n", list_name, name);#endif if (!strcmp(list_name, "/")) return(TRUE); ch1 = list_name; ch2 = name; done = 0; while (!done) { if ((ch1 = goto_char(ch1)) != NULL) ch11 = index(ch1, '/'); if ((ch2 = goto_char(ch2)) != NULL) ch22 = index(ch2, '/'); if (ch11 && *ch11 != '\0') { s1 = *ch11; *ch11 = '\0'; ch11++; } if (ch22 && *ch22 != '\0') { s2 = *ch22; *ch22 = '\0'; ch22++; }
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?